libraries/madeleine_service.rb in Pimki-1.4.092 vs libraries/madeleine_service.rb in Pimki-1.5.092
- old
+ new
@@ -6,10 +6,12 @@
class MadeleineService
include Madeleine::Automatic::Interceptor
@@storage_path = self.name.downcase + "_storage"
+ automatic_read_only :snapshot_interval_hours, :take_snapshot, :clean_old_snapshots,
+ :restart, :request_stop
class << self
def storage_path
@@storage_path
end
@@ -17,52 +19,145 @@
def storage_path=(storage_path)
@@storage_path = storage_path
end
def instance
- @system = MadeleineServer.new(self).system if @system.nil?
+ if @system.nil?
+ @madeleine_server = MadeleineServer.new(self)
+ @system = @madeleine_server.system
+ end
@system
end
def restart
- MadeleineServer.clean_storage(self)
- @system = MadeleineServer.new(self).system
+ MadeleineServer.delete_storage(self)
+ @system = nil
+ instance
end
+
+ def clean_old_snapshots
+ instance
+ @madeleine_server.clean_storage(self)
+ end
+
+ def take_snapshot
+ instance
+ @madeleine_server.force_snapshot
+ end
+
+ def snapshot_interval_hours
+ instance
+ @madeleine_server.snapshot_interval.div MadeleineServer::ONE_HOUR rescue 1
+ end
+
+ def snapshot_interval_hours= hours
+ instance
+ @madeleine_server.snapshot_interval = hours.to_i * MadeleineServer::ONE_HOUR rescue MadeleineServer::ONE_HOUR
+ end
+
+ def request_stop
+ instance
+ @madeleine_server.request_stop
+ end
+
end
end
+require 'fileutils'
class MadeleineServer
- SNAPSHOT_INTERVAL = 30 * 60 * 24 # Each day
- AUTOMATIC_SNAPSHOTS = true
+ attr_reader :storage_path
+ attr_accessor :snapshot_interval
+
# Clears all the command_log and snapshot files located in the storage directory, so the
# database is essentially dropped and recreated as blank. Used in tests.
- def self.clean_storage(service)
- require 'fileutils'
+ def self.delete_storage(service)
if (File.directory?(service.storage_path))
FileUtils.rm_rf(Dir[service.storage_path + '/*.command_log'])
FileUtils.rm_rf(Dir[service.storage_path + '/*.snapshot'])
else
FileUtils.mkdir_p(service.storage_path)
end
end
+
+ def clean_storage(service)
+ force_snapshot
+ command_logs = Dir[service.storage_path + '/*.command_log']
+ raise 'Error: existing command_logs after snapshot' unless command_logs.empty?
+ snapshots = Dir[service.storage_path + '/*.snapshot']
+ FileUtils.rm_rf(snapshots.sort[0..-2])
+ end
+
+
def initialize(service)
+ @storage_path = service.storage_path
+ @snapshot_interval = ONE_HOUR
marshaller = Madeleine::ZMarshal.new()
@server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path,
marshaller) { service.new }
- start_snapshot_thread if AUTOMATIC_SNAPSHOTS
+ start_snapshot_thread
end
def system
@server.system
end
+ def command_log_present?
+ not Dir[storage_path + '/*.command_log'].empty?
+ end
+
+ def force_snapshot
+ begin
+ hours_since_last_snapshot = 0
+ @server.take_snapshot
+ rescue => e
+ sleep(ONE_MINUTE)
+ retry
+ end
+ end
+
+
+ ONE_MINUTE = 60
+ ONE_HOUR = ONE_MINUTE * 60
+ MAX_INTERVAL_HOURS = 24 * 2
+
def start_snapshot_thread
- Thread.new(@server) {
- while true
- sleep(SNAPSHOT_INTERVAL)
- @server.take_snapshot
+ @snapshot_thread = Thread.new(@server) {
+ hours_since_last_snapshot = 0
+ while not @request_stop
+ sleep(snapshot_interval)
+ hours_since_last_snapshot += snapshot_interval.div ONE_HOUR
+ begin
+ # Take a snapshot if there is a command log
+ if command_log_present? or hours_since_last_snapshot > MAX_INTERVAL_HOURS
+ # 'Taking a Madeleine snapshot'
+ @server.take_snapshot
+ hours_since_last_snapshot = 0
+ puts "[#{DateTime.now.strftime '%F %T'}] INFO Taking snapshot"
+ else
+ puts "[#{DateTime.now.strftime '%F %T'}] INFO Skipping snapshot (no command logs)"
+ end
+ rescue => e
+ # wait for a minute (not to spoof the log with the same error)
+ # and go back into the loop, to keep trying
+ sleep(ONE_MINUTE)
+ retry
+ end
end
}
end
+
+ def request_stop
+ begin
+ @request_stop = true
+ if @snapshot_thread and @snapshot_thread.alive?
+ @snapshot_thread.wakeup
+ @snapshot_thread.join
+ end
+ @server.take_snapshot if command_log_present?
+ rescue => detail
+ puts detail
+ end
+ end
+
end
\ No newline at end of file