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