kyotocabinet-java 0.2.0-java → 0.3.0-java

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.
@@ -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