]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blobdiff - lib/rbot/registry.rb
registry: add in-memory implementation for tests
[user/henk/code/ruby/rbot.git] / lib / rbot / registry.rb
index 799e69ee4f0a72d9876b1257842dcd41b3915e84..61d4b33e02ef454d8cebcfb52617d53bc1f9eef0 100644 (file)
@@ -57,6 +57,15 @@ class Registry
     @libpath = File.join(File.dirname(__FILE__), 'registry')
     @format = format
     load File.join(@libpath, @format+'.rb') if format
+    # The get_impl method will return all implementations of the
+    # abstract accessor interface, since we only ever load one
+    # (the configured one) accessor implementation, we can just assume
+    # it to be the correct accessor to use.
+    accessors = AbstractAccessor.get_impl
+    if accessors.length > 1
+      warning 'multiple accessor implementations loaded!'
+    end
+    @accessor_class = accessors.first
   end
 
   # Returns a list of supported registry database formats.
@@ -68,12 +77,7 @@ class Registry
 
   # Creates a new Accessor object for the specified database filename.
   def create(path, filename)
-    # The get_impl method will return a list of all the classes that
-    # implement the accessor interface, since we only ever load one
-    # (the configured one) accessor implementation, we can just assume
-    # it to be the correct accessor to use.
-    cls = AbstractAccessor.get_impl.first
-    db = cls.new(File.join(path, 'registry_' + @format, filename.downcase))
+    db = @accessor_class.new(File.join(path, 'registry_' + @format, filename.downcase))
     db.optimize
     db
   end
@@ -83,26 +87,41 @@ class Registry
     @@formats ||= Registry.new.discover
   end
 
+  # Will detect tokyocabinet registry location: ~/.rbot/registry/*.tdb
+  #  and move it to its new location ~/.rbot/registry_tc/*.tdb
+  def migrate_registry_folder(path)
+    old_name = File.join(path, 'registry')
+    new_name = File.join(path, 'registry_tc')
+    if @format == 'tc' and File.exists?(old_name) and
+        not File.exists?(new_name) and
+        not Dir.glob(File.join(old_name, '*.tdb')).empty?
+      File.rename(old_name, new_name)
+    end
+  end
+
   # Abstract database accessor (a hash-like interface).
   class AbstractAccessor
 
+    attr_reader :filename
+
     # lets the user define a recovery procedure in case the Marshal
     # deserialization fails, it might be manually recover data.
     # NOTE: weird legacy stuff, used by markov plugin (WTH?)
     attr_accessor :recovery
 
     def initialize(filename)
-      debug 'init registry accessor for: ' + filename
+      debug "init registry accessor of #{self.class} for: #{filename}"
       @filename = filename
       @name = File.basename filename
       @registry = nil
       @default = nil
       @recovery = nil
+      @sub_registries = {}
     end
 
     def sub_registry(prefix)
       path = File.join(@filename.gsub(/\.[^\/\.]+$/,''), prefix.to_s)
-      return self.class.new(path)
+      @sub_registries[path] ||= self.class.new(path)
     end
 
     # creates the registry / subregistry folders
@@ -175,13 +194,13 @@ class Registry
     # Forces flush/sync the database on disk.
     def flush
       return unless @registry
-      @registry.flush
+      # if not supported by the database, close/reopen:
+      close
+      registry
     end
 
-    # Should optimize/vacuum the database.
+    # Should optimize/vacuum the database. (if supported)
     def optimize
-      return unless @registry
-      @registry.optimize
     end
 
     # Closes the database.
@@ -208,8 +227,8 @@ class Registry
     # like Hash#each
     def each(&block)
       return nil unless dbexists?
-      registry.each do |key|
-        block.call(key, self[key])
+      registry.each do |key, value|
+        block.call(key, restore(value))
       end
     end
 
@@ -254,9 +273,13 @@ class Registry
     end
 
     # delete a key from the registry
+    # returns the value in success, nil otherwise
     def delete(key)
       return default unless dbexists?
-      return registry.delete(key.to_s)
+      value = registry.delete(key.to_s)
+      if value
+        restore(value)
+      end
     end
 
     # returns a list of your keys
@@ -265,12 +288,6 @@ class Registry
       return registry.keys
     end
 
-    # just like Hash#has_both?
-    def has_both?(key, value)
-      return false unless dbexists?
-      registry.has_key?(key.to_s) and registry.has_value?(store(value))
-    end
-
     # Return an array of all associations [key, value] in your namespace
     def to_a
       return [] unless dbexists?
@@ -317,7 +334,7 @@ class Registry
 
     # Returns all classes from the namespace that implement this interface
     def self.get_impl
-      ObjectSpace.each_object(Class).select { |klass| klass < self }
+      ObjectSpace.each_object(Class).select { |klass| klass.ancestors[1] == self }
     end
   end