dango 0.1.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dango/client_framework.rb +32 -23
- data/lib/dango/framework_base.rb +9 -8
- data/lib/dango/monitor/server_monitor_action.rb +8 -8
- data/lib/dango/script/dango_server.rb +3 -1
- data/lib/dango/server_framework.rb +262 -147
- data/lib/dango/shared/memory_store.rb +2 -1
- data/lib/dango/tasks/dango_rake.rb +171 -40
- data/lib/dango/tester/dango_tester_client.rb +92 -13
- data/lib/dango/version.rb +2 -2
- metadata +4 -4
@@ -31,7 +31,8 @@ module DangoFrameworkModule
|
|
31
31
|
raise(DangoFrameworkError, "Shared key is not exist.")
|
32
32
|
end
|
33
33
|
@mutex[key].synchronize do
|
34
|
-
data = yield(@data[key].deep_dup)
|
34
|
+
# data = yield(@data[key].deep_dup)
|
35
|
+
data = yield(@data[key])
|
35
36
|
@data[key] = data.deep_dup
|
36
37
|
end
|
37
38
|
end
|
@@ -2,73 +2,202 @@
|
|
2
2
|
ENV['RAILS_ENV'] = ENV['RAILS_ENV'] || 'development'
|
3
3
|
|
4
4
|
require "pp"
|
5
|
+
require "timeout"
|
5
6
|
|
6
|
-
namespace :dango do
|
7
|
-
desc "initialize dango"
|
8
|
-
task :initialize do
|
9
|
-
puts "complete initialize."
|
10
|
-
end
|
11
7
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
# verboseモードのフラグを立てる処理
|
9
|
+
def check_verbose_mode()
|
10
|
+
$is_verbose = (ENV["verbose"] == "true" || ENV["verbose"] == "on") ? true : false
|
11
|
+
end
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
# pid保存ファイルの読み出し
|
14
|
+
def get_dango_pid()
|
15
|
+
begin
|
20
16
|
pid = open("tmp/pids/dango.pid", "rb"){|fh| fh.read }.to_i
|
21
|
-
|
17
|
+
rescue
|
18
|
+
pid = nil
|
19
|
+
end
|
20
|
+
puts "pid=#{pid.inspect}" if $is_verbose
|
21
|
+
pid
|
22
|
+
end
|
23
|
+
|
24
|
+
# pidのプロセスがあるかどうかのチェック
|
25
|
+
def check_exist_dango_process(pid)
|
26
|
+
puts "check_exist_dango_process(pid=#{pid})" if $is_verbose
|
27
|
+
|
28
|
+
# そのpidのプロセスがあるかのチェック
|
29
|
+
is_pid_exist = nil
|
30
|
+
|
31
|
+
if RUBY_PLATFORM == 'i386-mswin32'
|
32
|
+
# WbemからProcessIDを取得
|
33
|
+
require "win32ole"
|
34
|
+
begin
|
35
|
+
n_locator = WIN32OLE.new("WbemScripting.SWbemLocator.1")
|
36
|
+
n_service = n_locator.ConnectServer
|
37
|
+
rescue
|
38
|
+
puts "failed connect to Wbem:#{$!.inspect}" if $is_verbose
|
39
|
+
return
|
40
|
+
end
|
22
41
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
begin
|
29
|
-
n_locator = WIN32OLE.new("WbemScripting.SWbemLocator.1")
|
30
|
-
n_service = n_locator.ConnectServer
|
31
|
-
rescue
|
32
|
-
puts "failed connect to Wbem:#{$!.inspect}"
|
33
|
-
return
|
42
|
+
set = n_service.ExecQuery("select Caption, ProcessID from Win32_Process where ProcessID = #{pid}")
|
43
|
+
set.each do |one|
|
44
|
+
# puts(sprintf("Win32_Process %8d %s", one.ProcessID, one.Caption))
|
45
|
+
if one.ProcessID == pid
|
46
|
+
is_pid_exist = true
|
34
47
|
end
|
48
|
+
end
|
49
|
+
|
50
|
+
else ## i386-mswin32以外
|
51
|
+
is_pid_exist = FileTest.exist?("/proc/#{pid}")
|
52
|
+
end
|
53
|
+
|
54
|
+
if is_pid_exist
|
55
|
+
puts "dango_process is exist." if $is_verbose
|
56
|
+
else
|
57
|
+
puts "dango_process is not exist." if $is_verbose
|
58
|
+
end
|
59
|
+
|
60
|
+
is_pid_exist
|
61
|
+
end
|
62
|
+
|
63
|
+
# プロセス停止
|
64
|
+
def stop_process(pid)
|
65
|
+
puts "stop process (pid=#{pid})" if $is_verbose
|
66
|
+
|
67
|
+
if RUBY_PLATFORM == 'i386-mswin32'
|
68
|
+
# WbemからProcessIDを取得
|
69
|
+
require "win32ole"
|
70
|
+
begin
|
71
|
+
n_locator = WIN32OLE.new("WbemScripting.SWbemLocator.1")
|
72
|
+
n_service = n_locator.ConnectServer
|
73
|
+
rescue
|
74
|
+
puts "failed connect to Wbem:#{$!.inspect}" if $is_verbose
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
set = n_service.ExecQuery("select Caption, name, ProcessID from Win32_Process where ProcessID = '#{pid}'")
|
79
|
+
set.each do |process|
|
80
|
+
puts "stopping #{process.Caption} #{process.name} #{process.ProcessID}" if $is_verbose
|
81
|
+
process.Terminate 0
|
82
|
+
end
|
83
|
+
|
84
|
+
else ## i386-mswin32以外
|
85
|
+
system("kill -9 #{pid}")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# サーバーへの通信を使ったチェック
|
90
|
+
def check_dango_connect()
|
91
|
+
require 'dango/tester/dango_tester_client'
|
92
|
+
|
93
|
+
# コンフィグから check_dango_process_cmd を取得
|
94
|
+
config = YAML.load(open("dango/config/#{ENV['RAILS_ENV']}.yml", "rb"){|fh| fh.read})
|
95
|
+
|
96
|
+
serv_info = {}
|
97
|
+
serv_info["host"] = config['network']['host'] || 'localhost'
|
98
|
+
serv_info["port"] = config['network']['port'] || 15000
|
99
|
+
# pp serv_info
|
100
|
+
|
101
|
+
tester = DangoTesterClient.new # 開始
|
102
|
+
|
103
|
+
begin
|
104
|
+
tester1 = nil
|
105
|
+
sid = nil
|
106
|
+
timeout(8) do
|
107
|
+
tester1 = tester.new_client("tester1", serv_info) # テスター1
|
35
108
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if
|
40
|
-
|
41
|
-
end
|
109
|
+
sleep 3
|
110
|
+
loop do
|
111
|
+
sid = tester1.sid
|
112
|
+
break if sid
|
113
|
+
sleep 1
|
42
114
|
end
|
43
|
-
else
|
44
|
-
is_pid_exist = FileTest.exist?("/proc/#{pid}")
|
45
115
|
end
|
116
|
+
rescue TimeoutError
|
117
|
+
sid = nil
|
118
|
+
ensure
|
119
|
+
tester1.dango_client_close if tester1.respond_to?(:dango_client_close)
|
120
|
+
tester1 = nil
|
121
|
+
tester.gc_thread_stop
|
122
|
+
end
|
123
|
+
|
124
|
+
puts "sid=#{sid.inspect}" if $is_verbose
|
125
|
+
|
126
|
+
if sid
|
127
|
+
is_alive_server = true
|
128
|
+
else
|
129
|
+
is_alive_server = false
|
130
|
+
end
|
131
|
+
|
132
|
+
is_alive_server
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
namespace :dango do
|
137
|
+
# desc "make swf"
|
138
|
+
# task :make_swf do
|
139
|
+
# puts "complete make_swf." if $is_verbose
|
140
|
+
# end
|
141
|
+
|
142
|
+
desc "stop dango process"
|
143
|
+
task :stop_dango_process do
|
144
|
+
check_verbose_mode() # verboseモードのフラグを立てる処理
|
145
|
+
|
146
|
+
pid = get_dango_pid()
|
147
|
+
stop_process(pid) if pid # pidがあればプロセス停止
|
148
|
+
puts "complete stop dango process." if $is_verbose
|
149
|
+
end
|
150
|
+
|
151
|
+
desc "check dango process"
|
152
|
+
task :check_dango_process do
|
153
|
+
check_verbose_mode() # verboseモードのフラグを立てる処理
|
46
154
|
|
47
|
-
|
155
|
+
pid = get_dango_pid() # pidのチェック
|
156
|
+
is_pid_exist = check_exist_dango_process(pid) # pidのプロセスがあるかどうかのチェック
|
157
|
+
is_alive_server = check_dango_connect() if is_pid_exist # サーバーへの通信を使ったチェック
|
48
158
|
|
49
159
|
# コンフィグから check_dango_process_cmd を取得
|
50
160
|
config = YAML.load(open("dango/config/#{ENV['RAILS_ENV']}.yml", "rb"){|fh| fh.read})
|
51
161
|
check_dango_process_cmd = config['server']['check_dango_process_cmd'] || nil
|
52
162
|
|
53
163
|
# is_pid_existがないならcheck_dango_process_cmd実行
|
54
|
-
if !
|
55
|
-
|
56
|
-
system(check_dango_process_cmd)
|
164
|
+
if check_dango_process_cmd && (! is_alive_server)
|
165
|
+
stop_process(pid) if pid # pidがあればプロセス停止
|
57
166
|
end
|
58
167
|
|
59
|
-
check_dango_process_cmd
|
168
|
+
if check_dango_process_cmd && ((! is_pid_exist) || (! is_alive_server))
|
169
|
+
puts "check_dango_process_cmd=#{check_dango_process_cmd}" if $is_verbose
|
170
|
+
system(check_dango_process_cmd)
|
171
|
+
end
|
60
172
|
|
61
|
-
puts "complete check_dango_process."
|
173
|
+
puts "complete check_dango_process." if $is_verbose
|
62
174
|
end
|
63
175
|
|
64
176
|
namespace :monitor do
|
65
177
|
desc "get server info"
|
66
178
|
task :get_server_info do
|
67
|
-
|
179
|
+
check_verbose_mode() # verboseモードのフラグを立てる処理
|
180
|
+
|
181
|
+
puts "server_reload"
|
182
|
+
require 'dango/monitor/dango_monitor_client.rb'
|
183
|
+
begin
|
184
|
+
dm = DangoMonitorClient.new()
|
185
|
+
pp dm.get_server_info()
|
186
|
+
dm.dango_client_close
|
187
|
+
puts "complete get_server_info."
|
188
|
+
rescue
|
189
|
+
pp $!.class
|
190
|
+
pp $!.message
|
191
|
+
pp $!.backtrace
|
192
|
+
puts "failed get_server_info."
|
193
|
+
end
|
194
|
+
|
68
195
|
end
|
69
196
|
|
70
197
|
desc "server_reload" # サーバーのリロード処理
|
71
198
|
task :server_reload do
|
199
|
+
check_verbose_mode() # verboseモードのフラグを立てる処理
|
200
|
+
|
72
201
|
puts "server_reload"
|
73
202
|
require 'dango/monitor/dango_monitor_client.rb'
|
74
203
|
begin
|
@@ -86,7 +215,9 @@ namespace :dango do
|
|
86
215
|
|
87
216
|
desc "send_system_message" # システムメッセージ配信
|
88
217
|
task :send_system_message do
|
89
|
-
|
218
|
+
check_verbose_mode() # verboseモードのフラグを立てる処理
|
219
|
+
|
220
|
+
puts "send_system_message" if $is_verbose
|
90
221
|
message_type = ENV["TYPE"]
|
91
222
|
if ! message_type
|
92
223
|
puts "please type. ex. rake dango:monitor:send_system_message TYPE=down_1min"
|
@@ -14,7 +14,9 @@ class DangoTesterClient
|
|
14
14
|
GCIntervalSec = 5.0 # GCの発生タイミング
|
15
15
|
|
16
16
|
# テスターのイニシャライズ
|
17
|
-
def initialize
|
17
|
+
def initialize(debug = false)
|
18
|
+
@debug = debug
|
19
|
+
|
18
20
|
@client_conns = {}
|
19
21
|
Thread.abort_on_exception = true
|
20
22
|
|
@@ -32,7 +34,7 @@ class DangoTesterClient
|
|
32
34
|
"port"=>serv_info["port"],
|
33
35
|
},
|
34
36
|
}
|
35
|
-
env =
|
37
|
+
env = ENV['RAILS_ENV'] || 'development'
|
36
38
|
|
37
39
|
# 接続
|
38
40
|
client_conn = nil
|
@@ -43,7 +45,7 @@ class DangoTesterClient
|
|
43
45
|
rescue
|
44
46
|
client_conn = nil
|
45
47
|
raise("connection error for retry times over.") if i == ConnectionRetryTimes - 1
|
46
|
-
puts "connection failed. sleep #{ConnectionRetryIntervalSec}"
|
48
|
+
puts "connection failed. sleep #{ConnectionRetryIntervalSec}" if @debug
|
47
49
|
sleep ConnectionRetryIntervalSec
|
48
50
|
end
|
49
51
|
end
|
@@ -74,7 +76,7 @@ class DangoTesterClient
|
|
74
76
|
|
75
77
|
# GCスレッドの開始
|
76
78
|
def gc_thread_start
|
77
|
-
|
79
|
+
gc_thread = Thread.start do
|
78
80
|
loop do
|
79
81
|
begin
|
80
82
|
sleep @gc_interval_sec
|
@@ -83,21 +85,28 @@ class DangoTesterClient
|
|
83
85
|
GC.enable
|
84
86
|
GC.start
|
85
87
|
GC.disable
|
86
|
-
puts "GC #{Time.now - gc_start_time}sec #{Time.now_to_s}"
|
88
|
+
puts "GC #{Time.now - gc_start_time}sec #{Time.now_to_s}" if @debug
|
87
89
|
|
88
90
|
rescue
|
89
91
|
puts "Exception gc_thread_start #{Time.now_to_s} #{error_message($!, 'u')}"
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
93
|
-
|
95
|
+
gc_thread.priority = -1
|
96
|
+
|
97
|
+
@gc_thread = gc_thread
|
98
|
+
end
|
99
|
+
|
100
|
+
# GCスレッドの終了
|
101
|
+
def gc_thread_stop
|
102
|
+
@gc_thread.kill
|
94
103
|
end
|
95
104
|
|
96
105
|
end
|
97
106
|
|
98
107
|
# テスト接続用のクラス
|
99
108
|
class TestClient < DangoClientFramework
|
100
|
-
SendReceiveSleepIntervalSec = 0.
|
109
|
+
SendReceiveSleepIntervalSec = 0.1 # データ送信後の順の際のタイムアウトチェック間隔秒
|
101
110
|
ReceiveWaitTimeoutSec = 10 # データ受信確認の待ち秒数
|
102
111
|
ReceiveTrapTimeoutSec = 0 # データ受信確認のトラップの秒数
|
103
112
|
|
@@ -107,13 +116,15 @@ class TestClient < DangoClientFramework
|
|
107
116
|
|
108
117
|
super(env, config)
|
109
118
|
|
110
|
-
|
111
|
-
@receive_arr = []
|
112
|
-
@trap_thread_hash = {}
|
119
|
+
send_receive_shared_init()
|
113
120
|
|
114
|
-
@
|
121
|
+
# @receive_mutex = Mutex.new # 受信用の排他処理
|
122
|
+
# @receive_arr = []
|
123
|
+
# @trap_thread_hash = {}
|
124
|
+
# @receive_methods = []
|
125
|
+
|
126
|
+
send_receive_shared[:receive_cache] = [] # 受信データ用のキャッシュ初期化
|
115
127
|
|
116
|
-
send_receive_shared_init()
|
117
128
|
end
|
118
129
|
|
119
130
|
attr_accessor(:client_name)
|
@@ -137,10 +148,33 @@ class TestClient < DangoClientFramework
|
|
137
148
|
|
138
149
|
# テストサーバー
|
139
150
|
def send(name, send_obj = {})
|
140
|
-
logger.debug("tester.send:send_obj=#{send_obj.inspect} ")
|
151
|
+
logger.debug("tester.send:name=#{name}:send_obj=#{send_obj.inspect} ")
|
141
152
|
send_action(name, send_obj)
|
142
153
|
end
|
143
154
|
|
155
|
+
# データ受信時の処理をするためにmethod_missingを定義
|
156
|
+
def method_missing(name, *args)
|
157
|
+
if name.to_s =~ /^dango_receive_/ && args.length == 1
|
158
|
+
ret_obj = args[0]
|
159
|
+
logger.debug "ret_obj:#{name}:" + ret_obj.inspect + " " + Time.now_to_s
|
160
|
+
send_receive_shared.transaction(:receive_cache) do |receive_cache|
|
161
|
+
receive_cache.push([name, ret_obj, Time.now])
|
162
|
+
receive_cache
|
163
|
+
end
|
164
|
+
|
165
|
+
else
|
166
|
+
logger.info "method not found. #{name.inspect} #{args.inspect}"
|
167
|
+
raise(NameError, "method not found. #{name.inspect} #{args.inspect}")
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# send_receive_shared[:receive_cache]の中身を返すメソッド
|
172
|
+
def get_receive_cache
|
173
|
+
send_receive_shared[:receive_cache]
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
=begin
|
144
178
|
# trap_receive
|
145
179
|
def trap_receive(notice_name, options = {})
|
146
180
|
logger.debug "trap_receive_data:#{notice_name}:"
|
@@ -231,6 +265,7 @@ class TestClient < DangoClientFramework
|
|
231
265
|
logger.debug "trap_receive_data:already register trap:notice_name:#{notice_name} "
|
232
266
|
end
|
233
267
|
|
268
|
+
logger.debug "trap_receive_data:registered:#{notice_name}:"
|
234
269
|
end
|
235
270
|
|
236
271
|
# cancel trap_receive
|
@@ -255,8 +290,51 @@ class TestClient < DangoClientFramework
|
|
255
290
|
@receive_arr.delete_if{|r| r[0] == notice_name}
|
256
291
|
end
|
257
292
|
end
|
293
|
+
=end
|
258
294
|
|
259
295
|
# wait_receive
|
296
|
+
def wait_receive(notice_name, options = {})
|
297
|
+
logger.debug "wait_receive_data:#{notice_name}:"
|
298
|
+
timeout = options[:timeout] || ReceiveWaitTimeoutSec
|
299
|
+
|
300
|
+
# データ受信待ち
|
301
|
+
receive_data = nil
|
302
|
+
receive_idx = nil
|
303
|
+
|
304
|
+
end_reserved_time = Time.now + timeout # 0以上ならタイムアウト時間決定
|
305
|
+
|
306
|
+
loop do
|
307
|
+
logger.debug "wait_receive_data:loop:#{send_receive_shared[:receive_cache].inspect}"
|
308
|
+
|
309
|
+
send_receive_shared[:receive_cache].each_with_index do |rec_data, i|
|
310
|
+
if rec_data[0].to_s == "dango_receive_" + notice_name.to_s
|
311
|
+
receive_data = rec_data.deep_dup
|
312
|
+
receive_idx = i
|
313
|
+
break
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
break if receive_data != nil
|
318
|
+
break if end_reserved_time < Time.now
|
319
|
+
|
320
|
+
sleep SendReceiveSleepIntervalSec # スリープ
|
321
|
+
end
|
322
|
+
|
323
|
+
# タイムアウトなら
|
324
|
+
if receive_data == nil
|
325
|
+
raise(DangoFrameworkTimeoutError, "timeout:timeout_sec=#{timeout}: \n client_name=#{@client_name}(#{self.sid}) \n :notice_name=#{notice_name} \n")
|
326
|
+
end
|
327
|
+
|
328
|
+
# 結果を削除しておく
|
329
|
+
send_receive_shared.transaction(:receive_cache) do |receive_cache|
|
330
|
+
receive_cache.delete_at(receive_idx)
|
331
|
+
receive_cache
|
332
|
+
end
|
333
|
+
|
334
|
+
receive_data[1]
|
335
|
+
end
|
336
|
+
|
337
|
+
=begin
|
260
338
|
def wait_receive(notice_name, options = {})
|
261
339
|
logger.debug "wait_receive_data:#{notice_name}:"
|
262
340
|
timeout = options[:timeout] || ReceiveWaitTimeoutSec
|
@@ -300,6 +378,7 @@ class TestClient < DangoClientFramework
|
|
300
378
|
end
|
301
379
|
receive_arr
|
302
380
|
end
|
381
|
+
=end
|
303
382
|
|
304
383
|
end
|
305
384
|
|