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,182 @@
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 HeartbeatResponse
22
+ def initialize(term=nil, sync_needed=nil)
23
+ @term = term
24
+ @sync_needed = sync_needed
25
+ end
26
+
27
+ attr_accessor :term
28
+ attr_accessor :sync_needed
29
+
30
+ public
31
+ def to_msgpack(out = '')
32
+ [@term, @sync_needed].to_msgpack(out)
33
+ end
34
+ def from_msgpack(obj)
35
+ @term = obj[0]
36
+ @sync_needed = obj[1]
37
+ self
38
+ end
39
+ end
40
+
41
+
42
+ class HeartbeatServerService < Service
43
+ def initialize
44
+ super
45
+ @syncs = []
46
+ end
47
+
48
+ def rpc_heartbeat(nid, sync_hash)
49
+ hbres = HeartbeatResponse.new
50
+
51
+ if nid
52
+ hbres.term = MembershipBus.reset_fault_detector(nid)
53
+ end
54
+
55
+ if sync_hash
56
+ if SyncBus.check_hash(sync_hash)
57
+ hbres.sync_needed = false
58
+ else
59
+ hbres.sync_needed = true
60
+ end
61
+ end
62
+
63
+ hbres
64
+ end
65
+
66
+ ebus_connect :CSRPCBus,
67
+ :heartbeat => :rpc_heartbeat
68
+ end
69
+
70
+
71
+ class HeartbeatClientService < Service
72
+ def initialize
73
+ @heartbeat_nid = nil
74
+ end
75
+
76
+ #def get_cs_session
77
+ # ProcessBus.get_session(ConfigBus.get_cs_address)
78
+ #end
79
+ #
80
+ #def on_timer
81
+ # do_heartbeat
82
+ #end
83
+ #
84
+ #def do_heartbeat
85
+ # sync_hash = SyncBus.get_hash
86
+ # get_cs_session.callback(:heartbeat, @heartbeat_nid, sync_hash) do |future|
87
+ # begin
88
+ # hbres = HeartbeatResponse.new.from_msgpack(future.get)
89
+ # ack_heartbeat(hbres)
90
+ # rescue
91
+ # $log.error "heartbeat error: #{$!}"
92
+ # $log.error_backtrace $!.backtrace
93
+ # end
94
+ # end
95
+ #end
96
+ #
97
+ #def ack_heartbeat(hbres)
98
+ # if hbres.sync_needed
99
+ # SyncBus.try_sync
100
+ # end
101
+ #end
102
+ #
103
+ #ebus_connect :ProcessBus,
104
+ # :on_timer
105
+ #
106
+ #def heartbeat_blocking!
107
+ # do_heartbeat.join
108
+ #end
109
+
110
+ def run
111
+ @cs = MessagePack::RPC::Client.new(*ConfigBus.get_cs_address)
112
+ @end = false
113
+ @thread = Thread.new do
114
+ while !@end
115
+ sleep 1
116
+ do_heartbeat_blocking
117
+ end
118
+ end
119
+ end
120
+
121
+ def shutdown
122
+ @end = true
123
+ #@thread.join
124
+ @cs.close
125
+ end
126
+
127
+ def do_heartbeat_blocking
128
+ sync_hash = SyncBus.get_hash
129
+ begin
130
+ res = @cs.call(:heartbeat, @heartbeat_nid, sync_hash)
131
+ hbres = HeartbeatResponse.new.from_msgpack(res)
132
+ if hbres.sync_needed
133
+ ProcessBus.submit {
134
+ SyncBus.try_sync
135
+ }
136
+ end
137
+ rescue
138
+ $log.error "heartbeat error: #{$!}"
139
+ $log.error_backtrace $!.backtrace
140
+ end
141
+ nil
142
+ end
143
+
144
+ def heartbeat_blocking!
145
+ do_heartbeat_blocking
146
+ end
147
+
148
+ ebus_connect :ProcessBus,
149
+ :run,
150
+ :shutdown
151
+ end
152
+
153
+
154
+ class HeartbeatMemberService < HeartbeatClientService
155
+ def initialize
156
+ super
157
+ @heartbeat_nid = ConfigBus.self_nid
158
+ end
159
+
160
+ #def ack_heartbeat(hbres)
161
+ # super
162
+ #
163
+ # if hbres.term
164
+ # # do nothing
165
+ # else
166
+ # # MembershipMemberService
167
+ # #register_self
168
+ # end
169
+ #
170
+ # MembershipBus.try_register_node
171
+ #end
172
+
173
+ def on_timer
174
+ MembershipBus.try_register_node
175
+ end
176
+
177
+ ebus_connect :ProcessBus,
178
+ :on_timer
179
+ end
180
+
181
+
182
+ end
@@ -0,0 +1,81 @@
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
+ $log = CCLog.new(CCLog::LEVEL_INFO)
22
+
23
+
24
+ class LogService < Service
25
+ def initialize
26
+ @out = nil
27
+ end
28
+
29
+ def self.open!
30
+ init.open
31
+ end
32
+
33
+ def open
34
+ if path = ConfigBus.get_log_path
35
+ out = File.open(path, "a")
36
+ @out = $log.out = out
37
+ end
38
+ end
39
+
40
+ def on_sighup
41
+ if path = ConfigBus.get_log_path
42
+ out = File.open(path, "a")
43
+ if @out
44
+ @out.close
45
+ @out = nil
46
+ end
47
+ @out = $log.out = out
48
+ end
49
+ end
50
+
51
+ def shutdown
52
+ if @out
53
+ @out.close
54
+ @out = nil
55
+ end
56
+ end
57
+
58
+ def log_event_bus
59
+ $log.on_trace do
60
+ LS4.constants.each {|const|
61
+ klass = LS4.const_get(const)
62
+ if klass.is_a?(Class) && klass < Bus
63
+ bus = klass
64
+ name = bus.name.gsub('LS4::','')
65
+ $log.trace name
66
+ bus.ebus_all_slots.each {|s|
67
+ s = s.to_s.gsub('LS4::','')
68
+ $log.trace " #{s}"
69
+ }
70
+ end
71
+ }
72
+ end
73
+ end
74
+
75
+ ebus_connect :ProcessBus,
76
+ :shutdown,
77
+ :on_sighup
78
+ end
79
+
80
+
81
+ end
@@ -0,0 +1,148 @@
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 MasterSelectBus < Bus
22
+ call_slot :select_master
23
+ call_slot :select_master_static
24
+ signal_slot :update_nodes
25
+ end
26
+
27
+
28
+ class LocationAwareMasterSelectService < Service
29
+ def initialize
30
+ @map = {} # { rsid => [nids] }
31
+ @self_location = ConfigBus.self_location
32
+ end
33
+
34
+ def update_nodes(nodes=nil)
35
+ nodes ||= MembershipBus.get_all_nodes
36
+
37
+ rsid_nodes = {}
38
+ nodes.each {|node|
39
+ node.rsids.each {|rsid|
40
+ (rsid_nodes[rsid] ||= []) << node
41
+ }
42
+ }
43
+
44
+ rsid_loc_nids = {}
45
+ rsid_nodes.each_pair {|rsid,nodes|
46
+ loc_grouped = nodes.group_by {|node| node.location }
47
+
48
+ sorted = loc_grouped.to_a.sort_by {|loc,nodes| loc }
49
+ if idx = sorted.find_index {|loc,nodes| loc == @self_location }
50
+ sorted = rotate(sorted, idx)
51
+ end
52
+
53
+ loc_nids = sorted.map {|loc,nodes|
54
+ nids = nodes.map {|node| node.nid }
55
+ nids.sort
56
+ }
57
+
58
+ rsid_loc_nids[rsid] = loc_nids
59
+ }
60
+
61
+ @map = rsid_loc_nids
62
+ end
63
+
64
+ def select_master(rsid, key)
65
+ loc_nodes = @map[rsid]
66
+ unless loc_nodes
67
+ raise "no such rsid: #{rsid}"
68
+ end
69
+ digest = Digest::MD5.digest(key)
70
+ i = digest.unpack('C')[0]
71
+ loc_nodes.map {|nodes| rotate(nodes, i) }.flatten
72
+ end
73
+
74
+ def select_master_static(rsid)
75
+ loc_nodes = @map[rsid]
76
+ unless loc_nodes
77
+ raise "no such rsid: #{rsid}"
78
+ end
79
+ loc_nodes.flatten
80
+ end
81
+
82
+ ebus_connect :MasterSelectBus,
83
+ :select_master,
84
+ :select_master_static,
85
+ :update_nodes
86
+
87
+ private
88
+ def rotate(array, i)
89
+ n = i % array.size
90
+ return array[-n,n] + array[0, array.size-n]
91
+ end
92
+ end
93
+
94
+
95
+ class FlatMasterSelectService < Service
96
+ def initialize
97
+ @map = {} # { rsid => nids }
98
+ end
99
+
100
+ def update_nodes(nodes=nil)
101
+ nodes ||= MembershipBus.get_all_nodes
102
+
103
+ rsid_nids = {}
104
+ nodes.each {|node|
105
+ node.rsids.each {|rsid|
106
+ (rsid_nids[rsid] ||= []) << node.nid
107
+ }
108
+ }
109
+
110
+ rsid_nids.values.each {|nids|
111
+ nids.sort!
112
+ }
113
+
114
+ @map = rsid_nids
115
+ end
116
+
117
+ def select_master(rsid, key)
118
+ nids = @map[rsid]
119
+ unless nids
120
+ raise "no such rsid: #{rsid}"
121
+ end
122
+ digest = Digest::MD5.digest(key)
123
+ i = digest.unpack('C')[0]
124
+ rotate(nids, i)
125
+ end
126
+
127
+ def select_master_static(rsid)
128
+ nids = @map[rsid]
129
+ unless nids
130
+ raise "no such rsid: #{rsid}"
131
+ end
132
+ nids.dup
133
+ end
134
+
135
+ ebus_connect :MasterSelectBus,
136
+ :select_master,
137
+ :select_master_static,
138
+ :update_nodes
139
+
140
+ private
141
+ def rotate(array, i)
142
+ n = i % array.size
143
+ return array[-n,n] + array[0, array.size-n]
144
+ end
145
+ end
146
+
147
+
148
+ end
@@ -0,0 +1,292 @@
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 MDSBus < Bus
22
+ # @return
23
+ # found: ObjectKey
24
+ # not found: nil
25
+ call_slot :get_okey
26
+
27
+ # @return
28
+ # found: Hash (may be {})
29
+ # not found: nil
30
+ call_slot :get_attrs
31
+
32
+ # @return
33
+ # found: [ObjectKey, Hash (may be {})]
34
+ # not found: [nil, nil]
35
+ call_slot :get_okey_attrs
36
+
37
+ # @return new ObjectKey
38
+ call_slot :add
39
+
40
+ # @return
41
+ # found: updated ObjectKey
42
+ # not found: nil
43
+ call_slot :update_attrs
44
+
45
+ # @return
46
+ # found: removed ObjectKey
47
+ # not found: nil
48
+ call_slot :remove
49
+
50
+ # @return
51
+ # found: removed ObjectKey
52
+ # not found: nil
53
+ call_slot :delete
54
+
55
+ # @return
56
+ # found: array of [ObjectKey, vtime, vname]
57
+ # not found: []
58
+ call_slot :util_locate
59
+ end
60
+
61
+
62
+ class MDSConfigService < Service
63
+ def run
64
+ @uri = ConfigBus.get_initial_mds_uri
65
+ on_change
66
+ end
67
+
68
+ def rpc_get_mds_uri
69
+ @uri
70
+ end
71
+
72
+ def rpc_set_mds_uri(uri)
73
+ @uri = uri
74
+ on_change
75
+ nil
76
+ end
77
+
78
+ def self.hash_uri(uri)
79
+ Digest::SHA1.digest(uri)
80
+ end
81
+
82
+ def on_change
83
+ SyncBus.update(SYNC_MDS_URI,
84
+ @uri, MDSConfigService.hash_uri(@uri))
85
+ end
86
+
87
+ ebus_connect :ProcessBus,
88
+ :run
89
+
90
+ ebus_connect :CSRPCBus,
91
+ :get_mds_uri => :rpc_get_mds_uri,
92
+ :set_mds_uri => :rpc_set_mds_uri
93
+ end
94
+
95
+
96
+ class MDSService < Service
97
+ def initialize
98
+ @uri = ""
99
+ @mds = NullMDS.new
100
+ end
101
+
102
+ def run
103
+ SyncBus.register_callback(SYNC_MDS_URI,
104
+ MDSConfigService.hash_uri(@uri)) do |obj|
105
+ uri = obj
106
+ reopen(uri)
107
+ @uri = uri
108
+ MDSConfigService.hash_uri(@uri)
109
+ end
110
+ end
111
+
112
+ def shutdown
113
+ if @mds
114
+ @mds.close rescue nil
115
+ end
116
+ end
117
+
118
+ def reopen(uri)
119
+ klass, expr = MDSSelector.select_class(uri)
120
+
121
+ mds = klass.new
122
+ mds.open(expr)
123
+
124
+ old_mds = @mds
125
+ @mds = mds
126
+
127
+ $log.info "using MDS: #{@mds}"
128
+
129
+ begin
130
+ old_mds.close
131
+ rescue
132
+ $log.error "MDS close error: #{$!}"
133
+ $log.error_backtrace $!.backtrace
134
+ end
135
+ end
136
+
137
+ ebus_connect :ProcessBus,
138
+ :run,
139
+ :shutdown
140
+
141
+ ebus_connect :MDSBus,
142
+ :get_okey,
143
+ :get_attrs,
144
+ :get_okey_attrs,
145
+ :add,
146
+ :update_attrs,
147
+ :remove,
148
+ :delete,
149
+ :util_locate
150
+
151
+ extend Forwardable
152
+
153
+ def_delegators :@mds,
154
+ :get_okey,
155
+ :get_attrs,
156
+ :get_okey_attrs,
157
+ :add,
158
+ :update_attrs,
159
+ :remove,
160
+ :delete,
161
+ :util_locate
162
+ end
163
+
164
+
165
+ module MDSSelector
166
+ IMPLS = {}
167
+
168
+ def self.register(name, klass)
169
+ IMPLS[name.to_sym] = klass
170
+ nil
171
+ end
172
+
173
+ def self.select_class(uri)
174
+ if m = /^(\w{1,8})\:(.*)/.match(uri)
175
+ type = m[1].to_sym
176
+ expr = m[2]
177
+ else
178
+ type = :tt
179
+ expr = uri
180
+ end
181
+
182
+ klass = IMPLS[type]
183
+ unless klass
184
+ raise "unknown MDS type: #{type}"
185
+ end
186
+
187
+ return klass, expr
188
+ end
189
+ end
190
+
191
+
192
+ class MDS
193
+ module Query
194
+ QC_EQ = 0
195
+ QC_NOT_EQ = 1
196
+ QC_LESS_THAN = 2
197
+ QC_LESS_THAN_EQ = 3
198
+ QC_GRATER_THAN = 4
199
+ QC_GRATER_THAN_EQ = 5
200
+ QC_NULL = 6
201
+ QC_NOT_NULL = 8
202
+
203
+ ORDER_NONE = 0
204
+ ORDER_STR_ASC = 1
205
+ ORDER_STR_DESC = 2
206
+ ORDER_NUM_ASC = 3
207
+ ORDER_NUM_DESC = 4
208
+ end
209
+
210
+ #def open(expr)
211
+ #end
212
+
213
+ #def close
214
+ #end
215
+
216
+ # @param version vname:String or vtime:Integer
217
+ #def get_okey(key, version=nil, &cb)
218
+ #end
219
+
220
+ # @param version vname:String or vtime:Integer
221
+ #def get_attrs(key, version=nil, &cb)
222
+ #end
223
+
224
+ # @param version vname:String or vtime:Integer
225
+ #def get_okey_attrs(key, version=nil, &cb)
226
+ #end
227
+
228
+ #def add(key, attrs={}, vname=nil, &cb)
229
+ #end
230
+
231
+ #def update_attrs(key, attrs, &cb)
232
+ #end
233
+
234
+ #def remove(key, &cb)
235
+ #end
236
+
237
+ #def delete(key, version=nil, &cb)
238
+ #end
239
+
240
+ def util_locate(key, &cb)
241
+ get_okey(key) {|okey|
242
+ if okey
243
+ cb.call([okey, nil], nil) rescue nil
244
+ else
245
+ cb.call([], nil) rescue nil
246
+ end
247
+ }
248
+ end
249
+
250
+ protected
251
+ def get_current_vtime(at_least=0)
252
+ now = Time.now.utc.to_i
253
+ if now <= at_least
254
+ return at_least + 1
255
+ else
256
+ return now
257
+ end
258
+ end
259
+
260
+ def new_okey(key, vtime=get_current_vtime, rsid=nil)
261
+ rsid ||= BalanceBus.select_next_rsid(key)
262
+ ObjectKey.new(key, vtime, rsid)
263
+ end
264
+ end
265
+
266
+
267
+ class NullMDS < MDS
268
+ extend Forwardable
269
+
270
+ [
271
+ :get_okey,
272
+ :get_attrs,
273
+ :get_okey_attrs,
274
+ :add,
275
+ :remove,
276
+ :delete,
277
+ :util_locate,
278
+ :open
279
+ ].each {|method|
280
+ def_delegator :self, :raise_error, method
281
+ }
282
+
283
+ def raise_error(*args)
284
+ raise "mds is not configured"
285
+ end
286
+
287
+ def close
288
+ end
289
+ end
290
+
291
+
292
+ end