dango 0.1.0 → 0.2.2
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.
- 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
|
|