diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d964a1f..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -pkg -*.gem -*.gemspec -rdoc -*.rbc diff --git a/README.md b/README.md index 7459cc5..67ed7aa 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ Dependencies ============ -You need first the [Bdb](http://github.com/ruby-bdb/bdb) and of course [ruby](http://ruby-lang.org). +You need first the [Bdb](http://github.com/DenisKnauf/bdb) and of course [ruby](http://ruby-lang.org). Download ======== via git: - git clone git://github.com/ruby-bdb/sbdb + git clone git://github.com/DenisKnauf/sbdb.git Install ======= @@ -23,22 +23,21 @@ First, open environment and database require 'sbdb' Dir.mkdir 'newenv' rescue Errno::EEXIST - env = SBDB::Env.new 'newenv', SBDB::CREATE | SBDB::Env::INIT_TRANSACTION - db = env.btree 'newdb.db', :flags => SBDB::CREATE + env = SBDB::Env.new 'newenv', SBDB::CREATE + db = env.open SBDB::Btree, 'newdb.db', :flags => SBDB::CREATE It works nearly like a Ruby-Hash: db['key'] = 'value' - db['key'] # => 'value' - db.to_hash # => {'key'=>'value'} - db.map {|k, v| "k => v" } # => ["key => value"] - db.count # => 1 - db.each {|k,v| puts "#{k}: #{v}" } + db['key'] # => 'value' + db.to_hash # => {'key'=>'value'} + db.map {|k, v| [k, v].join ' => '} # => ["key => value"] + db.count # => 1 -`SBDB::DB#each` uses a `SBDB::Cursor`: +SBDB::DB#each uses a SBDB::Cursor: cursor = db.cursor - cursor.each {|k,v| puts "#{k}: #{v}" } + cursor.each {|k,v| puts "#{k}: ${v}" } **Don't forget to close everything, you've opened!** @@ -48,14 +47,10 @@ It works nearly like a Ruby-Hash: But you can use a *lambda* to ensure to close everything: - SBDB::Env.new( 'newenv', SBDB::CREATE | SBDB::Env::INIT_TRANSACTION) do |env| + SBDB::Env.new( 'newenv', SBDB::CREATE) do |env| env.open SBDB::Btree, 'newdb.db', :flags => SBDB::CREATE do |db| db.to_hash end end -`SBDB::DB#to_hash` creates a cursor and close it later. - -Tip: - - Signal.trap 'EXIT', env.method( :close) +SBDB::DB#to_hash creates a cursor and close it later. diff --git a/Rakefile b/Rakefile index 89416e7..2804098 100644 --- a/Rakefile +++ b/Rakefile @@ -10,12 +10,11 @@ begin gem.summary = %Q{Simple Ruby Berkeley DB} gem.description = %Q{Simple Ruby Berkeley DB wrapper library for bdb.} gem.email = "Denis.Knauf@gmail.com" - gem.homepage = "http://github.com/ruby-bdb/sbdb" + gem.homepage = "http://github.com/DenisKnauf/bdb" gem.authors = ["Denis Knauf"] gem.files = %w[AUTHORS README.md VERSION lib/**/*.rb test/**/*.rb] gem.require_paths = %w[lib] - gem.add_dependency 'bdb', '>= 0.2.6.5' - gem.add_dependency 'ref' + gem.add_dependency 'dk-bdb' end Jeweler::GemcutterTasks.new rescue LoadError diff --git a/VERSION b/VERSION index 7e743eb..7c1886b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.12.2 \ No newline at end of file +0.0.10 diff --git a/lib/sbdb.rb b/lib/sbdb.rb index 2b3ab6f..d796a06 100644 --- a/lib/sbdb.rb +++ b/lib/sbdb.rb @@ -1,5 +1,4 @@ require 'bdb' -require 'ref' require 'sbdb/environment' require 'sbdb/db' require 'sbdb/cursor' diff --git a/lib/sbdb/db.rb b/lib/sbdb/db.rb index 2a0d04a..2da1a94 100644 --- a/lib/sbdb/db.rb +++ b/lib/sbdb/db.rb @@ -60,11 +60,7 @@ module SBDB def _txn txn txn ||= @txn - txn && txn.bdb_object - end - - def transaction flg = nil, &exe - block_given? ? home.transaction( flg, &exe) : home.transaction( flg) + txn && t.bdb_object end # Arguments: diff --git a/lib/sbdb/environment.rb b/lib/sbdb/environment.rb index 71f5ef9..9a6479e 100644 --- a/lib/sbdb/environment.rb +++ b/lib/sbdb/environment.rb @@ -1,4 +1,5 @@ require 'bdb' +require 'sbdb/weakhash' require 'sbdb/db' require 'sbdb/transaction' @@ -60,7 +61,7 @@ module SBDB def initialize *args opts = ::Hash === args.last ? args.pop : {} opts = {:dir => args[0], :flags => args[1], :mode => args[2]}.update opts - @dbs, @env = Ref::WeakValueMap.new, Bdb::Env.new( 0) + @dbs, @env = WeakHash.new, Bdb::Env.new( 0) @env.log_config opts[:log_config], 1 if opts[:log_config] @env.lg_bsize = opts[:lg_bsize] if opts[:lg_bsize] @env.lg_max = opts[:lg_max] if opts[:lg_max] diff --git a/lib/sbdb/weakhash.rb b/lib/sbdb/weakhash.rb new file mode 100644 index 0000000..f6e9d9c --- /dev/null +++ b/lib/sbdb/weakhash.rb @@ -0,0 +1,61 @@ +module SBDB + +# See http://eigenclass.org/hiki/deferred-finalizers-in-Ruby +# Not threadsafe. + +class WeakHash + attr_reader :cache + def initialize cache = ::Hash.new + @cache = cache + @key_map = {} + @rev_cache = ::Hash.new{|h,k| h[k] = {}} + @reclaim_value = lambda do |value_id| + if @rev_cache.has_key? value_id + @rev_cache[value_id].each_key{|key| @cache.delete key} + @rev_cache.delete value_id + end + end + @reclaim_key = lambda do |key_id| + @cache.delete @key_map.delete(key_id) if @key_map.has_key? key_id + end + end + + def []= key, value + case key + when Fixnum, Symbol, true, false + key2 = key + else + key2 = key.dup + end + @rev_cache[value.object_id][key2] = true + @cache[key2] = value.object_id + @key_map[key.object_id] = key2 + + ObjectSpace.define_finalizer(value, @reclaim_value) + ObjectSpace.define_finalizer(key, @reclaim_key) + value + end + + def [] key + value_id = @cache[key] + return ObjectSpace._id2ref( value_id) unless value_id.nil? + nil + rescue RangeError + nil + end + + def each &e + @cache.each do |k, vid| + unless vid.nil? + obj = begin + ObjectSpace._id2ref vid + rescue RangeError + next + end + yield k, obj + end + end + end +end + +end diff --git a/sbdb.gemspec b/sbdb.gemspec new file mode 100644 index 0000000..612d59b --- /dev/null +++ b/sbdb.gemspec @@ -0,0 +1,48 @@ +# Generated by jeweler +# DO NOT EDIT THIS FILE DIRECTLY +# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{sbdb} + s.version = "0.0.10" + + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= + s.authors = ["Denis Knauf"] + s.date = %q{2011-08-01} + s.description = %q{Simple Ruby Berkeley DB wrapper library for bdb.} + s.email = %q{Denis.Knauf@gmail.com} + s.extra_rdoc_files = [ + "LICENSE", + "README.md" + ] + s.files = [ + "AUTHORS", + "README.md", + "VERSION", + "lib/sbdb.rb", + "lib/sbdb/cursor.rb", + "lib/sbdb/db.rb", + "lib/sbdb/environment.rb", + "lib/sbdb/transaction.rb", + "lib/sbdb/weakhash.rb" + ] + s.homepage = %q{http://github.com/DenisKnauf/bdb} + s.require_paths = ["lib"] + s.rubygems_version = %q{1.3.7} + s.summary = %q{Simple Ruby Berkeley DB} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [">= 0"]) + else + s.add_dependency(%q, [">= 0"]) + end + else + s.add_dependency(%q, [">= 0"]) + end +end +