ninjudd-bdb 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/bdb.h ADDED
@@ -0,0 +1,104 @@
1
+
2
+ #ifndef BDB2_H
3
+ #define BDB2_H
4
+
5
+ #include <ruby.h>
6
+
7
+ #ifdef stat
8
+ #undef stat
9
+ #endif
10
+
11
+ #ifdef close
12
+ #undef close
13
+ #endif
14
+
15
+ #ifdef rename
16
+ #undef rename
17
+ #endif
18
+
19
+ #include <version.h>
20
+ #include <db.h>
21
+
22
+ #define NOTXN NULL
23
+
24
+ #ifdef OPEN_MAX
25
+ #define LMAXFD OPEN_MAX
26
+ #else
27
+ #ifdef FOPEN_MAX
28
+ #define LMAXFD FOPEN_MAX
29
+ #endif
30
+ #endif
31
+ #ifndef LMAXFD
32
+ #error "No max fd define available."
33
+ #endif
34
+
35
+ #define FNLEN 40
36
+
37
+ #define filename_copy(fp,fv) \
38
+ strncpy(fp,RSTRING_PTR(fv),FNLEN);
39
+
40
+ #define filename_dup(fpd,fps) \
41
+ strncpy(fpd,fps,FNLEN);
42
+
43
+ typedef struct s_envh {
44
+ VALUE self;
45
+ DB_ENV *env;
46
+ VALUE adb; /* Ruby array holding opened databases */
47
+ VALUE atxn; /* Ruby array holding open transactions */
48
+ } t_envh;
49
+
50
+ typedef struct s_dbh {
51
+ VALUE self;
52
+ DB *db;
53
+ int db_opened;
54
+ VALUE aproc;
55
+ VALUE sproc; /* key sorting callback */
56
+
57
+ t_envh *env; /* Parent environment, NULL if not opened from one */
58
+ VALUE adbc; /* Ruby array holding opened cursor */
59
+ char filename[FNLEN+1];
60
+ } t_dbh;
61
+
62
+ typedef struct s_dbch {
63
+ VALUE self;
64
+ DBC *dbc;
65
+ t_dbh *db;
66
+ char filename[FNLEN+1];
67
+ } t_dbch;
68
+
69
+ typedef struct s_txnh {
70
+ VALUE self;
71
+ DB_TXN *txn;
72
+ t_envh *env;
73
+ } t_txnh;
74
+
75
+ #define cu(b,m) \
76
+ rb_define_const(b,#m,UINT2NUM(m))
77
+
78
+ #define ci(b,m) \
79
+ rb_define_const(b,#m,INT2NUM(m))
80
+
81
+ #define cs(b,m) \
82
+ rb_define_const(b,#m,rb_str_new2(m))
83
+
84
+ #define simple_set(fname) \
85
+ VALUE db_ ## fname ## _eq(VALUE obj, VALUE v) \
86
+ { \
87
+ rb_ivar_set(obj,fv_ ## fname,v); \
88
+ return obj; \
89
+ }
90
+
91
+ #define attr_writer(fname) \
92
+ VALUE fname ## _writer(VALUE obj, VALUE v) \
93
+ { \
94
+ rb_ivar_set(obj,fv_ ## fname,v); \
95
+ return obj; \
96
+ }
97
+
98
+ #define attr_reader(fname) \
99
+ VALUE fname ## _reader(VALUE obj) \
100
+ { \
101
+ return rb_ivar_get(obj,fv_ ## fname); \
102
+ }
103
+
104
+ #endif
data/ext/extconf.rb ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mkmf'
3
+
4
+ inc, lib = dir_config('db')
5
+
6
+ # OS X compatibility
7
+ if(PLATFORM =~ /darwin/) then
8
+ # test if Bdb is probably universal
9
+
10
+ filetype = (IO.popen("file #{inc}/../db_dump").readline.chomp rescue nil)
11
+ # if it's not universal, ARCHFLAGS should be set
12
+ if((filetype !~ /universal binary/) && ENV['ARCHFLAGS'].nil?) then
13
+ arch = (IO.popen("uname -m").readline.chomp rescue nil)
14
+ $stderr.write %{
15
+ =========== WARNING ===========
16
+
17
+ You are building this extension on OS X without setting the
18
+ ARCHFLAGS environment variable, and BerkeleyDB does not appear
19
+ to have been built as a universal binary. If you are seeing this
20
+ message, that means that the build will probably fail.
21
+
22
+ Try setting the environment variable ARCHFLAGS
23
+ to '-arch #{arch}' before building.
24
+
25
+ For example:
26
+ (in bash) $ export ARCHFLAGS='-arch #{arch}'
27
+ (in tcsh) % setenv ARCHFLAGS '-arch #{arch}'
28
+
29
+ Then try building again.
30
+
31
+ ===================================
32
+
33
+ }
34
+ # We don't exit here. Who knows? It might build.
35
+ end
36
+ end
37
+
38
+ versions=%w(db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2)
39
+ until versions.empty?
40
+ (lib_ok = have_library(versions.shift,'db_version', 'db.h')) && break
41
+ end
42
+
43
+ def create_header
44
+ if File.exist?("bdb_aux._c")
45
+ message("Not writing bdb_aux._c (defines), already exists\n")
46
+ return
47
+ end
48
+
49
+ message("Writing bdb_aux._c (defines), this takes a while\n")
50
+ db_header = $CPPFLAGS.split.select { |f| f =~ /^-I/ }.map { |e|
51
+ f = File.join(e[2..-1], 'db.h')
52
+ File.exists?(f) ? f : nil
53
+ }.select { |e| e }.first
54
+
55
+ n=0
56
+ defines=[]
57
+ File.open(db_header) {|fd|
58
+ File.open("bdb_aux._c","w") {|hd|
59
+ hd.puts("/* This file automatically generated by extconf.rb */\n")
60
+ fd.each_line {|l|
61
+ if l =~ %r{^#define\s+(DBC?_\w*)\s+([^\/]*)\s*(.*?)(\/\*.*)?$}
62
+ name = $1
63
+ value = $2
64
+ if macro_defined?(name,"#include <db.h>")
65
+ case value
66
+ when /^"/
67
+ hd.print(%Q{cs(mBdb,%s);\n}%[name])
68
+ when /^\(?(0x|\d)/
69
+ hd.print(%Q{cu(mBdb,%s);\n}%[name])
70
+ when /^\(?-/
71
+ hd.print(%Q{ci(mBdb,%s);\n}%[name])
72
+ else
73
+ $stderr.puts "don't know how to handle #{name} #{value.strip}, guessing UINT"
74
+ hd.print(%Q{cu(mBdb,%s);\n}%[name])
75
+ end
76
+ n+=1
77
+ end
78
+ end
79
+ }
80
+ }
81
+ message("\nwrote #{n} defines\n")
82
+ }
83
+ end
84
+
85
+ if lib_ok
86
+ create_header
87
+ create_makefile('bdb')
88
+ else
89
+ $stderr.puts("cannot create Makefile")
90
+ exit 1
91
+ end
@@ -0,0 +1,150 @@
1
+ require 'test_helper'
2
+
3
+ class CursorTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ mkdir File.join(File.dirname(__FILE__), 'tmp')
7
+ @db = Bdb::Db.new
8
+ @db.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
9
+ 10.times { |i| @db.put(nil, i.to_s, "data-#{i}", 0)}
10
+ @cursor = @db.cursor(nil, 0)
11
+ end
12
+
13
+ def teardown
14
+ @cursor.close if @cursor
15
+ assert(@db.close(0)) if @db
16
+ rm_rf File.join(File.dirname(__FILE__), 'tmp')
17
+ end
18
+
19
+ def test_get
20
+ key, value = @cursor.get(nil, nil, Bdb::DB_FIRST)
21
+ assert_equal '0', key
22
+ assert_equal 'data-0', value
23
+ end
24
+
25
+ def test_get_range
26
+ keys = []
27
+ key, value = @cursor.get("4", nil, Bdb::DB_SET_RANGE)
28
+ while key and key <= "9"
29
+ keys << key
30
+ key, value = @cursor.get(nil, nil, Bdb::DB_NEXT)
31
+ end
32
+
33
+ assert_equal (4..9).collect {|i| i.to_s}, keys
34
+ end
35
+
36
+ def test_pget
37
+ @db1 = Bdb::Db.new
38
+ @db1.flags = Bdb::DB_DUPSORT
39
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test1.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
40
+
41
+ @db.associate(nil, @db1, 0, proc { |sdb, key, data| key.split('-')[0] })
42
+
43
+ @db.put(nil, '1234-5678', 'data', 0)
44
+ @db.put(nil, '5678-1234', 'atad', 0)
45
+
46
+ @cursor1 = @db1.cursor(nil, 0)
47
+ key, pkey, value = @cursor1.pget(nil, nil, Bdb::DB_FIRST)
48
+ assert_equal '1234', key
49
+ assert_equal '1234-5678', pkey
50
+ assert_equal 'data', value
51
+
52
+ @cursor1.close
53
+ @db1.close(0)
54
+ end
55
+
56
+ def test_put
57
+ @cursor.put('10_000', 'data-10_000', Bdb::DB_KEYLAST)
58
+ value = @db.get(nil, '10_000', nil, 0)
59
+ assert_equal 'data-10_000', value
60
+ end
61
+
62
+ def test_del
63
+ key, value = @cursor.get(nil, nil, Bdb::DB_FIRST)
64
+ value = @db.get(nil, '0', nil, 0)
65
+ assert_equal '0', key
66
+ assert_equal 'data-0', value
67
+ @cursor.del
68
+ value = @db.get(nil, '0', nil, 0)
69
+ assert_nil value
70
+ end
71
+
72
+ def test_count
73
+ @cursor.get(nil, nil, Bdb::DB_FIRST)
74
+ assert_equal 1, @cursor.count
75
+ end
76
+
77
+ def test_get_all_in_order
78
+ all = []
79
+ while pair = @cursor.get(nil, nil, Bdb::DB_NEXT)
80
+ all << pair.first
81
+ end
82
+ assert_equal (0..9).collect {|i| i.to_s}, all
83
+ end
84
+
85
+ def test_get_all_with_btree_compare
86
+ @db1 = Bdb::Db.new
87
+ @db1.btree_compare = proc {|db, key1, key2| key2 <=> key1}
88
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test1.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
89
+ 10.times { |i| @db1.put(nil, i.to_s, "data-#{i}", 0)}
90
+ @cursor1 = @db1.cursor(nil, 0)
91
+
92
+ all = []
93
+ while pair = @cursor1.get(nil, nil, Bdb::DB_NEXT)
94
+ all << pair.first
95
+ end
96
+ assert_equal (0..9).collect {|i| i.to_s}.reverse, all
97
+ @cursor1.close
98
+ @db1.close(0)
99
+ end
100
+
101
+ def test_btree_compare_raises_if_fixnum_not_returned
102
+ @db1 = Bdb::Db.new
103
+ @db1.btree_compare = proc {|db, key1, key2| key1}
104
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test1.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
105
+
106
+ assert_raises(TypeError) do
107
+ @db1.put(nil, "no", "way", 0)
108
+ @db1.put(nil, "ho", "say", 0)
109
+ end
110
+ @db1.close(Bdb::DB_NOSYNC)
111
+ end
112
+
113
+ def test_join
114
+ @personnel_db = Bdb::Db.new
115
+ @personnel_db.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'personnel_db.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
116
+
117
+ @names_db = Bdb::Db.new
118
+ @names_db.flags = Bdb::DB_DUPSORT
119
+ @names_db.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'names_db.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
120
+
121
+ @jobs_db = Bdb::Db.new
122
+ @jobs_db.flags = Bdb::DB_DUPSORT
123
+ @jobs_db.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'jobs_db.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
124
+
125
+ [{:ssn => '111-11-1111', :lastname => 'Smith', :job => 'welder'},
126
+ {:ssn => '222-22-2222', :lastname => 'Jones', :job => 'welder'},
127
+ {:ssn => '333-33-3333', :lastname => 'Smith', :job => 'painter'}].each do |e|
128
+ @personnel_db.put(nil, e[:ssn], Marshal.dump([e[:ssn], e[:lastname], e[:job]]), 0)
129
+ @names_db.put(nil, e[:lastname], e[:ssn], 0)
130
+ @jobs_db.put(nil, e[:job], e[:ssn], 0)
131
+ end
132
+
133
+ @name_cursor = @names_db.cursor(nil, 0)
134
+ @name_cursor.get('Smith', nil, Bdb::DB_SET)
135
+ assert_equal 2, @name_cursor.count
136
+ @job_cursor = @jobs_db.cursor(nil, 0)
137
+ @job_cursor.get('welder', nil, Bdb::DB_SET)
138
+ assert_equal 2, @job_cursor.count
139
+ @personnel_cursor = @personnel_db.join([@name_cursor, @job_cursor], 0)
140
+ assert_equal '111-11-1111', @personnel_cursor.get(nil, nil, 0).first
141
+
142
+ @personnel_cursor.close
143
+ @name_cursor.close
144
+ @job_cursor.close
145
+
146
+ @jobs_db.close(0)
147
+ @names_db.close(0)
148
+ @personnel_db.close(0)
149
+ end
150
+ end
data/test/db_test.rb ADDED
@@ -0,0 +1,157 @@
1
+ require 'test_helper'
2
+
3
+ class DbTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ mkdir File.join(File.dirname(__FILE__), 'tmp')
7
+ @db = Bdb::Db.new
8
+ @db.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
9
+ end
10
+
11
+ def teardown
12
+ assert(@db.close(0)) if @db
13
+ rm_rf File.join(File.dirname(__FILE__), 'tmp')
14
+ end
15
+
16
+ def test_put_and_get
17
+ @db.put(nil, 'key', 'data', 0)
18
+ result = @db.get(nil, 'key', nil, 0)
19
+ assert_equal 'data', result
20
+ end
21
+
22
+ def test_del
23
+ @db.put(nil, 'key', 'data', 0)
24
+ result = @db.get(nil, 'key', nil, 0)
25
+ assert_equal 'data', result
26
+ @db.del(nil, 'key', 0)
27
+ result = @db.get(nil, 'key', nil, 0)
28
+ assert_nil result
29
+ end
30
+
31
+ def test_flags_set_and_get
32
+ @db1 = Bdb::Db.new
33
+ @db1.flags = Bdb::DB_DUPSORT
34
+ assert Bdb::DB_DUPSORT, @db1.flags
35
+ end
36
+
37
+ def test_associate_and_pget
38
+ @db1 = Bdb::Db.new
39
+ @db1.flags = Bdb::DB_DUPSORT
40
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test1.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
41
+
42
+ @db.associate(nil, @db1, 0, proc { |sdb, key, data| key.split('-')[0] })
43
+
44
+ @db.put(nil, '1234-5678', 'data', 0)
45
+ @db.put(nil, '5678-1234', 'atad', 0)
46
+
47
+ result = @db.get(nil, '1234-5678', nil, 0)
48
+ assert_equal 'data', result
49
+ result = @db1.get(nil, '5678', nil, 0)
50
+ assert_equal 'atad', result
51
+
52
+ result = @db1.pget(nil, '1234', nil, 0)
53
+ assert_equal ['1234-5678', 'data'], result
54
+
55
+ @db1.close(0)
56
+ end
57
+
58
+ def test_associate_with_multiple_keys
59
+ @db1 = Bdb::Db.new
60
+ @db1.flags = Bdb::DB_DUPSORT
61
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'test1.db'), nil, Bdb::Db::HASH, Bdb::DB_CREATE, 0)
62
+
63
+ @db.associate(nil, @db1, 0, proc { |sdb, key, data| key.split('-') })
64
+
65
+ @db.put(nil, '1234-5678', 'data', 0)
66
+ @db.put(nil, '8765-4321', 'atad', 0)
67
+
68
+ result = @db.get(nil, '1234-5678', nil, 0)
69
+ assert_equal 'data', result
70
+ result = @db1.get(nil, '5678', nil, 0)
71
+ assert_equal 'data', result
72
+ result = @db1.get(nil, '1234', nil, 0)
73
+ assert_equal 'data', result
74
+ result = @db1.get(nil, '8765', nil, 0)
75
+ assert_equal 'atad', result
76
+ result = @db1.get(nil, '4321', nil, 0)
77
+ assert_equal 'atad', result
78
+
79
+ @db1.close(0)
80
+ end
81
+
82
+ def test_aset_and_aget
83
+ @db['key'] = 'data'
84
+ result = @db.get(nil, 'key', nil, 0)
85
+ assert_equal 'data', result
86
+ result = @db['key']
87
+ assert_equal 'data', result
88
+ @db['key'] = 'data1'
89
+ result = @db['key']
90
+ assert_equal 'data1', result
91
+ end
92
+
93
+ def test_get_byteswapped
94
+ @db.get_byteswapped
95
+ end
96
+
97
+ def test_get_type
98
+ assert_equal Bdb::Db::BTREE, @db.get_type
99
+ end
100
+
101
+ def test_remove
102
+ @db1 = Bdb::Db.new
103
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'other_test.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
104
+ @db1.close(0)
105
+ Bdb::Db.new.remove(File.join(File.dirname(__FILE__), 'tmp', 'other_test.db'), nil, 0)
106
+ assert !File.exists?(File.join(File.dirname(__FILE__), 'tmp', 'other_test.db'))
107
+ end
108
+
109
+ def test_key_range
110
+ 10.times { |i| @db.put(nil, i.to_s, 'data', 0) }
111
+ @db.key_range(nil, '2', 0)
112
+ end
113
+
114
+ def test_rename
115
+ @db1 = Bdb::Db.new
116
+ @db1.open(nil, File.join(File.dirname(__FILE__), 'tmp', 'other_test.db'), nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
117
+ @db1.close(0)
118
+ assert Bdb::Db.new.rename(File.join(File.dirname(__FILE__), 'tmp', 'other_test.db'), nil, File.join(File.dirname(__FILE__), 'tmp', 'other2_test.db'), 0)
119
+ assert File.exists?(File.join(File.dirname(__FILE__), 'tmp', 'other2_test.db'))
120
+ end
121
+
122
+ def test_pagesize_get_and_set
123
+ @db1 = Bdb::Db.new
124
+ @db1.pagesize = 1024
125
+ assert_equal 1024, @db1.pagesize
126
+ end
127
+
128
+ def test_h_ffactor_get_and_set
129
+ @db1 = Bdb::Db.new
130
+ @db1.h_ffactor = 5
131
+ assert_equal 5, @db1.h_ffactor
132
+ end
133
+
134
+ def test_h_nelem_get_and_set
135
+ @db1 = Bdb::Db.new
136
+ @db1.h_nelem = 10_000
137
+ assert_equal 10_000, @db1.h_nelem
138
+ end
139
+
140
+ def test_sync
141
+ assert @db.sync
142
+ end
143
+
144
+ def test_truncate
145
+ @db.put(nil, 'key', 'data', 0)
146
+ result = @db.get(nil, 'key', nil, 0)
147
+ assert_equal 'data', result
148
+ @db.truncate(nil)
149
+ result = @db.get(nil, 'key', nil, 0)
150
+ assert_nil result
151
+ end
152
+
153
+ def test_compact
154
+ assert @db.compact(nil, nil, nil, nil, 0)
155
+ end
156
+
157
+ end