[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