Using transactions with secondary indexes in bdb

I’m having trouble figuring out how to do transactions. I’m using db
4.5.40 from Oracle and bdb 0.6.0. Here’s a code snippet:

require ‘bdb’

BDB::Hash.open(‘models.db’, nil, BDB::TRUNCATE) {}
BDB::Hash.open(‘makes.db’, nil, BDB::TRUNCATE) {}

BDB::Env.open(‘db’, BDB::CREATE | BDB::INIT_TRANSACTION) do |env|
models = makes = nil
env.begin(BDB::TXN_COMMIT) do |tx|
models = tx.open_db(BDB::HASH, ‘models.db’, nil, BDB::CREATE)
makes = tx.open_db(BDB::HASH, ‘makes.db’, nil, BDB::CREATE |
BDB::DUPSORT)
models.associate(makes) { |sdb, key, value| value }
end

env.begin(BDB::TXN_COMMIT) do |tx|
tx.assoc(models, makes)
puts ‘===== Before’
puts ‘----- models’
models.each { |key, value| puts “#{key} = #{value}” }
puts ‘----- makes’
makes.each { |key, value| puts “#{key} = #{value}” }
end

env.begin(BDB::TXN_COMMIT) do |tx|
tx.assoc(models, makes)
models[‘Civic’] = ‘Honda’
models[‘Accord’] = ‘Honda’ # this is line 26 where the error is
occurring
models[‘S2000’] = ‘Honda’
models[‘Camry’] = ‘Toyota’
models[‘Solara’] = ‘Toyota’
end

env.begin do |tx|
tx.assoc(models, makes)
puts ‘===== After’
puts ‘----- models’
models.each { |key, value| puts “#{key} = #{value}” }
puts ‘----- makes’
makes.each { |key, value| puts “#{key} = #{value}” }
end

makes.close
models.close
end

Now I have no idea if I’m using transactions properly, not to mention
any of the other various features, but I suspect I’m not since I get
this output:

===== Before
----- models
----- makes
/home/jim/eclipse/testRuby/test.rb:26:in close': BUG : current_env not set (BDB::Fatal) from /home/jim/eclipse/testRuby/test.rb:26:inopen’
from /home/jim/eclipse/testRuby/test.rb:6
/home/jim/eclipse/testRuby/test.rb:26: [BUG] Segmentation fault
ruby 1.8.5 (2007-03-13) [i386-linux]

I would greatly appreciate any help that anyone can provide.

Cheers,
Jim

OK, I figured out that a lot of my previous code was wrong, not even
considering the transactions, so I removed the transactional stuff and
got down to this:

require ‘bdb’

BDB::Hash.open(‘models.db’, nil, BDB::CREATE | BDB::TRUNCATE) {}
BDB::Hash.open(‘makes.db’, nil, BDB::CREATE | BDB::TRUNCATE,
:set_flags => BDB::DUP | BDB::DUPSORT) {}

BDB::Hash.open(‘models.db’, nil, BDB::CREATE) do |models|
BDB::Hash.open(‘makes.db’, nil, BDB::CREATE, :set_flags => BDB::DUP
| BDB::DUPSORT) do |makes|
models.associate(makes) { |sdb, key, value| value }

puts '===== Before'
puts '----- models'
models.each { |key, value| puts "#{key} = #{value}" }
puts '----- makes'
makes.each_primary { |skey, pkey, pvalue| p [skey, pkey, pvalue] }

models['Civic'] = 'Honda'
models['Accord'] = 'Honda'
models['S2000'] = 'Honda'
models['Camry'] = 'Toyota'
models['Solara'] = 'Toyota'

puts '===== After'
puts '----- models'
models.each { |key, value| puts "#{key} = #{value}" }
puts '----- makes'
makes.each_primary { |skey, pkey, pvalue| p [skey, pkey, pvalue] }

end
end

And here is the output, which looks right to me:

===== Before
----- models
----- makes
===== After
----- models
Civic = Honda
Accord = Honda
Camry = Toyota
Solara = Toyota
S2000 = Honda
----- makes
[“Honda”, “Accord”, “Honda”]
[“Honda”, “Civic”, “Honda”]
[“Honda”, “S2000”, “Honda”]
[“Toyota”, “Camry”, “Toyota”]
[“Toyota”, “Solara”, “Toyota”]

Now I just have to figure out the transactional part. I’ll follow up
on the list once I do.

Cheers,
Jim

On Tue, 3 Apr 2007, Jim Cain wrote:

BDB::Hash.open(‘models.db’, nil, BDB::CREATE) do |models|
models[‘Civic’] = ‘Honda’
end
Accord = Honda
Now I just have to figure out the transactional part. I’ll follow up
on the list once I do.

there are transaction examples in the bdb src - have you looked at that?

-a

On 4/2/07, [email protected] [email protected] wrote:

there are transaction examples in the bdb src - have you looked at that?

I looked at the one example file “txn.rb” originally, but I didn’t put
it all together then. Upon a second look, it’s making a bit more
sense. In that example, he has:

module BDB
class ThreadHash < Hash
def start(val, num)
Thread.start do
self.env.begin(self) do |txn, b1|
b1.delete_if do |k, v|
print “\t#{num} #{k} – #{v}\n”
k == val
end
p “Thread #{num} Pass”
Thread.pass
b1.each do |k, v|
print “\t#{num} #{k} – #{v}\n”
end
if num == 1
txn.abort
else
txn.commit
end
end
p “End Thread #{num}”
end
end
end
end

And then later on he calls #start for each ThreadHash object. I
suppose the business part of that is:

self.env.begin(self) do |txn, b1|

end

So he’s passing in the ThreadHash object as the only argument to
#begin, but the docs have this for Env#begin:

begin(flags = 0, db, …) { |txn, db, …| …}

This says that “flags” is the first argument. Maybe that’s where my
confusion started.

Cheers,
Jim

I’ve updated my previous example to include transactions:

BDB::Hash.open(‘models.db’, nil, BDB::CREATE | BDB::TRUNCATE) {}
BDB::Hash.open(‘makes.db’, nil, BDB::CREATE | BDB::TRUNCATE,
:set_flags => BDB::DUP | BDB::DUPSORT) {}

env = BDB::Env.new(’/home/jim/eclipse/testRuby’,
BDB::CREATE|BDB::INIT_TRANSACTION)
models = env.open_db(BDB::HASH, ‘models.db’, nil, BDB::CREATE)
makes = env.open_db(BDB::HASH, ‘makes.db’, nil, BDB::CREATE,
:set_flags => BDB::DUP | BDB::DUPSORT)

env.begin(models, makes) do |tx, tx_models, tx_makes|
tx_models.associate(tx_makes) { |sdb, key, value| value }
tx.commit
end

puts ‘===== Before’
puts ‘----- models’
models.each { |key, value| puts “#{key} = #{value}” }
puts ‘----- makes’
makes.each_primary { |skey, pkey, pvalue| p [skey, pkey, pvalue] }

env.begin(BDB::TXN_COMMIT, models, makes) do |tx, tx_models, tx_makes|
tx_models[‘Civic’] = ‘Honda’
tx_models[‘Accord’] = ‘Honda’
tx_models[‘S2000’] = ‘Honda’
tx_models[‘Camry’] = ‘Toyota’
tx_models[‘Solara’] = ‘Toyota’
end

env.begin(models, makes) do |tx, tx_models, tx_makes|
puts ‘===== After’
puts ‘----- models’
tx_models.each { |key, value| puts “#{key} = #{value}” }
puts ‘----- makes’
tx_makes.each_primary { |skey, pkey, pvalue| p [skey, pkey, pvalue]
}
end

env.begin(BDB::TXN_COMMIT, models, makes) do |tx, tx_models, tx_makes|
tx_makes.close
tx_models.close
end

env.close

Here is the output:

===== Before
----- models
----- makes
===== After
----- models
Civic = Honda
Accord = Honda
Camry = Toyota
Solara = Toyota
S2000 = Honda
----- makes

It doesn’t appear to be updating the secondary index. What have I done
wrong?

Cheers,
Jim