rufus-tokyo 1.0.3 → 1.0.4

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.
Files changed (55) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG.txt +6 -0
  3. data/Rakefile +91 -0
  4. data/doc/decision_table.numbers +0 -0
  5. data/lib/rufus/edo/README.txt +101 -0
  6. data/lib/rufus/edo/tabcore.rb +1 -3
  7. data/lib/rufus/tokyo.rb +1 -2
  8. data/lib/rufus/tokyo/cabinet/lib.rb +4 -7
  9. data/lib/rufus/tokyo/cabinet/table.rb +10 -13
  10. data/lib/rufus/tokyo/cabinet/util.rb +4 -1
  11. data/lib/rufus/tokyo/hmethods.rb +4 -4
  12. data/lib/rufus/tokyo/outlen.rb +5 -1
  13. data/lib/rufus/tokyo/tyrant/abstract.rb +8 -0
  14. data/lib/rufus/tokyo/tyrant/lib.rb +6 -6
  15. data/lib/rufus/tokyo/tyrant/table.rb +9 -1
  16. data/lib/rufus/tokyo/version.rb +32 -0
  17. data/rufus-tokyo.gemspec +135 -0
  18. data/spec/cabinet_btree_spec.rb +92 -0
  19. data/spec/cabinet_fixed_spec.rb +33 -0
  20. data/spec/cabinet_spec.rb +291 -0
  21. data/spec/cabinetconfig_spec.rb +82 -0
  22. data/spec/dystopia_core_spec.rb +124 -0
  23. data/spec/edo_cabinet_btree_spec.rb +123 -0
  24. data/spec/edo_cabinet_fixed_spec.rb +42 -0
  25. data/spec/edo_cabinet_spec.rb +286 -0
  26. data/spec/edo_ntyrant_spec.rb +224 -0
  27. data/spec/edo_ntyrant_table_spec.rb +296 -0
  28. data/spec/edo_table_spec.rb +292 -0
  29. data/spec/hmethods_spec.rb +73 -0
  30. data/spec/incr.lua +23 -0
  31. data/spec/openable_spec.rb +51 -0
  32. data/spec/shared_abstract_spec.rb +426 -0
  33. data/spec/shared_table_spec.rb +675 -0
  34. data/spec/shared_tyrant_spec.rb +42 -0
  35. data/spec/spec_base.rb +23 -0
  36. data/spec/start_tyrants.sh +28 -0
  37. data/spec/stop_tyrants.sh +9 -0
  38. data/spec/table_spec.rb +267 -0
  39. data/spec/tyrant_spec.rb +218 -0
  40. data/spec/tyrant_table_spec.rb +298 -0
  41. data/spec/util_list_spec.rb +197 -0
  42. data/spec/util_map_spec.rb +130 -0
  43. data/tasks/dev.rb +70 -0
  44. data/test/bm0.rb +353 -0
  45. data/test/bm1_compression.rb +54 -0
  46. data/test/con0.rb +30 -0
  47. data/test/mem.rb +49 -0
  48. data/test/mem1.rb +44 -0
  49. data/test/readme0.rb +17 -0
  50. data/test/readme1.rb +21 -0
  51. data/test/readme2.rb +15 -0
  52. data/test/readme3.rb +24 -0
  53. data/test/readmes_test.sh +17 -0
  54. metadata +81 -21
  55. data/MIGRATED.txt +0 -1
@@ -0,0 +1,130 @@
1
+
2
+ #
3
+ # Specifying rufus-tokyo
4
+ #
5
+ # Mon Jan 26 15:10:03 JST 2009
6
+ #
7
+
8
+ require File.dirname(__FILE__) + '/spec_base'
9
+
10
+ require 'rufus/tokyo'
11
+
12
+
13
+ describe 'Rufus::Tokyo::Map' do
14
+
15
+ before do
16
+ @m = Rufus::Tokyo::Map.new
17
+ end
18
+ after do
19
+ @m.free
20
+ end
21
+
22
+ it 'should be empty initially' do
23
+ @m.size.should.be.zero
24
+ end
25
+
26
+ it 'should respond to #size and #length' do
27
+ @m.size.should.be.zero
28
+ @m.length.should.be.zero
29
+ end
30
+
31
+ it 'should return nil when there is no value for a key' do
32
+ @m['missing'].should.be.nil
33
+ end
34
+
35
+ it 'should accept input' do
36
+ @m['a'] = 'b'
37
+ @m.size.should.equal(1)
38
+ end
39
+
40
+ it 'should fetch values' do
41
+ @m['a'] = 'b'
42
+ @m['a'].should.equal('b')
43
+ end
44
+
45
+ it 'should accept and restitute strings with \\0' do
46
+ s = "shinjuku#{0.chr}jiken"
47
+ @m[s] = s
48
+ @m[s].should.equal(s)
49
+ end
50
+
51
+ it 'should delete value with \\0' do
52
+ s = "shinjuku#{0.chr}jiken"
53
+ @m[s] = s
54
+ @m.delete(s).should.equal(s)
55
+ end
56
+
57
+ it 'should iterate over values with \\0' do
58
+ s = "oumya#{0.chr}box"
59
+ (1..4).inject(@m) { |m, i| m["#{s}_k#{i}"] = "#{s}_v#{i}"; m }
60
+ aa = @m.inject([]) { |a, (k, v)| a << k << v; a }
61
+ aa.each { |e| e.should.match(/^oumya.box_[kv]/) }
62
+ end
63
+
64
+ it 'should raise an ArgumentError on non-string input' do
65
+ lambda {
66
+ @m[1] = 2
67
+ }.should.raise(ArgumentError)
68
+ lambda {
69
+ @m['a'] = 2
70
+ }.should.raise(ArgumentError)
71
+ lambda {
72
+ @m[1] = 'b'
73
+ }.should.raise(ArgumentError)
74
+ end
75
+ end
76
+
77
+ describe 'Rufus::Tokyo::Map class, like the Ruby Hash class,' do
78
+
79
+ it 'should respond to #[]' do
80
+ m = Rufus::Tokyo::Map[ 'a' => 'b' ]
81
+ m.class.should.equal(Rufus::Tokyo::Map)
82
+ m['a'].should.equal('b')
83
+ m.free
84
+ end
85
+ end
86
+
87
+ describe 'Rufus::Tokyo::Map, like a Ruby Hash,' do
88
+
89
+ before do
90
+ @m = Rufus::Tokyo::Map[%w{ a A b B c C }]
91
+ end
92
+ after do
93
+ @m.free
94
+ end
95
+
96
+ it 'should list keys' do
97
+ @m.keys.should.equal(%w{ a b c })
98
+ end
99
+
100
+ it 'should list values' do
101
+ @m.values.should.equal(%w{ A B C })
102
+ end
103
+
104
+ it 'should respond to merge (and return a Hash)' do
105
+ h = @m.merge('d' => 'D')
106
+ h.should.equal(::Hash[*%w{ a A b B c C d D }])
107
+ @m.size.should.equal(3)
108
+ end
109
+
110
+ it 'should respond to merge! (and return self)' do
111
+ r = @m.merge!('d' => 'D')
112
+ @m.size.should.equal(4)
113
+ r.should.equal(@m)
114
+ end
115
+ end
116
+
117
+ describe 'Rufus::Tokyo::Map, as an Enumerable,' do
118
+
119
+ before do
120
+ @m = Rufus::Tokyo::Map[%w{ a A b B c C }]
121
+ end
122
+ after do
123
+ @m.free
124
+ end
125
+
126
+ it 'should respond to collect' do
127
+ @m.inject('') { |s, (k, v)| s << "#{k}#{v}" }.should.equal('aAbBcC')
128
+ end
129
+ end
130
+
data/tasks/dev.rb ADDED
@@ -0,0 +1,70 @@
1
+ desc "tasks for handling extension libraries"
2
+ namespace :ext do
3
+
4
+ def git_repo
5
+ {
6
+ :cabinet => "git://github.com/etrepum/tokyo-cabinet.git",
7
+ :tyrant => "git://github.com/etrepum/tokyo-tyrant.git"
8
+ }
9
+ end
10
+
11
+ def extensions
12
+ [:cabinet, :tyrant]
13
+ end
14
+
15
+ def ext_root_path
16
+ File.expand_path(File.join(File.dirname(__FILE__), '..', 'ext'))
17
+ end
18
+
19
+ def ext_local_of type
20
+ File.join(ext_root_path, "tokyo-#{type}")
21
+ end
22
+
23
+ desc "creates the extensions build directory"
24
+ task :create do
25
+ mkdir_p ext_root_path
26
+ end
27
+
28
+ desc "removes the extensions build directory"
29
+ task :remove do
30
+ rm_rf ext_root_path
31
+ end
32
+
33
+ desc "builds the extensions, takes PREFIX for where to install"
34
+ task :build => [:create] do
35
+ extensions.each do |ext|
36
+ sh "cd #{ext_local_of ext} &&
37
+ ./configure --prefix=#{ENV['PREFIX'] || '/usr/local'} &&
38
+ make"
39
+ end
40
+ end
41
+
42
+ desc "installs the extensions [REQUIRES SUDO AND BUILD_ALL]"
43
+ task :install do
44
+ extensions.each do |ext|
45
+ sh "cd #{ext_local_of ext} && sudo make install"
46
+ end
47
+ end
48
+
49
+ desc "clones/pulls and builds all extensions, takes PREFIX for where to install"
50
+ task :build_all => [:create] + extensions + [:build]
51
+
52
+ desc "builds and installs all the extensions"
53
+ task :install_all => [:build_all, :install]
54
+
55
+ desc "update all the extensions"
56
+ task :update_all => extensions
57
+
58
+ extensions.each do |ext|
59
+ desc "clones and/or updates the etrepum/tokyo-#{ext} repo"
60
+ task ext => [:create] do
61
+ repo = ext_local_of ext
62
+ if ! File.directory?(repo)
63
+ sh "cd #{ext_root_path} && git clone #{git_repo[ext]}"
64
+ else
65
+ sh "cd #{repo} && git checkout master && git pull"
66
+ end
67
+ end
68
+ end
69
+
70
+ end
data/test/bm0.rb ADDED
@@ -0,0 +1,353 @@
1
+
2
+ #
3
+ # a bit of benchmarking
4
+ #
5
+ # some gists of runs :
6
+ #
7
+ # http://gist.github.com/60709
8
+ #
9
+
10
+ $:.unshift('lib')
11
+
12
+ require 'benchmark'
13
+
14
+ require 'date'
15
+ require 'fileutils'
16
+
17
+ require 'rubygems'
18
+
19
+
20
+ # Are the 'native'/'author' ruby bindings present ?
21
+
22
+ puts
23
+
24
+ begin
25
+ require 'tokyocabinet'
26
+ rescue LoadError
27
+ puts "Tokyo Cabinet 'native' ruby bindings not present"
28
+ end
29
+
30
+ begin
31
+ require 'tokyotyrant'
32
+ rescue LoadError
33
+ puts "Tokyo Tyrant 'native' ruby bindings not present"
34
+ end
35
+
36
+ begin
37
+ require 'memcache'
38
+ rescue LoadError
39
+ puts "\ngem memcache-client not present"
40
+ end
41
+
42
+ # moving on...
43
+
44
+ N = 10_000
45
+
46
+ puts
47
+ puts Time.now.to_s
48
+ puts "N is #{N}"
49
+ puts "ruby is #{RUBY_VERSION}"
50
+
51
+ # ==============================================================================
52
+ # bench methods
53
+ # ==============================================================================
54
+
55
+ #
56
+ # note : pre db.clear and post db.close are included.
57
+ #
58
+ def rufus_cabinet_bench (bench_title, db)
59
+
60
+ db.clear
61
+
62
+ 2.times { puts }
63
+ puts bench_title
64
+
65
+ Benchmark.benchmark(' ' * 31 + Benchmark::Tms::CAPTION, 31) do |b|
66
+
67
+ b.report('inserting one') do
68
+ db['a'] = 'A'
69
+ end
70
+ b.report('inserting N') do
71
+ N.times { |i| db["key #{i}"] = "value #{i}" }
72
+ end
73
+ b.report('finding all keys') do
74
+ db.keys
75
+ end
76
+
77
+ unless db.class.name.match(/^Rufus::Edo::/)
78
+ b.report('finding all keys (native)') do
79
+ db.keys(:native => true).free
80
+ end
81
+ end
82
+
83
+ b.report('finding all keys (pref)') do
84
+ db.keys(:prefix => 'key ')
85
+ end
86
+ b.report('finding all keys (r pref)') do
87
+ db.keys.select { |k| k[0, 4] == 'key ' }
88
+ end
89
+ b.report('finding all') do
90
+ db.values
91
+ end
92
+ b.report('iterate all') do
93
+ db.each { |k, v| }
94
+ end
95
+ b.report('find first') do
96
+ db["key #{0}"]
97
+ end
98
+ b.report('delete first') do
99
+ db.delete("key #{0}")
100
+ end
101
+
102
+ txt = 'delete_keys_with_prefix "1"'
103
+ txt += ' (M)' if db.class.name == 'Rufus::Edo::Cabinet'
104
+ b.report(txt) do
105
+ db.delete_keys_with_prefix('key 1')
106
+ end
107
+
108
+ b.report('del keys with prefix "2" (m)') do
109
+ ks = db.keys(:prefix => 'key 2')
110
+ ks.each { |k| db.delete(k) }
111
+ end
112
+ end
113
+
114
+ db.close
115
+ end
116
+
117
+ # = table ==
118
+
119
+ puts "\npreparing fake data for table tests..."
120
+
121
+ require 'faker'
122
+
123
+ DATA = (0..N - 1).collect { |i|
124
+ {
125
+ 'name' => Faker::Name.name,
126
+ 'sex' => (i % 2) ? 'male' : 'female',
127
+ 'birthday' => DateTime.new(1972, 10, 14),
128
+ 'divisions' => (i % 2) ? 'brd' : 'dev'
129
+ }
130
+ }
131
+
132
+ DATA1 = DATA.collect { |e|
133
+ h = e.dup
134
+ h['birthday'] = h['birthday'].to_s
135
+ h
136
+ }
137
+ # Tokyo Cabinet tables only do strings
138
+
139
+
140
+ # = memcache ===
141
+
142
+ #
143
+ # tiny test for memcache_client gem
144
+ #
145
+ # note : space is an illegal char in keys here !
146
+ #
147
+ def limited_bench (bench_title, db)
148
+
149
+ 2.times { puts }
150
+ puts bench_title
151
+
152
+ Benchmark.benchmark(' ' * 31 + Benchmark::Tms::CAPTION, 31) do |b|
153
+
154
+ b.report('inserting one') do
155
+ db['a'] = 'A'
156
+ end
157
+ b.report('inserting N') do
158
+ N.times { |i| db["key#{i}"] = "value #{i}" }
159
+ end
160
+ b.report('find first') do
161
+ db["key#{0}"]
162
+ end
163
+ b.report('delete first') do
164
+ db.delete("key#{0}")
165
+ end
166
+ end
167
+ end
168
+
169
+
170
+ #
171
+ # note : pre db.clear and post db.close are included.
172
+ #
173
+ def rufus_table_bench (bench_title, db)
174
+
175
+ 2.times { puts }
176
+ puts bench_title
177
+
178
+ Benchmark.benchmark(' ' * 31 + Benchmark::Tms::CAPTION, 31) do |b|
179
+
180
+ db.clear
181
+
182
+ db.clear
183
+ db.set_index('name', :lexical)
184
+
185
+ b.report('inserting data (index set)') do
186
+ DATA1.each_with_index { |e, i| db["key #{i.to_s}"] = e }
187
+ end
188
+
189
+ db.clear
190
+ db.set_index('name', :remove)
191
+
192
+ b.report('inserting data (no index)') do
193
+ DATA1.each_with_index { |e, i| db["key #{i.to_s}"] = e }
194
+ end
195
+
196
+ b.report('finding all keys') do
197
+ db.keys
198
+ end
199
+ b.report('finding all keys (pref)') do
200
+ db.keys(:prefix => 'key ')
201
+ end
202
+ b.report('finding all keys (r pref)') do
203
+ db.keys.select { |k| k[0, 4] == 'key ' }
204
+ end
205
+ b.report('finding all') do
206
+ db.query { |q| }
207
+ end
208
+ b.report('find last') do
209
+ db["key #{DATA.size.to_s}"]
210
+ end
211
+ b.report('delete last') do
212
+ db.delete("key #{DATA.size.to_s}")
213
+ end
214
+ b.report('find Alphonse') do
215
+ db.query { |q| q.add('name', :equals, DATA1[0]['name']) }
216
+ end
217
+
218
+ b.report("setting index (#{DATA.size} rows)") do
219
+ db.set_index('name', :lexical)
220
+ end
221
+
222
+ b.report('find Alphonse (index set)') do
223
+ db.query { |q| q.add('name', :equals, DATA1[0]['name']) }
224
+ end
225
+
226
+ b.report('delete_keys_with_prefix "1"') do
227
+ db.delete_keys_with_prefix('key 1')
228
+ end
229
+ #b.report('del keys with prefix "2" (m)') do
230
+ # ks = db.keys(:prefix => 'key 2')
231
+ # ks.each { |k| db.delete(k) }
232
+ #end
233
+ end
234
+
235
+ db.close
236
+ end
237
+
238
+ # ==============================================================================
239
+ # hashes
240
+ # ==============================================================================
241
+
242
+ #
243
+ # Tokyo Cabinet ===============================================================
244
+ #
245
+
246
+ require 'rufus/tokyo'
247
+
248
+ FileUtils.rm_f('tmp/test.tch')
249
+
250
+ rufus_cabinet_bench('TC', Rufus::Tokyo::Cabinet.new('tmp/test.tch'))
251
+
252
+ #
253
+ # 'native' ruby bindings
254
+ #
255
+
256
+ FileUtils.rm_f('tmp/test.tch')
257
+
258
+ if defined?(TokyoCabinet)
259
+
260
+ require 'rufus/edo'
261
+
262
+ rufus_cabinet_bench('Edo TC', Rufus::Edo::Cabinet.new('tmp/test.tch'))
263
+ end
264
+
265
+
266
+ #
267
+ # Tokyo Tyrant ================================================================
268
+ #
269
+
270
+ require 'rufus/tokyo/tyrant'
271
+
272
+ rufus_cabinet_bench('TT', Rufus::Tokyo::Tyrant.new('127.0.0.1', 45000))
273
+
274
+
275
+ #
276
+ # 'native' Tokyo Tyrant ========================================================
277
+ #
278
+
279
+ if defined?(TokyoTyrant)
280
+
281
+ require 'rufus/edo/ntyrant'
282
+
283
+ rufus_cabinet_bench('net TT', Rufus::Edo::NetTyrant.new('127.0.0.1', 45000))
284
+ end
285
+
286
+
287
+ if defined?(MemCache)
288
+
289
+ db = MemCache.new(
290
+ :compression => false,
291
+ :readonly => false,
292
+ :debug => false)
293
+ db.servers = [ '127.0.0.1:45000' ]
294
+
295
+ limited_bench('TT over memcache-client', db)
296
+
297
+ db = MemCache.new(
298
+ :compression => true,
299
+ :readonly => false,
300
+ :debug => false)
301
+ db.servers = [ '127.0.0.1:45000' ]
302
+
303
+ limited_bench('TT over memcache-client (:compression => true)', db)
304
+ end
305
+
306
+
307
+ # ==============================================================================
308
+ # tables
309
+ # ==============================================================================
310
+
311
+ #
312
+ # Tokyo Cabinet table =========================================================
313
+ #
314
+
315
+ FileUtils.rm_f('tmp/test.tct')
316
+
317
+ rufus_table_bench('TC table', Rufus::Tokyo::Table.new('tmp/test.tct'))
318
+
319
+
320
+ #
321
+ # 'native' Tokyo Cabinet table =================================================
322
+ #
323
+
324
+ FileUtils.rm_f('tmp/test.tct')
325
+
326
+
327
+ if defined?(TokyoCabinet)
328
+
329
+ require 'rufus/edo'
330
+
331
+ rufus_table_bench('Edo TC table', Rufus::Edo::Table.new('tmp/test.tct'))
332
+ end
333
+
334
+ #
335
+ # Tokyo Tyrant table ===========================================================
336
+ #
337
+
338
+ rufus_table_bench(
339
+ 'TT table', Rufus::Tokyo::TyrantTable.new('localhost', 45001))
340
+
341
+
342
+ #
343
+ # 'author' Tokyo Tyrant table ==================================================
344
+ #
345
+
346
+ if defined?(TokyoTyrant)
347
+
348
+ rufus_table_bench(
349
+ "net TT table", Rufus::Edo::NetTyrantTable.new('127.0.0.1', 45001))
350
+ end
351
+
352
+ puts
353
+