[Archipelago-submits] [227] trunk/archipelago/lib/archipelago: created a trial Dump backed hashish.

nobody at rubyforge.org nobody at rubyforge.org
Tue Mar 6 11:44:42 EST 2007


Revision: 227
Author:   zond
Date:     2007-03-06 11:44:42 -0500 (Tue, 06 Mar 2007)

Log Message:
-----------
created a trial Dump backed hashish. made treasure smarter when selecting hashish

Modified Paths:
--------------
    trunk/archipelago/lib/archipelago/hashish.rb
    trunk/archipelago/lib/archipelago/treasure.rb

Modified: trunk/archipelago/lib/archipelago/hashish.rb
===================================================================
--- trunk/archipelago/lib/archipelago/hashish.rb	2007-03-06 15:49:26 UTC (rev 226)
+++ trunk/archipelago/lib/archipelago/hashish.rb	2007-03-06 16:44:42 UTC (rev 227)
@@ -25,7 +25,15 @@
   #
   module Hashish
 
+    #
+    # In essence a persistence backed Hash.
+    #
+    # Will cache everything including timestamps for last
+    # modification in normal Hashes, but keep everything stored
+    # in a persistency backer defined by the subclass.
+    #
     module CachedHashish
+      include Archipelago::Current::Synchronized
       #
       # Returns true if what +key+ points to is no longer +value+.
       #
@@ -40,8 +48,11 @@
       end
       #
       # Actually writes +key+ serialized as +serialized_key+ an
-      # +serialized_value+ to the db. Used by <b>write_to_db</b>.
+      # +serialized_value+ to the db, and a new timestamp to the 
+      # timestamp db, and the same timestamp to the @timestamp attribute.
       #
+      # Used by <b>write_to_db</b>.
+      #
       def do_write_to_db(key, serialized_key, serialized_value)
         raise "You have to implement me!"
       end
@@ -69,7 +80,6 @@
       def do_delete_from_persistence(serialized_key)
         raise "You have to implement me!"
       end
-      
       #
       # Will do +callable+.call(key, value) for each
       # key-and-value pair in this Hashish.
@@ -237,25 +247,68 @@
           old_serialized_value = do_get_from_db(serialized_key)
           old_value = old_serialized_value ? Marshal.load(old_serialized_value) : nil
           value.save_hook(old_value) do
-            do_write_to_db(key, serialized_key, serialized_value)            
+            now = Time.now
+            do_write_to_db(key, serialized_key, serialized_value, now)
+            @timestamps[key] = now
           end
         else
-          do_write_to_db(key, serialized_key, serialized_value)
+          now = Time.now
+          do_write_to_db(key, serialized_key, serialized_value, now)
+          @timestamps[key] = now
         end
       end
     end
 
     #
-    # In essence a Berkeley Database backed Hash.
+    # An Archipelago::Dump network backed CachedHashish.
     #
-    # Will cache all values having been written or read
-    # in a normal Hash cache for fast access.
+    class DumpHashish
+      include Archipelago::Hashish::CachedHashish
+      #
+      # Initialize a new DumpHashish with the given +officer+ to find Dumps.
+      #
+      def initialize(officer)
+        super()
+        initialize_cached_hashish
+        @officer = officer
+        @hash_by_key = {}
+      end
+      def changed?(key, value)
+        return (old_hash = @hash_by_key[Marshal.dump(key)]) && old_hash != Digest::SHA1.hexdigest(Marshal.dump(value))
+      end
+      def do_get_timestamp_from_db(serialized_key)
+        return @officer[officer_key(serialized_key, "timestamp")]
+      end
+      def do_write_to_db(key, serialized_key, serialized_value, now)
+        @officer[officer_key(serialized_key, "content")] = serialized_value
+        @officer[officer_key(serialized_key, "timestamp")] = Marshal.dump(now)
+        @hash_by_key[serialized_key] = Digest::SHA1.hexdigest(serialized_value)
+      end
+      def close!
+      end
+      def officer_key(serialized_key, space)
+        Digest::SHA1.hexdigest("DumpHashish:#{space}:#{serialized_key}")
+      end
+      def db_include?(key)
+        return !@officer[officer_key(Marshal.dump(key), "content")].nil?
+      end
+      def do_get_from_db(serialized_key)
+        return @officer[officer_key(Marshal.dump(key), "content")]
+      end
+      def do_delete_from_persistence(serialized_key)
+        @officer.delete(officer_key(serialized_key, "content"))
+        @officer.delete(officer_key(serialized_key, "timestamp"))
+        @hash_by_key[serialized_key] = Digest::SHA1.hexdigest(serialized_value)
+      end
+      def each(callable)
+        raise "You have to implement me!"
+      end
+    end
+
     #
-    # Will save the last update timestamp for all keys
-    # in a separate Hash cache AND a separate Berkeley Database.
+    # A CachedHashish backed by a few BDB::Hashes.
     #
     class BerkeleyHashish
-      include Archipelago::Current::Synchronized
       include Archipelago::Hashish::CachedHashish
       #
       # Initialize an instance with the +name+ and BDB::Env +env+.
@@ -266,80 +319,39 @@
         @content_db = env.open_db(BDB::HASH, name, "content", BDB::CREATE)
         @timestamps_db = env.open_db(BDB::HASH, name, "timestamps", BDB::CREATE | BDB::NOMMAP)
       end
-      #
-      # Close the @content_db and @timestamps_db behind this BerkeleyHashish
-      #
       def close!
         @content_db.close
         @timestamps_db.close
       end
-      #
-      # Will do +callable+.call(key, value) for each
-      # key-and-value pair in this Hashish.
-      #
-      # NB: This is totaly thread-unsafe, only do this
-      # for management or rescue!
-      #
       def each(callable)
         @content_db.each do |serialized_key, serialized_value|
           key = Marshal.load(serialized_key)
           callable.call(key, self.[](key))
         end
       end
-
-      private
-
-      #
-      # Get the serialized timestamp for +serialized_key+ from the persistent backer.
-      #
       def do_get_timestamp_from_db(serialized_key)
         return @timestamps_db[serialized_key]
       end
-
-      #
-      # Actually deletes +serialized_key+ from the persistent backer.
-      #
       def do_delete_from_persistence(serialized_key)
-          @timestamps_db[serialized_key] = nil
-          @content_db[serialized_key] = nil
+        @timestamps_db[serialized_key] = nil
+        @content_db[serialized_key] = nil
       end
-      
-      #
-      # Returns true if what +key+ points to is no longer +value+.
-      #
       def changed?(key, value)
         serialized_value = Marshal.dump(value)
         serialized_key = Marshal.dump(key)
         old_serialized_value = @content_db[serialized_key]
         return old_serialized_value && old_serialized_value != serialized_value
       end
-
-      #
-      # Actually writes +key+ serialized as +serialized_key+ an
-      # +serialized_value+ to the db. Used by <b>write_to_db</b>.
-      #
-      def do_write_to_db(key, serialized_key, serialized_value)
-        now = Time.now
-
+      def do_write_to_db(key, serialized_key, serialized_value, now)
         @content_db[serialized_key] = serialized_value
         @timestamps_db[serialized_key] = Marshal.dump(now)
-        @timestamps[key] = now
       end
-
-      #
-      # Returns whether the persistent backer contains +key+.
-      #
       def db_include?(key)
         return !@content_db[Marshal.dump(key)].nil?
       end
-      
-      #
-      # Will perform an actual fetching of +serialized_key+ from the persistent backer.
-      #
       def do_get_from_db(serialized_key)
         return @content_db[serialized_key]
       end
-
     end
 
     #
@@ -356,23 +368,17 @@
         @berkeley_hashishes = []
         @bdb_dbs = []
       end
-      #
-      # Returns a cleverly cached (but slightly inefficient)
-      # hash-like instance (see Archipelago::Hashish::BerkeleyHashish)
-      # using +name+.
-      #
       def get_cached_hashish(options)
         if options[:officer]
-        else
+          hashish = DumpHashish.new(options[:officer])
+          @berkeley_hashishes << hashish
+          return hashish
+        elsif options[:name]
           hashish = BerkeleyHashish.new(options[:name], @env)
           @berkeley_hashishes << hashish
           return hashish
         end
       end
-      #
-      # Returns something acting like a Berkeley Btree DB instance allowing duplicate entries
-      # and transactions using +name+.
-      #
       def get_dup_tree(name, flags = BDB::CREATE | BDB::NOMMAP)
         db = BDB::Btree.open(Pathname.new(File.join(@env.home, name)).expand_path, 
                             nil, 
@@ -383,17 +389,11 @@
         @bdb_dbs << db
         return db
       end
-      #
-      # Returns something acting like a Berkeley Hash DB instance using +name+.
-      #
       def get_hashish(name, flags = BDB::CREATE | BDB::NOMMAP)
         db = @env.open_db(BDB::HASH, name, nil, flags)
         @bdb_dbs << db
         return db
       end
-      #
-      # Closes databases opened by this instance.
-      #
       def close!
         @berkeley_hashishes.each do |h|
           h.close!
@@ -402,9 +402,6 @@
           d.close
         end
       end
-      #
-      # Closes databases opened by this instance and removes the persistent files.
-      #
       def unlink!
         close!
         home = Pathname.new(@env.home).expand_path

Modified: trunk/archipelago/lib/archipelago/treasure.rb
===================================================================
--- trunk/archipelago/lib/archipelago/treasure.rb	2007-03-06 15:49:26 UTC (rev 226)
+++ trunk/archipelago/lib/archipelago/treasure.rb	2007-03-06 16:44:42 UTC (rev 227)
@@ -288,7 +288,11 @@
         # The magical persistent map that defines how we actually 
         # store our data.
         #
-        @db = @persistence_provider.get_cached_hashish(:name => "db", :officer => options[:officer] || nil)
+        if options[:officer]
+          @db = @persistence_provider.get_cached_hashish(:officer => options[:officer])
+        else
+          @db = @persistence_provider.get_cached_hashish(:name => "db")
+        end
 
         initialize_prepared(options[:transaction_recovery_interval] || TRANSACTION_RECOVERY_INTERVAL)
 




More information about the Archipelago-submits mailing list