kyotocabinet-java 0.2.0-java → 0.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+
3
+ module KyotoCabinet
4
+
5
+ class TestVisitor
6
+ attr_reader :empty
7
+ attr_reader :full
8
+
9
+ def visit_empty(key)
10
+ @empty = true
11
+ end
12
+
13
+ def visit_full(key, value)
14
+ @full = value
15
+ end
16
+ end
17
+
18
+ BIN = "\x01\xd6"
19
+
20
+ describe Cursor do
21
+ before(:each) do
22
+ @db = DB.new
23
+ @db.open('%')
24
+ @db["hello"] = "world"
25
+ @db["int_a"] = [0].pack("Q>")
26
+ @db["empty"] = nil
27
+ @db[BIN] = BIN
28
+ @cur = @db.cursor
29
+ end
30
+
31
+ describe "#accept" do
32
+ it "works with a Visitor" do
33
+ @cur.jump("hello")
34
+ v = TestVisitor.new
35
+ @cur.accept(v, false)
36
+ end
37
+ end
38
+
39
+ describe "#jump" do
40
+ it "works with no args" do
41
+ @cur.jump()
42
+ @cur.get_key.should == BIN
43
+ end
44
+ end
45
+
46
+ describe "#jump_back" do
47
+ it "works with no args" do
48
+ @cur.jump_back()
49
+ @cur.get_key.should == "int_a"
50
+ end
51
+ end
52
+
53
+ describe "#seize" do
54
+ it "works" do
55
+ @cur.jump("hello")
56
+ r = @cur.seize
57
+ r[0].should == 'hello'
58
+ r[1].should == 'world'
59
+ @db['hello'].should == nil
60
+ end
61
+ end
62
+
63
+ describe "#set_value" do
64
+ it "works with step=true" do
65
+ @cur.jump("empty")
66
+ @cur.set_value("foo", true)
67
+ @cur.get_key.should == "hello"
68
+ @db["empty"].should == "foo"
69
+ end
70
+
71
+ it "works with step=false" do
72
+ @cur.jump("empty")
73
+ @cur.set_value("foo")
74
+ @cur.get_key.should == "empty"
75
+ @db["empty"].should == "foo"
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ describe DB do
82
+
83
+ it "can create an in-memory tree DB" do
84
+ db = DB.new
85
+ db.open("%", KyotoCabinet::DB::OWRITER | KyotoCabinet::DB::OCREATE)
86
+ db["hello"] = "world"
87
+ db.count.should == 1
88
+ end
89
+
90
+ describe "with in-memory DB" do
91
+ before(:each) do
92
+ @db = DB.new
93
+ @db.open("%", KyotoCabinet::DB::OWRITER | KyotoCabinet::DB::OCREATE)
94
+ @db["hello"] = "world"
95
+ @db["int_a"] = [0].pack("Q>")
96
+ @db["empty"] = nil
97
+ @db[BIN] = BIN
98
+ end
99
+
100
+ describe "#accept" do
101
+ it "works with a visitor" do
102
+ v = TestVisitor.new
103
+ @db.accept("hello", v, true)
104
+ v.full.should == "world"
105
+ end
106
+ it "works with a block" do
107
+ value = nil
108
+ @db.accept("hello") do |k, v|
109
+ if k == "hello"
110
+ value = v
111
+ end
112
+ end
113
+ value.should == "world"
114
+ end
115
+ end
116
+
117
+ describe "#accept_bulk" do
118
+ it "works with a visitor and one item" do
119
+ v = TestVisitor.new
120
+ @db.accept_bulk(["hello"], v, true)
121
+ v.full.should == "world"
122
+ end
123
+ it "works with a block and one item" do
124
+ value = nil
125
+ @db.accept_bulk(["hello"]) do |k, v|
126
+ value = v if k == "hello"
127
+ end
128
+ value.should == "world"
129
+ end
130
+ end
131
+
132
+ describe "#add" do
133
+ it "adds an entry" do
134
+ @db.add("a", BIN)
135
+ @db['a'].should == BIN
136
+ end
137
+ end
138
+
139
+ describe "#append" do
140
+ it "works" do
141
+ @db.append("hello", "wide").should be_true
142
+ @db["hello"].should == "worldwide"
143
+ end
144
+ end
145
+
146
+ describe "#cas" do
147
+ it "works on existing values" do
148
+ @db.cas("hello", "world", BIN).should be_true
149
+ @db["hello"].should == BIN
150
+ end
151
+ end
152
+
153
+ describe "#check" do
154
+ it "works" do
155
+ @db.check(BIN).should == BIN.size
156
+ end
157
+ end
158
+
159
+ describe "#delete" do
160
+ it "works like #remove" do
161
+ @db.delete('hello')
162
+ @db['hello'].should be_nil
163
+ end
164
+ end
165
+
166
+ describe "#each" do
167
+ it "works like block #iterate without side effects" do
168
+ value = nil
169
+ @db.each do |k, v|
170
+ if k == "hello"
171
+ value = v
172
+ end
173
+ "12345"
174
+ end
175
+ value.should == "world"
176
+ @db["hello"].should == "world"
177
+ end
178
+ end
179
+
180
+ describe "#each_key" do
181
+ it "gives keys" do
182
+ keys = []
183
+ @db.each_key do |k|
184
+ keys << k
185
+ end
186
+ keys.sort!
187
+ keys.should == [[BIN], ["empty"], ["hello"], ["int_a"]]
188
+ end
189
+ end
190
+
191
+ describe "#each_value" do
192
+ it "gives values" do
193
+ values = []
194
+ @db.each_value do |v|
195
+ values << v
196
+ end
197
+ values.sort!
198
+ values.should == [[''], [@db["int_a"]], [BIN], ["world"]]
199
+ end
200
+ end
201
+
202
+ describe "#get" do
203
+ it "returns nil properly" do
204
+ @db.get("foo").should be_nil
205
+ end
206
+ end
207
+
208
+ describe "#get_bulk" do
209
+ it "works on multiple records" do
210
+ @db.get_bulk(["hello", BIN]).should == {
211
+ 'hello' => "world",
212
+ BIN => BIN
213
+ }
214
+ end
215
+ end
216
+
217
+ describe "#increment" do
218
+ it "creates a value with one arg" do
219
+ @db.increment("int_z")
220
+ @db["int_z"].should_not be_nil
221
+ end
222
+
223
+ it "increments with two args" do
224
+ @db.increment("int_a", 1)
225
+ @db["int_a"].unpack("Q>")[0].should == 1
226
+ end
227
+ end
228
+
229
+ describe "#increment_double" do
230
+ it "creates a value with one arg" do
231
+ @db.increment_double("double_z")
232
+ @db["double_z"].should_not be_nil
233
+ end
234
+
235
+ it "increments with two args" do
236
+ @db.increment_double("double_a", 1.5).should == 1.5
237
+ end
238
+ end
239
+
240
+ describe "#iterate" do
241
+ it "works with a visitor" do
242
+ v = TestVisitor.new
243
+ @db.iterate(v)
244
+ v.full.should_not be_nil
245
+ end
246
+
247
+ it "works with a block" do
248
+ value = nil
249
+ @db.iterate do |k, v|
250
+ if k == "hello"
251
+ value = v
252
+ "NEWVAL"
253
+ end
254
+ end
255
+ value.should == "world"
256
+ @db["hello"].should == "NEWVAL"
257
+ end
258
+ end
259
+
260
+ describe "#merge" do
261
+ it "combines multiple DBs" do
262
+ db1 = KyotoCabinet::DB.new
263
+ db1.open('%')
264
+ db1['z1'] = 'xyzzy'
265
+ db2 = KyotoCabinet::DB.new
266
+ db2.open('%')
267
+ db2['z2'] = 'foo'
268
+ @db.merge([db1, db2])
269
+ @db['z1'].should == 'xyzzy'
270
+ @db['z2'].should == 'foo'
271
+ end
272
+ end
273
+
274
+ describe "#remove_bulk" do
275
+ it "works with a single key" do
276
+ @db.remove_bulk(["hello"])
277
+ @db["hello"].should be_nil
278
+ end
279
+ end
280
+
281
+ describe "#seize" do
282
+ it "returns the correct value" do
283
+ @db.seize("hello").should == "world"
284
+ end
285
+ end
286
+
287
+ describe "#store" do
288
+ it "works like #set" do
289
+ @db.store("a", "b")
290
+ @db["a"].should == "b"
291
+ end
292
+ end
293
+
294
+ after(:each) do
295
+ @db.close
296
+ end
297
+ end
298
+
299
+ end
300
+
301
+ end
@@ -0,0 +1,13 @@
1
+ require 'rspec'
2
+ if RUBY_PLATFORM == 'java'
3
+ require 'bundler/setup'
4
+
5
+ $LOAD_PATH << File.expand_path('../../test_ext', __FILE__)
6
+ else
7
+ # enable running this against the kyotocabinet-ruby library for
8
+ # compatibility testing.
9
+ $LOAD_PATH.delete_if { |e| e =~ %r{kyotocabinet-java/lib} }
10
+ $stderr.puts $LOAD_PATH.join("\n")
11
+ end
12
+
13
+ require 'kyotocabinet'
@@ -0,0 +1 @@
1
+ casket.kch
@@ -0,0 +1,1184 @@
1
+ #! /usr/bin/ruby -w
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #-------------------------------------------------------------------------------------------------
5
+ # The test cases of the Ruby binding
6
+ # Copyright (C) 2009-2010 FAL Labs
7
+ # This file is part of Kyoto Cabinet.
8
+ # This program is free software: you can redistribute it and/or modify it under the terms of
9
+ # the GNU General Public License as published by the Free Software Foundation, either version
10
+ # 3 of the License, or any later version.
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12
+ # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
+ # See the GNU General Public License for more details.
14
+ # You should have received a copy of the GNU General Public License along with this program.
15
+ # If not, see <http://www.gnu.org/licenses/>.
16
+ #-------------------------------------------------------------------------------------------------
17
+
18
+
19
+ require 'kyotocabinet'
20
+ require 'fileutils'
21
+ include KyotoCabinet
22
+
23
+
24
+ # main routine
25
+ def main
26
+ begin
27
+ ARGV.length >= 1 || usage
28
+ if ARGV[0] == "order"
29
+ rv = runorder
30
+ elsif ARGV[0] == "wicked"
31
+ rv = runwicked
32
+ elsif ARGV[0] == "misc"
33
+ rv = runmisc
34
+ else
35
+ usage
36
+ end
37
+ GC.start
38
+ return rv
39
+ rescue
40
+ $stderr.puts "#{$!.class}: #{$!}"
41
+ $stderr.puts $!.backtrace.join("\n")
42
+ exit 1
43
+ end
44
+ end
45
+
46
+
47
+ # print the usage and exit
48
+ def usage
49
+ STDERR.printf("%s: test cases of the Ruby binding\n", $progname)
50
+ STDERR.printf("\n")
51
+ STDERR.printf("usage:\n")
52
+ STDERR.printf(" %s order [-cc] [-th num] [-rnd] [-etc] path rnum\n", $progname)
53
+ STDERR.printf(" %s wicked [-cc] [-th num] [-it num] path rnum\n", $progname)
54
+ STDERR.printf(" %s misc path\n", $progname)
55
+ STDERR.printf("\n")
56
+ exit(1)
57
+ end
58
+
59
+
60
+ # print the error message of the database
61
+ def dberrprint(db, func)
62
+ err = db.error
63
+ $stderr.printf("%s: %s: %d: %s: %s\n", $progname, func, err.code, err.name, err.message)
64
+ end
65
+
66
+
67
+ # print members of a database
68
+ def dbmetaprint(db, verbose)
69
+ if verbose
70
+ status = db.status
71
+ if status
72
+ status.each { |name, value|
73
+ printf("%s: %s\n", name, value)
74
+ }
75
+ end
76
+ else
77
+ printf("count: %d\n", db.count)
78
+ printf("size: %d\n", db.size)
79
+ end
80
+ end
81
+
82
+
83
+ # parse arguments of order command
84
+ def runorder
85
+ path = nil
86
+ rnum = nil
87
+ gopts = 0
88
+ thnum = 1
89
+ rnd = false
90
+ etc = false
91
+ i = 1
92
+ while i < ARGV.length
93
+ arg = ARGV[i]
94
+ if !path && arg =~ /^-/
95
+ if arg == "-cc"
96
+ gopts |= DB::GCONCURRENT
97
+ elsif arg == "-th"
98
+ i += 1
99
+ usage if i >= ARGV.length
100
+ thnum = ARGV[i].to_i
101
+ elsif arg == "-rnd"
102
+ rnd = true
103
+ elsif arg == "-etc"
104
+ etc = true
105
+ else
106
+ usage
107
+ end
108
+ elsif !path
109
+ path = arg
110
+ elsif !rnum
111
+ rnum = arg.to_i
112
+ else
113
+ usage
114
+ end
115
+ i += 1
116
+ end
117
+ usage if !path || !rnum || rnum < 1 || thnum < 1
118
+ rv = procorder(path, rnum, gopts, thnum, rnd, etc)
119
+ return rv
120
+ end
121
+
122
+
123
+ # parse arguments of wicked command
124
+ def runwicked
125
+ path = nil
126
+ rnum = nil
127
+ gopts = 0
128
+ thnum = 1
129
+ itnum = 1
130
+ i = 1
131
+ while i < ARGV.length
132
+ arg = ARGV[i]
133
+ if !path && arg =~ /^-/
134
+ if arg == "-cc"
135
+ gopts |= DB::GCONCURRENT
136
+ elsif arg == "-th"
137
+ i += 1
138
+ usage if i >= ARGV.length
139
+ thnum = ARGV[i].to_i
140
+ elsif arg == "-it"
141
+ i += 1
142
+ usage if i >= ARGV.length
143
+ itnum = ARGV[i].to_i
144
+ else
145
+ usage
146
+ end
147
+ elsif !path
148
+ path = arg
149
+ elsif !rnum
150
+ rnum = arg.to_i
151
+ else
152
+ usage
153
+ end
154
+ i += 1
155
+ end
156
+ usage if !path || !rnum || rnum < 1 || thnum < 1 || itnum < 1
157
+ rv = procwicked(path, rnum, gopts, thnum, itnum)
158
+ return rv
159
+ end
160
+
161
+
162
+ # parse arguments of wicked command
163
+ def runmisc
164
+ path = nil
165
+ i = 1
166
+ while i < ARGV.length
167
+ arg = ARGV[i]
168
+ if !path && arg =~ /^-/
169
+ usage
170
+ elsif !path
171
+ path = arg
172
+ else
173
+ usage
174
+ end
175
+ i += 1
176
+ end
177
+ usage if !path
178
+ rv = procmisc(path)
179
+ return rv
180
+ end
181
+
182
+
183
+ # perform order command
184
+ def procorder(path, rnum, gopts, thnum, rnd, etc)
185
+ printf("<In-order Test>\n path=%s rnum=%d gopts=%d thnum=%d rnd=%s etc=%s\n\n",
186
+ path, rnum, gopts, thnum, rnd, etc)
187
+ err = false
188
+ db = DB::new(gopts)
189
+ db.tune_exception_rule([ Error::SUCCESS, Error::NOIMPL, Error::MISC ])
190
+ db.tune_encoding("utf-8")
191
+ printf("opening the database:\n")
192
+ stime = Time::now
193
+ if !db.open(path, DB::OWRITER | DB::OCREATE | DB::OTRUNCATE)
194
+ dberrprint(db, "DB::open")
195
+ err = true
196
+ end
197
+ etime = Time::now
198
+ printf("time: %.3f\n", etime - stime)
199
+ printf("setting records:\n")
200
+ stime = Time::now
201
+ threads = Array::new
202
+ for thid in 0...thnum
203
+ th = Thread::new(thid) { |id|
204
+ base = id * rnum
205
+ range = rnum * thnum
206
+ for i in 1..rnum
207
+ break if err
208
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
209
+ if !db.set(key, key)
210
+ dberrprint(db, "DB::set")
211
+ err = true
212
+ end
213
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
214
+ print(".")
215
+ if i == rnum || i % (rnum / 10) == 0
216
+ printf(" (%08d)\n", i)
217
+ end
218
+ end
219
+ end
220
+ }
221
+ threads.push(th)
222
+ end
223
+ threads.each { |jth|
224
+ jth.join
225
+ }
226
+ etime = Time::now
227
+ dbmetaprint(db, false)
228
+ printf("time: %.3f\n", etime - stime)
229
+ if etc
230
+ printf("adding records:\n")
231
+ stime = Time::now
232
+ threads = Array::new
233
+ for thid in 0...thnum
234
+ th = Thread::new(thid) { |id|
235
+ base = id * rnum
236
+ range = rnum * thnum
237
+ for i in 1..rnum
238
+ break if err
239
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
240
+ if !db.add(key, key) && db.error != Error::DUPREC
241
+ dberrprint(db, "DB::add")
242
+ err = true
243
+ end
244
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
245
+ print(".")
246
+ if i == rnum || i % (rnum / 10) == 0
247
+ printf(" (%08d)\n", i)
248
+ end
249
+ end
250
+ end
251
+ }
252
+ threads.push(th)
253
+ end
254
+ threads.each { |jth|
255
+ jth.join
256
+ }
257
+ etime = Time::now
258
+ dbmetaprint(db, false)
259
+ printf("time: %.3f\n", etime - stime)
260
+ end
261
+ if etc
262
+ printf("appending records:\n")
263
+ stime = Time::now
264
+ threads = Array::new
265
+ for thid in 0...thnum
266
+ th = Thread::new(thid) { |id|
267
+ base = id * rnum
268
+ range = rnum * thnum
269
+ for i in 1..rnum
270
+ break if err
271
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
272
+ if !db.append(key, key)
273
+ dberrprint(db, "DB::append")
274
+ err = true
275
+ end
276
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
277
+ print(".")
278
+ if i == rnum || i % (rnum / 10) == 0
279
+ printf(" (%08d)\n", i)
280
+ end
281
+ end
282
+ end
283
+ }
284
+ threads.push(th)
285
+ end
286
+ threads.each { |jth|
287
+ jth.join
288
+ }
289
+ etime = Time::now
290
+ dbmetaprint(db, false)
291
+ printf("time: %.3f\n", etime - stime)
292
+ end
293
+ if etc && !(gopts & DB::GCONCURRENT)
294
+ printf("accepting visitors:\n")
295
+ stime = Time::now
296
+ threads = Array::new
297
+ for thid in 0...thnum
298
+ th = Thread::new(thid) { |id|
299
+ me = Thread::current
300
+ me[:rnd] = rnd
301
+ me[:cnt] = 0
302
+ def me.visit_full(key, value)
303
+ self[:cnt] += 1
304
+ Thread::pass if self[:cnt] % 100 == 0
305
+ rv = Visitor::NOP
306
+ if self[:rnd]
307
+ case rand(7)
308
+ when 0
309
+ rv = self[:cnt]
310
+ when 1
311
+ rv = Visitor::REMOVE
312
+ end
313
+ end
314
+ return rv
315
+ end
316
+ def me.visit_empty(key)
317
+ return visit_full(key, key)
318
+ end
319
+ base = id * rnum
320
+ range = rnum * thnum
321
+ for i in 1..rnum
322
+ break if err
323
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
324
+ if !db.accept(key, me, rnd)
325
+ dberrprint(db, "DB::accept")
326
+ err = true
327
+ end
328
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
329
+ print(".")
330
+ if i == rnum || i % (rnum / 10) == 0
331
+ printf(" (%08d)\n", i)
332
+ end
333
+ end
334
+ end
335
+ }
336
+ threads.push(th)
337
+ end
338
+ threads.each { |jth|
339
+ jth.join
340
+ }
341
+ etime = Time::now
342
+ dbmetaprint(db, false)
343
+ printf("time: %.3f\n", etime - stime)
344
+ end
345
+ printf("getting records:\n")
346
+ stime = Time::now
347
+ threads = Array::new
348
+ for thid in 0...thnum
349
+ th = Thread::new(thid) { |id|
350
+ base = id * rnum
351
+ range = rnum * thnum
352
+ for i in 1..rnum
353
+ break if err
354
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
355
+ if !db.get(key) && db.error != Error::NOREC
356
+ dberrprint(db, "DB::get")
357
+ err = true
358
+ end
359
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
360
+ print(".")
361
+ if i == rnum || i % (rnum / 10) == 0
362
+ printf(" (%08d)\n", i)
363
+ end
364
+ end
365
+ end
366
+ }
367
+ threads.push(th)
368
+ end
369
+ threads.each { |jth|
370
+ jth.join
371
+ }
372
+ etime = Time::now
373
+ dbmetaprint(db, false)
374
+ printf("time: %.3f\n", etime - stime)
375
+ if etc && !(gopts & DB::GCONCURRENT)
376
+ printf("traversing the database by the inner iterator:\n")
377
+ stime = Time::now
378
+ threads = Array::new
379
+ for thid in 0...thnum
380
+ th = Thread::new(thid) { |id|
381
+ me = Thread::current
382
+ me[:id] = id
383
+ me[:rnum] = rnum
384
+ me[:rnd] = rnd
385
+ me[:cnt] = 0
386
+ def me.visit_full(key, value)
387
+ self[:cnt] += 1
388
+ Thread::pass if self[:cnt] % 100 == 0
389
+ rv = Visitor::NOP
390
+ if self[:rnd]
391
+ case rand(7)
392
+ when 0
393
+ rv = self[:cnt].to_s * 2
394
+ when 1
395
+ rv = Visitor::REMOVE
396
+ end
397
+ end
398
+ if self[:id] < 1 && self[:rnum] > 250 && self[:cnt] % (self[:rnum] / 250) == 0
399
+ print(".")
400
+ if self[:cnt] == self[:rnum] || self[:cnt] % (self[:rnum] / 10) == 0
401
+ printf(" (%08d)\n", self[:cnt])
402
+ end
403
+ end
404
+ return rv
405
+ end
406
+ def me.visit_empty(key)
407
+ return Visitor::NOP
408
+ end
409
+ if !db.iterate(me, rnd)
410
+ dberrprint(db, "DB::iterate")
411
+ err = true
412
+ end
413
+ }
414
+ threads.push(th)
415
+ end
416
+ threads.each { |jth|
417
+ jth.join
418
+ }
419
+ printf(" (end)\n") if rnd
420
+ etime = Time::now
421
+ dbmetaprint(db, false)
422
+ printf("time: %.3f\n", etime - stime)
423
+ end
424
+ if etc && !(gopts & DB::GCONCURRENT)
425
+ printf("traversing the database by the outer cursor:\n")
426
+ stime = Time::now
427
+ threads = Array::new
428
+ for thid in 0...thnum
429
+ th = Thread::new(thid) { |id|
430
+ me = Thread::current
431
+ me[:id] = id
432
+ me[:rnum] = rnum
433
+ me[:rnd] = rnd
434
+ me[:cnt] = 0
435
+ def me.visit_full(key, value)
436
+ self[:cnt] += 1
437
+ Thread::pass if self[:cnt] % 100 == 0
438
+ rv = Visitor::NOP
439
+ if self[:rnd]
440
+ case rand(7)
441
+ when 0
442
+ rv = self[:cnt].to_s * 2
443
+ when 1
444
+ rv = Visitor::REMOVE
445
+ end
446
+ end
447
+ if self[:id] < 1 && self[:rnum] > 250 && self[:cnt] % (self[:rnum] / 250) == 0
448
+ print(".")
449
+ if self[:cnt] == self[:rnum] || self[:cnt] % (self[:rnum] / 10) == 0
450
+ printf(" (%08d)\n", self[:cnt])
451
+ end
452
+ end
453
+ return rv
454
+ end
455
+ def me.visit_empty(key)
456
+ return Visitor::NOP
457
+ end
458
+ cur = db.cursor
459
+ if !cur.jump && db.error != Error::NOREC
460
+ dberrprint(db, "Cursor::jump")
461
+ err = true
462
+ end
463
+ while cur.accept(me, rnd, false)
464
+ if !cur.step && db.error != Error::NOREC
465
+ dberrprint(db, "Cursor::step")
466
+ err = true
467
+ end
468
+ end
469
+ if db.error != Error::NOREC
470
+ dberrprint(db, "Cursor::accept")
471
+ err = true
472
+ end
473
+ cur.disable if !rnd || rand(2) == 0
474
+ }
475
+ threads.push(th)
476
+ end
477
+ threads.each { |jth|
478
+ jth.join
479
+ }
480
+ printf(" (end)\n") if rnd
481
+ etime = Time::now
482
+ dbmetaprint(db, false)
483
+ printf("time: %.3f\n", etime - stime)
484
+ end
485
+ printf("removing records:\n")
486
+ stime = Time::now
487
+ threads = Array::new
488
+ for thid in 0...thnum
489
+ th = Thread::new(thid) { |id|
490
+ base = id * rnum
491
+ range = rnum * thnum
492
+ for i in 1..rnum
493
+ break if err
494
+ key = sprintf("%08d", rnd ? rand(range) + 1 : base + i)
495
+ if !db.remove(key) && db.error != Error::NOREC
496
+ dberrprint(db, "DB::remove")
497
+ err = true
498
+ end
499
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
500
+ print(".")
501
+ if i == rnum || i % (rnum / 10) == 0
502
+ printf(" (%08d)\n", i)
503
+ end
504
+ end
505
+ end
506
+ }
507
+ threads.push(th)
508
+ end
509
+ threads.each { |jth|
510
+ jth.join
511
+ }
512
+ etime = Time::now
513
+ dbmetaprint(db, true)
514
+ printf("time: %.3f\n", etime - stime)
515
+ printf("closing the database:\n")
516
+ stime = Time::now
517
+ if !db.close
518
+ dberrprint(db, "DB::close")
519
+ err = true
520
+ end
521
+ etime = Time::now
522
+ printf("time: %.3f\n", etime - stime)
523
+ printf("%s\n\n", err ? "error" : "ok")
524
+ return err ? 1 : 0
525
+ end
526
+
527
+
528
+ # perform wicked command
529
+ def procwicked(path, rnum, gopts, thnum, itnum)
530
+ printf("<Wicked Test>\n path=%s rnum=%d gopts=%d thnum=%d itnum=%d\n\n",
531
+ path, rnum, gopts, thnum, itnum)
532
+ err = false
533
+ db = DB::new(gopts)
534
+ db.tune_exception_rule([ Error::SUCCESS, Error::NOIMPL, Error::MISC ])
535
+ db.tune_encoding("utf-8") if rand(2) == 0
536
+ for itcnt in 1..itnum
537
+ printf("iteration %d:\n", itcnt) if itnum > 1
538
+ stime = Time::now
539
+ omode = DB::OWRITER | DB::OCREATE
540
+ omode |= DB::OTRUNCATE if itcnt == 1
541
+ if !db.open(path, omode)
542
+ dberrprint(db, "DB::open")
543
+ err = true
544
+ end
545
+ threads = Array::new
546
+ for thid in 0...thnum
547
+ th = Thread::new(thid) { |id|
548
+ me = Thread::current
549
+ me[:cnt] = 0
550
+ def me.visit_full(key, value)
551
+ self[:cnt] += 1
552
+ Thread::pass if self[:cnt] % 100 == 0
553
+ rv = Visitor::NOP
554
+ if self[:rnd]
555
+ case rand(7)
556
+ when 0
557
+ rv = self[:cnt]
558
+ when 1
559
+ rv = Visitor::REMOVE
560
+ end
561
+ end
562
+ return rv
563
+ end
564
+ def me.visit_empty(key)
565
+ return visit_full(key, key)
566
+ end
567
+ cur = db.cursor
568
+ range = rnum * thnum
569
+ for i in 1..rnum
570
+ break if err
571
+ tran = rand(100) == 0
572
+ if tran && !db.begin_transaction(rand(rnum) == 0)
573
+ dberrprint(db, "DB::begin_transaction")
574
+ tran = false
575
+ err = true
576
+ end
577
+ key = sprintf("%08d", rand(range) + 1)
578
+ case rand(12)
579
+ when 0
580
+ if !db.set(key, key)
581
+ dberrprint(db, "DB::set")
582
+ err = true
583
+ end
584
+ when 1
585
+ if !db.add(key, key) && db.error != Error::DUPREC
586
+ dberrprint(db, "DB::add")
587
+ err = true
588
+ end
589
+ when 2
590
+ if !db.replace(key, key) && db.error != Error::NOREC
591
+ dberrprint(db, "DB::replace")
592
+ err = true
593
+ end
594
+ when 3
595
+ if !db.append(key, key)
596
+ dberrprint(db, "DB::append")
597
+ err = true
598
+ end
599
+ when 4
600
+ if rand(2) == 0
601
+ if !db.increment(key, rand(10)) && db.error != Error::LOGIC
602
+ dberrprint(db, "DB::increment")
603
+ err = true
604
+ end
605
+ else
606
+ if !db.increment_double(key, rand() * 10) && db.error != Error::LOGIC
607
+ dberrprint(db, "DB::increment_double")
608
+ err = true
609
+ end
610
+ end
611
+ when 5
612
+ if !db.cas(key, key, key) && db.error != Error::LOGIC
613
+ dberrprint(db, "DB::cas")
614
+ err = true
615
+ end
616
+ when 6
617
+ if !db.remove(key) && db.error != Error::NOREC
618
+ dberrprint(db, "DB::remove")
619
+ err = true
620
+ end
621
+ when 7
622
+ if !db.accept(key, me, true) &&
623
+ (!(gopts & DB::GCONCURRENT) || db.error != Error::INVALID)
624
+ dberrprint(db, "DB::accept")
625
+ err = true
626
+ end
627
+ when 8
628
+ if rand(10) == 0
629
+ if rand(4) == 0
630
+ begin
631
+ if !cur.jump_back(key) && db.error != Error::NOREC
632
+ dberrprint(db, "Cursor::jump_back")
633
+ err = true
634
+ end
635
+ rescue Error::XNOIMPL
636
+ end
637
+ else
638
+ if !cur.jump(key) && db.error != Error::NOREC
639
+ dberrprint(db, "Cursor::jump")
640
+ err = true
641
+ end
642
+ end
643
+ else
644
+ case rand(6)
645
+ when 0
646
+ if !cur.get_key && db.error != Error::NOREC
647
+ dberrprint(db, "Cursor::get_key")
648
+ err = true
649
+ end
650
+ when 1
651
+ if !cur.get_value && db.error != Error::NOREC
652
+ dberrprint(db, "Cursor::get_value")
653
+ err = true
654
+ end
655
+ when 2
656
+ if !cur.get && db.error != Error::NOREC
657
+ dberrprint(db, "Cursor::get")
658
+ err = true
659
+ end
660
+ when 3
661
+ if !cur.remove && db.error != Error::NOREC
662
+ dberrprint(db, "Cursor::remove")
663
+ err = true
664
+ end
665
+ else
666
+ if !cur.accept(me, true, rand(2) == 0) && db.error != Error::NOREC &&
667
+ (!(gopts & DB::GCONCURRENT) || db.error != Error::INVALID)
668
+ dberrprint(db, "Cursor::accept")
669
+ err = true
670
+ end
671
+ end
672
+ end
673
+ if rand(2) == 0
674
+ if !cur.step && db.error != Error::NOREC
675
+ dberrprint(db, "Cursor::step")
676
+ err = true
677
+ end
678
+ end
679
+ if rand(rnum / 50 + 1) == 0
680
+ prefix = key[0,key.length-1]
681
+ if !db.match_prefix(prefix, rand(10))
682
+ dberrprint(db, "DB::match_prefix")
683
+ err = true
684
+ end
685
+ end
686
+ if rand(rnum / 50 + 1) == 0
687
+ regex = key[0,key.length-1]
688
+ if !db.match_regex(regex, rand(10))
689
+ dberrprint(db, "DB::match_regex")
690
+ err = true
691
+ end
692
+ end
693
+ if rand(rnum / 50 + 1) == 0
694
+ origin = key[0,key.length-1]
695
+ if !db.match_similar(origin, 3, rand(10))
696
+ dberrprint(db, "DB::match_similar")
697
+ err = true
698
+ end
699
+ end
700
+ if rand(10) == 0
701
+ paracur = db.cursor
702
+ paracur.jump(key)
703
+ if !paracur.accept(me, true, rand(2) == 0) && db.error != Error::NOREC &&
704
+ (!(gopts & DB::GCONCURRENT) || db.error != Error::INVALID)
705
+ dberrprint(db, "Cursor::accept")
706
+ err = true
707
+ end
708
+ paracur.disable
709
+ end
710
+ else
711
+ if !db.get(key) && db.error != Error::NOREC
712
+ dberrprint(db, "DB::get")
713
+ err = true
714
+ end
715
+ end
716
+ if tran
717
+ Thread::pass if rand(10) == 0
718
+ if !db.end_transaction(rand(10) > 0)
719
+ dberrprint(db, "DB::end_transaction")
720
+ err = true
721
+ end
722
+ end
723
+ if id < 1 && rnum > 250 && i % (rnum / 250) == 0
724
+ print(".")
725
+ if i == rnum || i % (rnum / 10) == 0
726
+ printf(" (%08d)\n", i)
727
+ end
728
+ end
729
+ end
730
+ cur.disable if rand(2) == 0
731
+ }
732
+ threads.push(th)
733
+ end
734
+ threads.each { |jth|
735
+ jth.join
736
+ }
737
+ dbmetaprint(db, itcnt == itnum)
738
+ if !db.close
739
+ dberrprint(db, "DB::close")
740
+ err = true
741
+ end
742
+ etime = Time::now
743
+ printf("time: %.3f\n", etime - stime)
744
+ end
745
+ printf("%s\n\n", err ? "error" : "ok")
746
+ return err ? 1 : 0
747
+ end
748
+
749
+
750
+ # perform misc command
751
+ def procmisc(path)
752
+ printf("<Miscellaneous Test>\n path=%s\n\n", path)
753
+ err = false
754
+ if conv_str(:mikio) != "mikio" || conv_str(123.45) != "123.45"
755
+ printf("%s: conv_str: error\n", $progname)
756
+ err = true
757
+ end
758
+ printf("calling utility functions:\n")
759
+ atoi("123.456mikio")
760
+ atoix("123.456mikio")
761
+ atof("123.456mikio")
762
+ hash_murmur(path)
763
+ hash_fnv(path)
764
+ levdist(path, "casket")
765
+ dcurs = Array::new
766
+ printf("opening the database by iterator:\n")
767
+ dberr = DB::process(path, DB::OWRITER | DB::OCREATE | DB::OTRUNCATE) { |db|
768
+ db.tune_exception_rule([ Error::SUCCESS, Error::NOIMPL, Error::MISC ])
769
+ db.tune_encoding("utf-8")
770
+ db.to_s
771
+ db.inspect
772
+ rnum = 10000
773
+ printf("setting records:\n")
774
+ for i in 0...rnum
775
+ db[i] = i
776
+ end
777
+ if db.count != rnum
778
+ dberrprint(db, "DB::count")
779
+ err = true
780
+ end
781
+ printf("deploying cursors:\n")
782
+ for i in 1..100
783
+ cur = db.cursor
784
+ if !cur.jump(i)
785
+ dberrprint(db, "Cursor::jump")
786
+ err = true
787
+ end
788
+ case i % 3
789
+ when 0
790
+ dcurs.push(cur)
791
+ when 1
792
+ cur.disable
793
+ end
794
+ cur.to_s
795
+ cur.inspect
796
+ end
797
+ printf("getting records:\n")
798
+ dcurs.each { |tcur|
799
+ if !tcur.get_key
800
+ dberrprint(db, "Cursor::get_key")
801
+ err = true
802
+ end
803
+ }
804
+ printf("accepting visitor:\n")
805
+ def db.visit_full(key, value)
806
+ rv = Visitor::NOP
807
+ case key.to_i % 3
808
+ when 0
809
+ rv = sprintf("full:%s", key)
810
+ when 1
811
+ rv = Visitor::REMOVE
812
+ end
813
+ return rv
814
+ end
815
+ def db.visit_empty(key)
816
+ rv = Visitor::NOP
817
+ case key.to_i % 3
818
+ when 0
819
+ rv = sprintf("empty:%s", key)
820
+ when 1
821
+ rv = Visitor::REMOVE
822
+ end
823
+ return rv
824
+ end
825
+ for i in 0...(rnum * 2)
826
+ if !db.accept(i, db, true)
827
+ dberrprint(db, "DB::access")
828
+ err = true
829
+ end
830
+ end
831
+ for i in 0...(rnum * 2)
832
+ if !db.accept(i) { |key, value|
833
+ rv = Visitor::NOP
834
+ case key.to_i % 5
835
+ when 0
836
+ rv = sprintf("block:%s", key)
837
+ when 1
838
+ rv = Visitor::REMOVE
839
+ end
840
+ rv
841
+ }
842
+ dberrprint(db, "DB::access")
843
+ err = true
844
+ end
845
+ end
846
+ printf("accepting visitor by iterator:\n")
847
+ def dcurs.visit_full(key, value)
848
+ Visitor::NOP
849
+ end
850
+ if !db.iterate(dcurs, false)
851
+ dberrprint(db, "DB::iterate")
852
+ err = true
853
+ end
854
+ if !db.iterate { |key, value|
855
+ value.upcase
856
+ }
857
+ dberrprint(db, "DB::iterate")
858
+ err = true
859
+ end
860
+ printf("accepting visitor with a cursor:\n")
861
+ cur = db.cursor
862
+ def cur.visit_full(key, value)
863
+ rv = Visitor::NOP
864
+ case key.to_i % 7
865
+ when 0
866
+ rv = sprintf("cur:full:%s", key)
867
+ when 1
868
+ rv = Visitor::REMOVE
869
+ end
870
+ return rv
871
+ end
872
+ begin
873
+ if !cur.jump_back
874
+ dberrprint(db, "Cursor::jump_back")
875
+ err = true
876
+ end
877
+ while cur.accept(cur, true)
878
+ cur.step_back
879
+ end
880
+ rescue Error::XNOIMPL
881
+ if !cur.jump
882
+ dberrprint(db, "Cursor::jump")
883
+ err = true
884
+ end
885
+ while cur.accept(cur, true)
886
+ cur.step
887
+ end
888
+ end
889
+ cur.jump
890
+ while cur.accept { |key, value|
891
+ rv = Visitor::NOP
892
+ case key.to_i % 11
893
+ when 0
894
+ rv = sprintf("cur:block:%s", key)
895
+ when 1
896
+ rv = Visitor::REMOVE
897
+ end
898
+ rv
899
+ }
900
+ cur.step
901
+ end
902
+ printf("accepting visitor in bulk:\n")
903
+ keys = []
904
+ for i in 1..10
905
+ keys.push(i)
906
+ end
907
+ if not db.accept_bulk(keys, db, true)
908
+ dberrprint(db, "DB::accept_bulk")
909
+ err = true
910
+ end
911
+ recs = {}
912
+ for i in 1..10
913
+ recs[i] = sprintf("[%d]", i)
914
+ end
915
+ if db.set_bulk(recs) < 0
916
+ dberrprint(db, "DB::set_bulk")
917
+ err = true
918
+ end
919
+ if not db.get_bulk(keys)
920
+ dberrprint(db, "DB::get_bulk")
921
+ err = true
922
+ end
923
+ if db.remove_bulk(keys) < 0
924
+ dberrprint(db, "DB::remove_bulk")
925
+ err = true
926
+ end
927
+ printf("synchronizing the database:\n")
928
+ def db.process(path, count, size)
929
+ true
930
+ end
931
+ if !db.synchronize(false, db)
932
+ dberrprint(db, "DB::synchronize")
933
+ err = true
934
+ end
935
+ if !db.synchronize { |tpath, count, size|
936
+ true
937
+ }
938
+ dberrprint(db, "DB::synchronize")
939
+ err = true
940
+ end
941
+ if !db.occupy(false, db)
942
+ dberrprint(db, "DB::occupy")
943
+ err = true
944
+ end
945
+ if !db.occupy { |tpath, count, size|
946
+ true
947
+ }
948
+ dberrprint(db, "DB::occupy")
949
+ err = true
950
+ end
951
+ printf("performing transaction:\n")
952
+ if !db.transaction {
953
+ db["tako"] = "ika"
954
+ true
955
+ }
956
+ dberrprint(db, "DB::transaction")
957
+ err = true
958
+ end
959
+ if db["tako"] != "ika"
960
+ dberrprint(db, "DB::transaction")
961
+ err = true
962
+ end
963
+ db.delete("tako")
964
+ cnt = db.count
965
+ if !db.transaction {
966
+ db["tako"] = "ika"
967
+ db["kani"] = "ebi"
968
+ false
969
+ }
970
+ dberrprint(db, "DB::transaction")
971
+ err = true
972
+ end
973
+ if db["tako"] || db["kani"] || db.count != cnt
974
+ dberrprint(db, "DB::transaction")
975
+ err = true
976
+ end
977
+ printf("closing the database:\n")
978
+ }
979
+ if dberr
980
+ printf("%s: DB::process: %s\n", $progname, dberr)
981
+ err = true
982
+ end
983
+ printf("accessing dead cursors:\n")
984
+ dcurs.each { |cur|
985
+ cur.get_key
986
+ }
987
+ printf("checking the exceptional mode:\n")
988
+ db = DB::new(DB::GEXCEPTIONAL)
989
+ begin
990
+ db.open("hoge")
991
+ rescue Error::XINVALID => e
992
+ if e.code != Error::INVALID
993
+ dberrprint(db, "DB::open")
994
+ err = true
995
+ end
996
+ else
997
+ dberrprint(db, "DB::open")
998
+ err = true
999
+ end
1000
+ printf("re-opening the database as a reader:\n")
1001
+ db = DB::new
1002
+ if !db.open(path, DB::OREADER)
1003
+ dberrprint(db, "DB::open")
1004
+ err = true
1005
+ end
1006
+ printf("traversing records by iterator:\n")
1007
+ keys = Array::new
1008
+ db.each { |key, value|
1009
+ keys.push([key, value])
1010
+ if !value.index(key)
1011
+ dberrprint(db, "Cursor::each")
1012
+ err = true
1013
+ end
1014
+ }
1015
+ printf("checking records:\n")
1016
+ keys.each { |pair|
1017
+ if db.get(pair[0]) != pair[1]
1018
+ dberrprint(db, "DB::get")
1019
+ err = true
1020
+ end
1021
+ }
1022
+ printf("closing the database:\n")
1023
+ if !db.close
1024
+ dberrprint(db, "DB::close")
1025
+ err = true
1026
+ end
1027
+ printf("re-opening the database in the concurrent mode:\n")
1028
+ db = DB::new(DB::GCONCURRENT)
1029
+ if !db.open(path, DB::OWRITER)
1030
+ dberrprint(db, "DB::open")
1031
+ err = true
1032
+ end
1033
+ if !db.set("tako", "ika")
1034
+ dberrprint(db, "DB::set")
1035
+ err = true
1036
+ end
1037
+ if db.accept("tako") { |key, value| } != nil || db.error != Error::INVALID
1038
+ dberrprint(db, "DB::accept")
1039
+ err = true
1040
+ end
1041
+ printf("removing records by cursor:\n")
1042
+ cur = db.cursor
1043
+ if !cur.jump
1044
+ dberrprint(db, "Cursor::jump")
1045
+ err = true
1046
+ end
1047
+ cnt = 0
1048
+ while key = cur.get_key(true)
1049
+ if cnt % 10 != 0
1050
+ if !db.remove(key)
1051
+ dberrprint(db, "DB::remove")
1052
+ err = true
1053
+ end
1054
+ end
1055
+ cnt += 1
1056
+ end
1057
+ if db.error != Error::NOREC
1058
+ dberrprint(db, "Cursor::get_key")
1059
+ err = true
1060
+ end
1061
+ cur.disable
1062
+ printf("processing a cursor by iterator:\n")
1063
+ db.cursor_process { |tcur|
1064
+ if !tcur.jump
1065
+ dberrprint(db, "Cursor::jump")
1066
+ err = true
1067
+ end
1068
+ value = sprintf("[%s]", tcur.get_value)
1069
+ if !tcur.set_value(value)
1070
+ dberrprint(db, "Cursor::set_value")
1071
+ err = true
1072
+ end
1073
+ if tcur.get_value != value
1074
+ dberrprint(db, "Cursor::get_value")
1075
+ err = true
1076
+ end
1077
+ }
1078
+ printf("dumping records into snapshot:\n")
1079
+ snappath = db.path
1080
+ if snappath =~ /.(kch|kct)$/
1081
+ snappath = snappath + ".kcss"
1082
+ else
1083
+ snappath = "kctest.kcss"
1084
+ end
1085
+ if !db.dump_snapshot(snappath)
1086
+ dberrprint(db, "DB::dump_snapshot")
1087
+ err = true
1088
+ end
1089
+ cnt = db.count
1090
+ printf("clearing the database:\n")
1091
+ if !db.clear
1092
+ dberrprint(db, "DB::clear")
1093
+ err = true
1094
+ end
1095
+ printf("loading records from snapshot:\n")
1096
+ if !db.load_snapshot(snappath)
1097
+ dberrprint(db, "DB::load_snapshot")
1098
+ err = true
1099
+ end
1100
+ if db.count != cnt
1101
+ dberrprint(db, "DB::load_snapshot")
1102
+ err = true
1103
+ end
1104
+ File::unlink(snappath)
1105
+ copypath = db.path
1106
+ suffix = nil
1107
+ if copypath.end_with?(".kch")
1108
+ suffix = ".kch"
1109
+ elsif copypath.end_with?(".kct")
1110
+ suffix = ".kct"
1111
+ elsif copypath.end_with?(".kcd")
1112
+ suffix = ".kcd"
1113
+ elsif copypath.end_with?(".kcf")
1114
+ suffix = ".kcf"
1115
+ end
1116
+ if suffix
1117
+ printf("performing copy and merge:\n")
1118
+ copypaths = []
1119
+ for i in 0...2
1120
+ copypaths.push(sprintf("%s.%d%s", copypath, i + 1, suffix))
1121
+ end
1122
+ srcary = []
1123
+ copypaths.each do |cpath|
1124
+ if !db.copy(cpath)
1125
+ dberrprint(db, "DB::copy")
1126
+ err = true
1127
+ end
1128
+ srcdb = DB::new
1129
+ if !srcdb.open(cpath, DB::OREADER)
1130
+ dberrprint(srcdb, "DB::open")
1131
+ err = true
1132
+ end
1133
+ srcary.push(srcdb)
1134
+ end
1135
+ if !db.merge(srcary, DB::MAPPEND)
1136
+ dberrprint(srcdb, "DB::merge")
1137
+ err = true
1138
+ end
1139
+ srcary.each do |srcdb|
1140
+ if !srcdb.close
1141
+ dberrprint(srcdb, "DB::close")
1142
+ err = true
1143
+ end
1144
+ end
1145
+ copypaths.each do |cpath|
1146
+ FileUtils::remove_entry_secure(cpath, true)
1147
+ end
1148
+ end
1149
+ printf("shifting records:\n")
1150
+ ocnt = db.count
1151
+ cnt = 0
1152
+ while db.shift
1153
+ cnt += 1
1154
+ end
1155
+ if db.error != Error::NOREC
1156
+ dberrprint(db, "DB::shift")
1157
+ err = true
1158
+ end
1159
+ if db.count != 0 || cnt != ocnt
1160
+ dberrprint(db, "DB::shift")
1161
+ err = true
1162
+ end
1163
+ printf("closing the database:\n")
1164
+ if !db.close
1165
+ dberrprint(db, "DB::close")
1166
+ err = true
1167
+ end
1168
+ db.to_s
1169
+ db.inspect
1170
+ printf("%s\n\n", err ? "error" : "ok")
1171
+ return err ? 1 : 0
1172
+ end
1173
+
1174
+
1175
+ # execute main
1176
+ STDOUT.sync = true
1177
+ $progname = $0.dup
1178
+ $progname.gsub!(/.*\//, "")
1179
+ srand
1180
+ exit(main)
1181
+
1182
+
1183
+
1184
+ # END OF FILE