ls4 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +661 -0
  3. data/ChangeLog +9 -0
  4. data/NOTICE +8 -0
  5. data/README.rdoc +61 -0
  6. data/bin/ls4-cs +3 -0
  7. data/bin/ls4-ds +3 -0
  8. data/bin/ls4-gw +3 -0
  9. data/bin/ls4-standalone +3 -0
  10. data/bin/ls4cmd +3 -0
  11. data/bin/ls4ctl +3 -0
  12. data/bin/ls4rpc +3 -0
  13. data/bin/ls4stat +3 -0
  14. data/bin/ls4top +3 -0
  15. data/lib/ls4/command/cmd.rb +241 -0
  16. data/lib/ls4/command/cs.rb +190 -0
  17. data/lib/ls4/command/ctl.rb +278 -0
  18. data/lib/ls4/command/ds.rb +335 -0
  19. data/lib/ls4/command/gw.rb +256 -0
  20. data/lib/ls4/command/rpc.rb +172 -0
  21. data/lib/ls4/command/standalone.rb +318 -0
  22. data/lib/ls4/command/stat.rb +244 -0
  23. data/lib/ls4/command/top.rb +291 -0
  24. data/lib/ls4/default.rb +26 -0
  25. data/lib/ls4/lib/cclog.rb +220 -0
  26. data/lib/ls4/lib/ebus.rb +553 -0
  27. data/lib/ls4/lib/vbcode.rb +228 -0
  28. data/lib/ls4/logic/fault_detector.rb +212 -0
  29. data/lib/ls4/logic/membership.rb +253 -0
  30. data/lib/ls4/logic/node.rb +66 -0
  31. data/lib/ls4/logic/okey.rb +45 -0
  32. data/lib/ls4/logic/tsv_data.rb +81 -0
  33. data/lib/ls4/logic/weight.rb +166 -0
  34. data/lib/ls4/service/balance.rb +62 -0
  35. data/lib/ls4/service/base.rb +29 -0
  36. data/lib/ls4/service/bus.rb +37 -0
  37. data/lib/ls4/service/config.rb +63 -0
  38. data/lib/ls4/service/config_cs.rb +33 -0
  39. data/lib/ls4/service/config_ds.rb +56 -0
  40. data/lib/ls4/service/config_gw.rb +42 -0
  41. data/lib/ls4/service/data_client.rb +122 -0
  42. data/lib/ls4/service/data_server.rb +168 -0
  43. data/lib/ls4/service/data_server_url.rb +83 -0
  44. data/lib/ls4/service/gateway.rb +375 -0
  45. data/lib/ls4/service/gateway_ro.rb +91 -0
  46. data/lib/ls4/service/gw_http.rb +821 -0
  47. data/lib/ls4/service/heartbeat.rb +182 -0
  48. data/lib/ls4/service/log.rb +81 -0
  49. data/lib/ls4/service/master_select.rb +148 -0
  50. data/lib/ls4/service/mds.rb +292 -0
  51. data/lib/ls4/service/mds_cache.rb +294 -0
  52. data/lib/ls4/service/mds_cache_mem.rb +63 -0
  53. data/lib/ls4/service/mds_cache_memcached.rb +65 -0
  54. data/lib/ls4/service/mds_ha.rb +176 -0
  55. data/lib/ls4/service/mds_memcache.rb +209 -0
  56. data/lib/ls4/service/mds_tc.rb +508 -0
  57. data/lib/ls4/service/mds_tt.rb +472 -0
  58. data/lib/ls4/service/membership.rb +331 -0
  59. data/lib/ls4/service/process.rb +90 -0
  60. data/lib/ls4/service/rpc.rb +50 -0
  61. data/lib/ls4/service/rpc_cs.rb +101 -0
  62. data/lib/ls4/service/rpc_ds.rb +96 -0
  63. data/lib/ls4/service/rpc_gw.rb +255 -0
  64. data/lib/ls4/service/rts.rb +94 -0
  65. data/lib/ls4/service/rts_file.rb +76 -0
  66. data/lib/ls4/service/rts_memory.rb +55 -0
  67. data/lib/ls4/service/slave.rb +132 -0
  68. data/lib/ls4/service/stat.rb +91 -0
  69. data/lib/ls4/service/stat_cs.rb +25 -0
  70. data/lib/ls4/service/stat_ds.rb +40 -0
  71. data/lib/ls4/service/stat_gw.rb +25 -0
  72. data/lib/ls4/service/storage.rb +116 -0
  73. data/lib/ls4/service/storage_dir.rb +201 -0
  74. data/lib/ls4/service/sync.rb +206 -0
  75. data/lib/ls4/service/time_check.rb +80 -0
  76. data/lib/ls4/service/ulog.rb +159 -0
  77. data/lib/ls4/service/ulog_file.rb +398 -0
  78. data/lib/ls4/service/ulog_memory.rb +53 -0
  79. data/lib/ls4/service/weight.rb +134 -0
  80. data/lib/ls4/version.rb +5 -0
  81. data/test/01_add_get_remove.rt +84 -0
  82. data/test/02_read.rt +61 -0
  83. data/test/03_getd_readd.rt +69 -0
  84. data/test/04_version_time.rt +170 -0
  85. data/test/05_version_name.rt +161 -0
  86. data/test/06_http_get_set_remove_1.rt +119 -0
  87. data/test/07_http_get_set_remove_2.rt +116 -0
  88. data/test/08_read_only_time.rt +177 -0
  89. data/test/09_read_only_name.rt +173 -0
  90. data/test/10_http_get_set_remove_3.rt +73 -0
  91. data/test/11_mds_cache_memcached.rt +88 -0
  92. data/test/12_mds_cache_local_memory.rt +86 -0
  93. data/test/13_memcache_mds.rt +84 -0
  94. data/test/14_delete.rt +63 -0
  95. data/test/15_standalone.rt +71 -0
  96. data/test/chukan.rb +516 -0
  97. data/test/common.rb +250 -0
  98. data/test/load_test.rb +79 -0
  99. data/test/load_test_offload.rb +86 -0
  100. metadata +295 -0
@@ -0,0 +1,472 @@
1
+ #
2
+ # LS4
3
+ # Copyright (C) 2010-2011 FURUHASHI Sadayuki
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU Affero General Public License as
7
+ # published by the Free Software Foundation, either version 3 of the
8
+ # License, or (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU Affero General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Affero General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ #
18
+ module LS4
19
+
20
+
21
+ class TokyoTyrantMDS < MDS
22
+ MDSSelector.register(:tt, self)
23
+
24
+ COL_PK = ''
25
+ COL_KEY = '_key'
26
+ COL_VTIME = '_time'
27
+ COL_RSID = '_rsid'
28
+ COL_VNAME = '_vname'
29
+ COL_REMOVED = '_removed'
30
+
31
+ COLS_RESERVED = [COL_PK, COL_KEY, COL_VTIME, COL_RSID, COL_VNAME, COL_REMOVED]
32
+ COLS_REQUIRED = [COL_PK, COL_KEY, COL_VTIME, COL_RSID]
33
+
34
+ def self.define_consts
35
+ unless const_defined?(:QRY)
36
+ require 'tokyotyrant'
37
+ const_set(:QRY, TokyoTyrant::RDBQRY)
38
+ HADB.const_set(:TBL, TokyoTyrant::RDBTBL)
39
+ HADB.const_set(:FATAL_ERROR, [
40
+ TokyoTyrant::RDB::EINVALID,
41
+ TokyoTyrant::RDB::ENOHOST,
42
+ TokyoTyrant::RDB::EREFUSED,
43
+ TokyoTyrant::RDB::ESEND,
44
+ TokyoTyrant::RDB::ERECV,
45
+ TokyoTyrant::RDB::EMISC
46
+ ])
47
+ end
48
+ end
49
+
50
+ class HADB < BasicHADB
51
+ DEFAULT_PORT = 1978
52
+
53
+ def open_db(addr)
54
+ db = TBL.new
55
+ db.instance_eval("@enc = 'ASCII-8BIT'") # FIXME
56
+ unless db.open(*addr)
57
+ $log.warn "failed to connect TokyoTyrant MDS: #{addr}"
58
+ end
59
+ db.setindex(COL_KEY, TBL::ITLEXICAL)
60
+ db
61
+ end
62
+
63
+ def ensure_db(db, addr)
64
+ if FATAL_ERROR.include?(db.ecode)
65
+ db.close rescue nil
66
+ db.instance_eval("@ecode = ESUCCESS") # FIXME
67
+ db.open(*addr)
68
+ end
69
+ return db
70
+ rescue
71
+ return nil
72
+ end
73
+
74
+ def error_result?(db, result)
75
+ if FATAL_ERROR.include?(db.ecode)
76
+ return db.errmsg(db.ecode)
77
+ end
78
+ return nil
79
+ end
80
+ end
81
+
82
+ if defined?(Random)
83
+ def initialize
84
+ self.class.define_consts
85
+ @random = Random.new
86
+ @pid = Process.pid
87
+ end
88
+ else
89
+ # Ruby 1.8
90
+ class PseudoRandom
91
+ def rand(n)
92
+ Kernel::rand(n)
93
+ end
94
+ end
95
+ def initialize
96
+ self.class.define_consts
97
+ @random = PseudoRandom.new
98
+ @pid = Process.pid
99
+ end
100
+ end
101
+
102
+ def open(expr)
103
+ @hadb = HADB.new(expr)
104
+ end
105
+
106
+ def close
107
+ @hadb.close
108
+ end
109
+
110
+ def get_okey(key, version=nil, &cb)
111
+ map = get_impl(key, version, COLS_RESERVED)
112
+ if map && !is_removed(map)
113
+ okey = to_okey(map)
114
+ cb.call(okey, nil) rescue nil
115
+ else
116
+ cb.call(nil, nil) rescue nil
117
+ end
118
+ rescue
119
+ cb.call(nil, $!) rescue nil
120
+ end
121
+
122
+ def get_attrs(key, version=nil, &cb)
123
+ map = get_impl(key, version)
124
+ if map && !is_removed(map)
125
+ attrs = to_attrs(map)
126
+ cb.call(attrs, nil) rescue nil
127
+ else
128
+ cb.call(nil, nil) rescue nil
129
+ end
130
+ rescue
131
+ cb.call(nil, $!) rescue nil
132
+ end
133
+
134
+ def get_okey_attrs(key, version=nil, &cb)
135
+ map = get_impl(key, version)
136
+ if map && !is_removed(map)
137
+ okey = to_okey(map)
138
+ attrs = to_attrs(map)
139
+ cb.call([okey, attrs], nil) rescue nil
140
+ else
141
+ cb.call(nil, nil) rescue nil
142
+ end
143
+ rescue
144
+ cb.call(nil, $!) rescue nil
145
+ end
146
+
147
+ def add(key, attrs={}, vname=nil, &cb)
148
+ okey = add_impl(key, attrs, vname)
149
+ cb.call(okey, nil) rescue nil
150
+ rescue
151
+ cb.call(nil, $!) rescue nil
152
+ end
153
+
154
+ def update_attrs(key, attrs, &cb)
155
+ okey = update_impl(key) {|old_attrs|
156
+ attrs
157
+ }
158
+ cb.call(okey, nil) rescue nil
159
+ rescue
160
+ cb.call(nil, $!) rescue nil
161
+ end
162
+
163
+ #def merge_attrs(key, attrs, &cb)
164
+ # okey = update_impl(key) {|old_attrs|
165
+ # old_attrs.merge(attrs)
166
+ # }
167
+ # cb.call(okey, nil) rescue nil
168
+ #rescue
169
+ # cb.call(nil, $!) rescue nil
170
+ #end
171
+
172
+ def remove(key, &cb)
173
+ map = get_impl_head(key, COLS_REQUIRED)
174
+ if map && !is_removed(map)
175
+ okey = to_okey(map)
176
+
177
+ # optional: inherit rsid
178
+ rsid = map[COL_RSID].to_i
179
+
180
+ # get current vtime later than old vtime
181
+ vtime = get_current_vtime(map[COL_VTIME].to_i)
182
+
183
+ remove_okey = new_okey(key, vtime, rsid)
184
+
185
+ # insert
186
+ pk = new_pk(map[COL_PK])
187
+ map = to_map({}, remove_okey, nil, true)
188
+ @hadb.write(key) {|rdb| rdb.put(pk, map) }
189
+
190
+ cb.call(okey, nil) rescue nil
191
+
192
+ else
193
+ cb.call(nil, nil) rescue nil
194
+ end
195
+
196
+ rescue
197
+ cb.call(nil, $!) rescue nil
198
+ end
199
+
200
+ def delete(key, version=nil, &cb)
201
+ map = get_impl(key, version, COLS_RESERVED)
202
+ if map && !is_removed(map)
203
+ okey = to_okey(map)
204
+
205
+ pk = map[COL_PK]
206
+ @hadb.write(key) {|rdb| rdb.delete(pk) }
207
+
208
+ cb.call(okey, nil) rescue nil
209
+
210
+ else
211
+ cb.call(nil, nil) rescue nil
212
+ end
213
+ rescue
214
+ cb.call(nil, $!) rescue nil
215
+ end
216
+
217
+ def util_locate(key, &cb)
218
+ array = @hadb.read(key) {|rdb|
219
+ qry = QRY.new(rdb)
220
+ qry.addcond(COL_KEY, QRY::QCSTREQ, key)
221
+ qry.searchget(COLS_RESERVED)
222
+ }
223
+
224
+ array.reject! {|map|
225
+ !is_valid_map(map) || is_removed(map)
226
+ }
227
+
228
+ array.map! {|map|
229
+ [to_okey(map), map[COL_VNAME]]
230
+ }
231
+
232
+ cb.call(array, nil) rescue nil
233
+
234
+ rescue
235
+ cb.call(nil, $!) rescue nil
236
+ end
237
+
238
+ private
239
+ def to_okey(map)
240
+ key = map[COL_KEY]
241
+ rsid = map[COL_RSID].to_i
242
+ vtime = map[COL_VTIME].to_i
243
+ new_okey(key, vtime, rsid)
244
+ end
245
+
246
+ def to_attrs(map)
247
+ map.reject {|k,v| COLS_RESERVED.include?(k) }
248
+ end
249
+
250
+ def to_map(attrs, okey, vname=nil, removed=false)
251
+ map = attrs.dup
252
+ map.delete(COL_PK)
253
+ map[COL_KEY] = okey.key
254
+ map[COL_RSID] = okey.rsid.to_s
255
+ map[COL_VTIME] = okey.vtime.to_s
256
+ if vname
257
+ map[COL_VNAME] = vname.to_s
258
+ end
259
+ if removed
260
+ map[COL_REMOVED] = "1"
261
+ end
262
+ map
263
+ end
264
+
265
+ def get_impl(key, version=nil, cols=nil)
266
+ if version == nil
267
+ get_impl_head(key, cols)
268
+ elsif version.is_a?(String)
269
+ get_impl_vname(key, version, cols)
270
+ else
271
+ get_impl_vtime(key, version, cols)
272
+ end
273
+ end
274
+
275
+ def get_impl_head(key, cols=nil)
276
+ map = @hadb.read(key) {|rdb|
277
+ qry = QRY.new(rdb)
278
+ qry.addcond(COL_KEY, QRY::QCSTREQ, key)
279
+ qry.setorder(COL_VTIME, QRY::QONUMDESC)
280
+ qry.setlimit(1)
281
+ array = qry.searchget(cols)
282
+ array[0]
283
+ }
284
+
285
+ if map == nil
286
+ return nil
287
+ elsif !is_valid_map(map)
288
+ return nil
289
+ else
290
+ return map
291
+ end
292
+ end
293
+
294
+ def get_impl_vname(key, vname, cols=nil)
295
+ map = @hadb.read(key) {|rdb|
296
+ qry = QRY.new(rdb)
297
+ qry.addcond(COL_KEY, QRY::QCSTREQ, key)
298
+ qry.addcond(COL_VNAME, QRY::QCSTREQ, vname)
299
+ qry.setorder(COL_VTIME, QRY::QONUMDESC)
300
+ qry.setlimit(1)
301
+ array = qry.searchget(cols)
302
+ array[0]
303
+ }
304
+
305
+ if map == nil
306
+ return nil
307
+ elsif !is_valid_map(map)
308
+ return nil
309
+ else
310
+ return map
311
+ end
312
+ end
313
+
314
+ def get_impl_vtime(key, vtime, cols)
315
+ map = @hadb.read(key) {|rdb|
316
+ qry = QRY.new(rdb)
317
+ qry.addcond(COL_KEY, QRY::QCSTREQ, key)
318
+ qry.addcond(COL_VTIME, QRY::QCNUMLE, vtime.to_s)
319
+ qry.setorder(COL_VTIME, QRY::QONUMDESC)
320
+ qry.setlimit(1)
321
+ array = qry.searchget(cols)
322
+ array[0]
323
+ }
324
+
325
+ if map == nil
326
+ return nil
327
+ elsif !is_valid_map(map)
328
+ return nil
329
+ else
330
+ return map
331
+ end
332
+ end
333
+
334
+ #def select_latest_valid(array)
335
+ # latest = select_latest(array)
336
+ # if is_valid_map(latest)
337
+ # return latest
338
+ # else
339
+ # return nil
340
+ # end
341
+ #end
342
+
343
+ #def select_latest(array)
344
+ # if array.size == 1
345
+ # return array[0]
346
+ # end
347
+ #
348
+ # max_vtime = 0
349
+ # marray = []
350
+ #
351
+ # array.each {|map|
352
+ # vtime = map[COL_VTIME].to_i
353
+ # if max_vtime < vtime
354
+ # marray.clear
355
+ # marray << map
356
+ # max_vtime = vtime
357
+ # elsif max_vtime == vtime
358
+ # marray << map
359
+ # end
360
+ # }
361
+ #
362
+ # if marray.size == 1
363
+ # return marray[0]
364
+ # else
365
+ # return marray.sort_by {|map| map[COL_PK] }.last
366
+ # end
367
+ #end
368
+
369
+ def is_valid_map(map)
370
+ COLS_REQUIRED.all? {|col| map.has_key?(col) }
371
+ end
372
+
373
+ def is_removed(map)
374
+ map.has_key?(COL_REMOVED)
375
+ end
376
+
377
+ def add_impl(key, attrs, vname=nil)
378
+ map = get_impl_head(key, COLS_REQUIRED)
379
+
380
+ if map
381
+ # optional: inherit rsid
382
+ rsid = map[COL_RSID].to_i
383
+
384
+ # get current vtime later than old vtime
385
+ vtime = get_current_vtime(map[COL_VTIME].to_i)
386
+
387
+ okey = new_okey(key, vtime, rsid)
388
+
389
+ # insert
390
+ pk = new_pk(map[COL_PK])
391
+ map = to_map(attrs, okey, vname)
392
+ @hadb.write(key) {|rdb| rdb.put(pk, map) }
393
+
394
+ else
395
+ attrs ||= {}
396
+
397
+ okey = new_okey(key)
398
+
399
+ # insert
400
+ pk = new_pk()
401
+ map = to_map(attrs, okey, vname)
402
+ @hadb.write(key) {|rdb| rdb.put(pk, map) }
403
+ end
404
+
405
+ return okey
406
+ end
407
+
408
+ def update_impl(key, &modifier)
409
+ map = get_impl_head(key, nil)
410
+
411
+ if map && !is_removed(map)
412
+ okey = to_okey(map)
413
+
414
+ # create new attrs
415
+ attrs = modifier.call( to_attrs(map) )
416
+
417
+ # reject old attributes
418
+ map.reject! {|k,v| !COLS_RESERVED.include?(k) }
419
+
420
+ # merge new attributes
421
+ map = attrs.merge(map)
422
+
423
+ # update
424
+ pk = map.delete(COL_PK)
425
+ @hadb.write(key) {|rdb| rdb.put(pk, map) }
426
+
427
+ return okey
428
+
429
+ else
430
+ return nil
431
+ end
432
+ end
433
+
434
+ # +----------+----+------+---+
435
+ # | 30 | 10 | 16 | 8 |
436
+ # +----------+----+------+---+
437
+ # UNIX time
438
+ # millisec
439
+ # rand
440
+ # generator-id
441
+ # +--------------------------+
442
+ # 64 bits
443
+ #
444
+ def new_pk(at_least=nil)
445
+ nowtime = Time.now.utc
446
+ sec = nowtime.sec
447
+ msec = nowtime.usec / 1000
448
+
449
+ if at_least && at_least.size == 8
450
+ time_u, time_d = at_least.unpack('NC')
451
+ asec = time_u>>2
452
+ amsec = (time_u&0x3)<<2 & time_d
453
+ if sec < asec || (sec == asec && msec <= amsec)
454
+ sec = asec + 1
455
+ msec = amsec
456
+ end
457
+ end
458
+
459
+ gid = @pid
460
+
461
+ r = @random.rand(2**16)
462
+ raw = [sec<<2|msec>>8, msec&0xff, r, gid].pack('NCnC')
463
+
464
+ # FIXME base64
465
+ raw = [raw].pack('m')
466
+ raw.gsub!(/[\n\=]+/,'')
467
+ raw
468
+ end
469
+ end
470
+
471
+
472
+ end