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,25 @@
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 CSStatService < StatService
22
+ end
23
+
24
+
25
+ end
@@ -0,0 +1,40 @@
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 DSStatService < GWStatService
22
+ def stat_db_items
23
+ StatBus.db_items
24
+ end
25
+
26
+ def stat_cmd_read
27
+ StatBus.cmd_read
28
+ end
29
+
30
+ def stat_cmd_write
31
+ StatBus.cmd_write
32
+ end
33
+
34
+ def stat_cmd_delete
35
+ StatBus.cmd_delete
36
+ end
37
+ end
38
+
39
+
40
+ end
@@ -0,0 +1,25 @@
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 GWStatService < StatService
22
+ end
23
+
24
+
25
+ end
@@ -0,0 +1,116 @@
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 StorageBus < Bus
22
+ call_slot :open
23
+ call_slot :close
24
+
25
+ call_slot :get
26
+
27
+ call_slot :set
28
+
29
+ call_slot :read
30
+
31
+ call_slot :delete
32
+
33
+ call_slot :copy
34
+
35
+ call_slot :exist
36
+
37
+ call_slot :get_items
38
+ end
39
+
40
+
41
+ class StorageSelector
42
+ IMPLS = {}
43
+
44
+ def self.register(name, klass)
45
+ IMPLS[name.to_sym] = klass
46
+ nil
47
+ end
48
+
49
+ def self.select_class(uri)
50
+ if m = /^(\w{1,8})\:(.*)/.match(uri)
51
+ type = m[1].to_sym
52
+ expr = m[2]
53
+ else
54
+ type = :dir
55
+ expr = uri
56
+ end
57
+
58
+ klass = IMPLS[type]
59
+ unless klass
60
+ raise "unknown Storage type: #{type}"
61
+ end
62
+
63
+ return klass, expr
64
+ end
65
+
66
+ def self.select!(uri)
67
+ klass, expr = select_class(uri)
68
+ klass.init
69
+
70
+ StorageBus.open(expr)
71
+ end
72
+
73
+ def self.open!
74
+ select!(ConfigBus.get_storage_path)
75
+ end
76
+ end
77
+
78
+
79
+ class StorageService < Service
80
+ #def open(path)
81
+ #end
82
+
83
+ #def close
84
+ #end
85
+
86
+ #def get(vtime, key)
87
+ #end
88
+
89
+ #def set(vtime, key, data)
90
+ #end
91
+
92
+ #def read(vtime, key, offset, size)
93
+ #end
94
+
95
+ #def delete(vtime, key)
96
+ #end
97
+
98
+ #def exist(vtime, key)
99
+ #end
100
+
101
+ #def get_items
102
+ #end
103
+
104
+ ebus_connect :StorageBus,
105
+ :get,
106
+ :set,
107
+ :read,
108
+ :delete,
109
+ :exist,
110
+ :get_items,
111
+ :open,
112
+ :close
113
+ end
114
+
115
+
116
+ end
@@ -0,0 +1,201 @@
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
+ require 'fileutils'
21
+ require 'uri'
22
+
23
+ class DirectoryStorageService < StorageService
24
+ StorageSelector.register(:dir, self)
25
+
26
+ def open(expr)
27
+ @dir = File.expand_path(expr)
28
+ end
29
+
30
+ def close
31
+ end
32
+
33
+ def get(vtime, key)
34
+ read(vtime, key, nil, nil)
35
+ end
36
+
37
+ def read(vtime, key, offset, size)
38
+ $log.trace { "DirectoryStorage: read vtime=#{vtime} key=#{key.dump} offset=#{offset} size=#{size}" }
39
+
40
+ path = key_to_path(vtime, key)
41
+ begin
42
+ return File.read(path, size, offset)
43
+ rescue
44
+ return nil
45
+ end
46
+ end
47
+
48
+ def set(vtime, key, data)
49
+ $log.trace { "DirectoryStorage: set vtime=#{vtime} key=#{key.dump} data=#{data.size}byte)" }
50
+
51
+ path = key_to_path(vtime, key)
52
+ make_dir(path)
53
+
54
+ tmp_path = path+".tmp"
55
+ File.open(tmp_path, File::WRONLY|File::CREAT|File::TRUNC) {|f|
56
+ #f.write(data)
57
+ while true
58
+ n = f.syswrite(data)
59
+ if data.size <= n
60
+ break
61
+ else
62
+ data = data[n..-1]
63
+ #data.slice!(0,n-1)
64
+ end
65
+ end
66
+ }
67
+ File.rename(tmp_path, path)
68
+
69
+ true
70
+ end
71
+
72
+ #def write(vtime, key, offset, data)
73
+ # $log.trace { "DirectoryStorage: write vtime=#{vtime} key=#{key.dump} offset=#{offset} data=#{data.size}bytes" }
74
+ #
75
+ # path = key_to_path(vtime, key)
76
+ # make_dir(path)
77
+ #
78
+ # File.open(path, File::WRONLY|File::CREAT) {|f|
79
+ # f.pos = offset
80
+ # #f.write(data)
81
+ # while true
82
+ # n = f.syswrite(data)
83
+ # if data.size <= n
84
+ # break
85
+ # else
86
+ # data = data[n..-1]
87
+ # #data.slice!(0,n-1)
88
+ # end
89
+ # end
90
+ # }
91
+ #
92
+ # true
93
+ #end
94
+
95
+ #def append(vtime, key, data)
96
+ # $log.trace { "DirectoryStorage: append vtime=#{vtime} key=#{key.dump} offset=#{offset} data=#{data.size}bytes" }
97
+ #
98
+ # path = key_to_path(vtime, key)
99
+ # make_dir(path)
100
+ #
101
+ # size = nil
102
+ # File.open(path, File::WRONLY|File::CREAT|File::APPEND) {|f|
103
+ # #f.write(data)
104
+ # while true
105
+ # n = f.syswrite(data)
106
+ # if data.size <= n
107
+ # break
108
+ # else
109
+ # data = data[n..-1]
110
+ # #data.slice!(0,n-1)
111
+ # end
112
+ # end
113
+ # size = f.stat.size
114
+ # }
115
+ #
116
+ # size
117
+ #end
118
+
119
+ #def resize(vtime, key, size)
120
+ # $log.trace { "DirectoryStorage: resize vtime=#{vtime} key=#{key.dump} size=#{size}" }
121
+ #
122
+ # path = key_to_path(vtime, key)
123
+ # make_dir(path)
124
+ #
125
+ # File.open(path, File::WRONLY|File::CREAT) {|f|
126
+ # f.truncate(size)
127
+ # }
128
+ #
129
+ # true
130
+ #end
131
+
132
+ def delete(vtime, key)
133
+ $log.trace { "DirectoryStorage: delete vtime=#{vtime} key=#{key.dump}" }
134
+
135
+ path = key_to_path(vtime, key)
136
+ begin
137
+ File.unlink(path)
138
+ Dir.rmdir(File.dirname(path)) rescue nil
139
+ return true
140
+ rescue
141
+ return false
142
+ end
143
+ end
144
+
145
+ def exist(vtime, key)
146
+ $log.trace { "DirectoryStorage: exist vtime=#{vtime} key=#{key.dump}" }
147
+
148
+ path = key_to_path(vtime, key)
149
+ return File.exist?(path)
150
+ end
151
+
152
+ def get_items
153
+ num = 0
154
+ (0..0xff).each {|d|
155
+ box = "%03d" % d
156
+ dirpath = File.join(@dir, "data", box)
157
+ begin
158
+ e = Dir.entries(dirpath).size
159
+ e -= 2 # skip "." and ".."
160
+ num += e if e > 0
161
+ rescue
162
+ end
163
+ }
164
+ num
165
+ end
166
+
167
+ # for DataServerURLService
168
+ def self.encode_okey(okey)
169
+ subpath = key_to_subpath(okey.vtime, okey.key)
170
+ File.join(*subpath)
171
+ end
172
+
173
+ def key_to_path(vtime, key)
174
+ subpath = self.class.key_to_subpath(vtime, key)
175
+ File.join(@dir, "data", *subpath)
176
+ end
177
+
178
+ def self.key_to_subpath(vtime, key)
179
+ digest = Digest::MD5.digest(key)
180
+ box = "%03d" % digest.unpack('C')[0]
181
+ kdir = encode_path(key)
182
+ fname = "v#{vtime}"
183
+ return box, kdir, fname
184
+ end
185
+
186
+ private
187
+ def self.encode_path(s)
188
+ URI.encode(s, /[^-_.a-zA-Z0-9]/n)
189
+ end
190
+
191
+ def self.decode_path(b)
192
+ URI.decode(b, /[^-_.a-zA-Z0-9]/n)
193
+ end
194
+
195
+ def make_dir(path)
196
+ FileUtils.mkdir_p File.dirname(path)
197
+ end
198
+ end
199
+
200
+
201
+ end
@@ -0,0 +1,206 @@
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
+ SYNC_MEMBERSHIP = 0
22
+ SYNC_FAULT_LIST = 1
23
+ SYNC_REPLSET_WEIGHT = 2
24
+ SYNC_MDS_URI = 3
25
+ SYNC_MDS_CACHE_URI = 4
26
+
27
+
28
+ class SyncBus < Bus
29
+ call_slot :get_hash
30
+
31
+ call_slot :check_hash
32
+ call_slot :update
33
+
34
+ call_slot :register_callback
35
+ call_slot :try_sync
36
+ end
37
+
38
+
39
+ class SyncService < Service
40
+ def initialize
41
+ @hash_array = []
42
+ update_hash
43
+ end
44
+
45
+ def get_hash
46
+ @hash
47
+ end
48
+
49
+ ebus_connect :SyncBus,
50
+ :get_hash
51
+
52
+ private
53
+ def update_hash
54
+ @hash = Digest::SHA1.digest(@hash_array.to_msgpack)
55
+ end
56
+ end
57
+
58
+
59
+ class SyncServerService < SyncService
60
+ def initialize
61
+ @data_array = []
62
+ super
63
+ end
64
+
65
+ def check_hash(hash)
66
+ @hash == hash
67
+ end
68
+
69
+ def update(id, data, hash)
70
+ @data_array[id] = data
71
+ @hash_array[id] = hash
72
+ update_hash
73
+ nil
74
+ end
75
+
76
+ def rpc_sync_config(hash_array)
77
+ result = []
78
+
79
+ hash_array.each_with_index {|hash,id|
80
+ if h = @hash_array[id]
81
+ if h != hash
82
+ result[id] = @data_array[id]
83
+ end
84
+ end
85
+ }
86
+
87
+ result
88
+ end
89
+
90
+ ebus_connect :SyncBus,
91
+ :update,
92
+ :check_hash
93
+
94
+ ebus_connect :CSRPCBus,
95
+ :sync_config => :rpc_sync_config
96
+ end
97
+
98
+
99
+ class SyncClientService < SyncService
100
+ def initialize
101
+ @callback_array = []
102
+ super
103
+ end
104
+
105
+ def register_callback(id, initial_hash, &block)
106
+ @callback_array[id] = block
107
+ @hash_array[id] = initial_hash
108
+ update_hash
109
+ nil
110
+ end
111
+
112
+ def try_sync
113
+ do_sync
114
+ nil
115
+ end
116
+
117
+ def sync_blocking!
118
+ do_sync.join
119
+ end
120
+
121
+ ebus_connect :SyncBus,
122
+ :register_callback,
123
+ :try_sync
124
+
125
+ private
126
+ def do_sync
127
+ get_cs_session.callback(:sync_config, @hash_array) do |future|
128
+ begin
129
+ data_array = future.get
130
+ ack_sync(data_array)
131
+ rescue
132
+ $log.error "sync error: #{$!}"
133
+ $log.error_backgrace $!.backtrace
134
+ end
135
+ end
136
+ end
137
+
138
+ def ack_sync(data_array)
139
+ data_array.each_with_index {|obj,id|
140
+ if obj
141
+ if callback = @callback_array[id]
142
+ $log.debug "sync: #{id} => #{obj.inspect}"
143
+ @hash_array[id] = callback.call(obj)
144
+ end
145
+ end
146
+ }
147
+ update_hash
148
+ end
149
+
150
+ def get_cs_session
151
+ ProcessBus.get_session(ConfigBus.get_cs_address)
152
+ end
153
+ end
154
+
155
+
156
+ class StandaloneSyncService < SyncServerService
157
+ def initialize
158
+ @callback_array = []
159
+ @client_hash_array = []
160
+ super
161
+ end
162
+
163
+ def register_callback(id, initial_hash, &block)
164
+ @callback_array[id] = block
165
+ @client_hash_array[id] = initial_hash
166
+ nil
167
+ end
168
+
169
+ def try_sync
170
+ do_sync
171
+ nil
172
+ end
173
+
174
+ def sync_blocking!
175
+ do_sync.join
176
+ end
177
+
178
+ ebus_connect :SyncBus,
179
+ :register_callback,
180
+ :try_sync
181
+
182
+ private
183
+ def do_sync
184
+ result = []
185
+
186
+ @client_hash_array.each_with_index {|hash,id|
187
+ if h = @hash_array[id]
188
+ if h != hash
189
+ result[id] = MessagePack.unpack(@data_array[id].to_msgpack)
190
+ end
191
+ end
192
+ }
193
+
194
+ result.each_with_index {|obj,id|
195
+ if obj
196
+ if callback = @callback_array[id]
197
+ $log.debug "sync: #{id} => #{obj.inspect}"
198
+ @client_hash_array[id] = callback.call(obj)
199
+ end
200
+ end
201
+ }
202
+ end
203
+ end
204
+
205
+
206
+ end