ls4 0.9.0

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 (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