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
@@ -42,7 +42,8 @@ class DangoClientFramework
|
|
42
42
|
@connection_client_port = @config['network']['port'] || 15000
|
43
43
|
|
44
44
|
@connection_client_log_file = "" # 未定義時にこのログファイル名を使う
|
45
|
-
@connection_client_log_level = Logger::DEBUG # 未定義時にこのログレベルになる
|
45
|
+
# @connection_client_log_level = Logger::DEBUG # 未定義時にこのログレベルになる
|
46
|
+
@connection_client_log_level = Logger::INFO # 未定義時にこのログレベルになる
|
46
47
|
|
47
48
|
@recv_count = 0 # 受信回数
|
48
49
|
@send_count = 0 # 送信回数
|
@@ -53,7 +54,13 @@ class DangoClientFramework
|
|
53
54
|
exit!
|
54
55
|
end
|
55
56
|
|
56
|
-
|
57
|
+
begin
|
58
|
+
dango_client_init() # 初期設定読み込み
|
59
|
+
rescue
|
60
|
+
message = "failed in dango_client_init. #{error_message($!, 'u')}"
|
61
|
+
logger.error message
|
62
|
+
raise DangoError, message
|
63
|
+
end
|
57
64
|
|
58
65
|
@log_file = @connection_client_log_file
|
59
66
|
@log_level = @connection_client_log_level
|
@@ -104,9 +111,9 @@ class DangoClientFramework
|
|
104
111
|
begin
|
105
112
|
if @sock
|
106
113
|
logger.debug "start dango_receive_data #{@sid}"
|
107
|
-
|
114
|
+
ret_objs = nil
|
108
115
|
begin
|
109
|
-
|
116
|
+
ret_objs = dango_receive_data(@sock) # データ受信処理
|
110
117
|
rescue DangoFrameworkConnectionError
|
111
118
|
logger.debug "sock error #{@sid}:#{error_message($!, 'u')}"
|
112
119
|
throw(:session_closed)
|
@@ -114,26 +121,28 @@ class DangoClientFramework
|
|
114
121
|
logger.debug "sock error #{@sid}:#{error_message($!, 'u')}"
|
115
122
|
throw(:session_closed)
|
116
123
|
end
|
117
|
-
logger.debug "finished dango_receive_data:#{
|
124
|
+
logger.debug "finished dango_receive_data:#{ret_objs.inspect} #{@sid}"
|
118
125
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
126
|
+
ret_objs.each do |ret_obj| # 受信データひとつごとに処理
|
127
|
+
if !(ret_obj && ret_obj["notice"])
|
128
|
+
logger.info "no notice:#{ret_obj["notice"].inspect} #{@sid}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# メソッド呼び出し
|
132
|
+
logger.info "calling method=#{ret_obj["notice"].inspect} #{@sid} "
|
133
|
+
begin
|
134
|
+
__send__("dango_receive_#{ret_obj["notice"]}", ret_obj)
|
135
|
+
rescue
|
136
|
+
logger.error "error in dango_receive_#{ret_obj["notice"]} #{@sid} \n#{error_message($!, 'u')}"
|
137
|
+
ensure
|
138
|
+
# データの受信の送信返し
|
139
|
+
response_notice_name = "_response"
|
140
|
+
send_obj = {"_id" => ret_obj["_id"]}
|
141
|
+
send_action(response_notice_name, send_obj)
|
142
|
+
logger.debug "response_notice_name=#{response_notice_name.inspect} #{@sid} "
|
143
|
+
end
|
144
|
+
logger.debug "called method=#{ret_obj["notice"].inspect} #{@sid} "
|
135
145
|
end
|
136
|
-
logger.debug "called method=#{ret_obj["notice"].inspect} #{@sid} "
|
137
146
|
|
138
147
|
else
|
139
148
|
sleep 0.01
|
@@ -235,7 +244,7 @@ class DangoClientFramework
|
|
235
244
|
logger.debug "send_action(#{action_name.inspect}, #{send_obj['_id']}) "
|
236
245
|
send_obj_dup = send_obj.dup
|
237
246
|
send_obj_dup["action"] = action_name.to_s
|
238
|
-
dango_send_data(@sock, send_obj_dup)
|
247
|
+
dango_send_data(@sock, [send_obj_dup])
|
239
248
|
end
|
240
249
|
|
241
250
|
# サーバーからクライアントへのデータ送信
|
data/lib/dango/framework_base.rb
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
= コネクションのサーバー、クライアントで使うモジュール
|
5
5
|
=end
|
6
6
|
|
7
|
-
require "rubygems"
|
8
7
|
|
9
8
|
require 'resolv-replace' # 名前解決時のロックがかかってしまう件を解決できるはず
|
10
9
|
require 'socket'
|
@@ -16,6 +15,8 @@ require "stringio"
|
|
16
15
|
require "pp"
|
17
16
|
require "kconv"
|
18
17
|
require "fcntl"
|
18
|
+
|
19
|
+
require "rubygems"
|
19
20
|
require "json"
|
20
21
|
|
21
22
|
require "dango/shared/memory_store.rb"
|
@@ -209,7 +210,7 @@ module DangoFrameworkModule
|
|
209
210
|
|
210
211
|
begin
|
211
212
|
if ret_data == "" || ret_data == "{}" # データが空ならparseしない
|
212
|
-
data =
|
213
|
+
data = []
|
213
214
|
elsif dtype == 0
|
214
215
|
data = JSON.parse(ret_data)
|
215
216
|
elsif dtype == 1
|
@@ -223,19 +224,19 @@ module DangoFrameworkModule
|
|
223
224
|
end
|
224
225
|
|
225
226
|
# データ送信処理
|
226
|
-
def dango_send_data(sock,
|
227
|
-
# logger.debug "dango_send_data:
|
227
|
+
def dango_send_data(sock, send_objs, options = {})
|
228
|
+
# logger.debug "dango_send_data:send_objs=#{send_objs.inspect}"
|
228
229
|
|
229
230
|
dtype = options[:type] || DefaultDataType
|
230
231
|
|
231
|
-
if
|
232
|
+
if send_objs == []
|
232
233
|
send_data_orig = ""
|
233
234
|
elsif dtype == 0
|
234
|
-
send_data_orig = JSON.generate(
|
235
|
+
send_data_orig = JSON.generate(send_objs)
|
235
236
|
elsif dtype == 1
|
236
|
-
send_data_orig =
|
237
|
+
send_data_orig = send_objs.to_yaml
|
237
238
|
elsif dtype == 2
|
238
|
-
send_data_orig = Marshal.dump(
|
239
|
+
send_data_orig = Marshal.dump(send_objs)
|
239
240
|
end
|
240
241
|
|
241
242
|
send_data = dango_send_encrypt(send_data_orig) + "\n"
|
@@ -71,7 +71,7 @@ class ServerMonitorAction
|
|
71
71
|
if !match
|
72
72
|
notice_name = "return_" + action_name
|
73
73
|
send_obj = {'code'=>1, 'message'=>"error your ip address"}
|
74
|
-
@parent.send_notice(session[:sid],
|
74
|
+
@parent.send_notice(notice_name, session[:sid], send_obj, :type=>2)
|
75
75
|
raise(DangoFrameworkMonitorSecurityError)
|
76
76
|
end
|
77
77
|
end
|
@@ -95,28 +95,28 @@ class ServerMonitorAction
|
|
95
95
|
}
|
96
96
|
|
97
97
|
send_obj = {'code'=>0, 'get_server_info'=>get_server_info}
|
98
|
-
@parent.send_notice(session[:sid],
|
98
|
+
@parent.send_notice('return__monitor_get_server_info', session[:sid], send_obj, :type=>2)
|
99
99
|
end
|
100
100
|
|
101
101
|
# メンテナンスコマンド:サーバーからクライアントへのデータ送信
|
102
102
|
def dango_server_monitor_get_shared(ret_obj)
|
103
103
|
logger.debug "dango_server_monitor_get_shared:#{ret_obj.inspect}"
|
104
104
|
send_obj = {'code'=>0, 'get_shared'=>shared.to_hash}
|
105
|
-
@parent.send_notice(session[:sid],
|
105
|
+
@parent.send_notice('return__monitor_get_shared', session[:sid], send_obj, :type=>2)
|
106
106
|
end
|
107
107
|
|
108
108
|
# メンテナンスコマンド:サーバーからクライアントへのデータ送信
|
109
109
|
def dango_server_monitor_get_session_list(ret_obj)
|
110
110
|
logger.debug "dango_server_monitor_get_session_list:#{ret_obj.inspect}"
|
111
111
|
send_obj = {'code'=>0, 'get_session_list'=>session_list}
|
112
|
-
@parent.send_notice(session[:sid],
|
112
|
+
@parent.send_notice('return__monitor_get_session_list', session[:sid], send_obj, :type=>2)
|
113
113
|
end
|
114
114
|
|
115
115
|
# メンテナンスコマンド:サーバーからクライアントへのデータ送信
|
116
116
|
def dango_server_monitor_get_socket_list(ret_obj)
|
117
117
|
logger.debug "dango_server_monitor_get_socket_list:#{ret_obj.inspect}"
|
118
118
|
send_obj = {'code'=>0, 'get_socket_list'=>socket_list.keys}
|
119
|
-
@parent.send_notice(session[:sid],
|
119
|
+
@parent.send_notice('return__monitor_get_socket_list', session[:sid], send_obj, :type=>2)
|
120
120
|
end
|
121
121
|
|
122
122
|
# メンテナンスコマンド:サーバーデータ再読み込み
|
@@ -125,7 +125,7 @@ class ServerMonitorAction
|
|
125
125
|
@server_reload = true
|
126
126
|
logger.debug "@server_reload=#{@server_reload.inspect}"
|
127
127
|
send_obj = {'code'=>0, 'message'=>'success'}
|
128
|
-
@parent.send_notice(session[:sid],
|
128
|
+
@parent.send_notice('return__monitor_server_reload', session[:sid], send_obj, :type=>2)
|
129
129
|
end
|
130
130
|
|
131
131
|
# メンテナンスコマンド:接続者全員へメッセージ送信
|
@@ -136,11 +136,11 @@ class ServerMonitorAction
|
|
136
136
|
socket_list.keys.each do |sid|
|
137
137
|
next if session[:sid] == sid
|
138
138
|
send_obj = { "message" => ret_obj["message"] }
|
139
|
-
@parent.send_notice(
|
139
|
+
@parent.send_notice('_notice_system_message', sid, send_obj)
|
140
140
|
end
|
141
141
|
|
142
142
|
send_obj = {'code'=>0, }
|
143
|
-
@parent.send_notice(session[:sid],
|
143
|
+
@parent.send_notice('return__monitor_send_system_message', session[:sid], send_obj, :type=>2)
|
144
144
|
end
|
145
145
|
|
146
146
|
end
|
@@ -16,23 +16,26 @@ require "dango/monitor/server_monitor_action"
|
|
16
16
|
class DangoServerFramework
|
17
17
|
include DangoFrameworkModule
|
18
18
|
|
19
|
+
env = ENV['RAILS_ENV'] || 'development'
|
20
|
+
|
19
21
|
### 以下すべてデフォルト値
|
20
22
|
DefaultNetworkPort = 15000 # デフォルトのポート番号
|
21
|
-
|
23
|
+
DefaultNetworkHost = 'localhost' # デフォルトのサーバーホスト名
|
24
|
+
DefaultServerHost = 'localhost' # 接続制限ホスト "0.0.0.0"にすれば全接続オッケイ
|
22
25
|
DefaultMaxConnections = 10 # デフォルトの最大接続人数
|
23
26
|
|
24
|
-
DefaultLogFile = "log/
|
27
|
+
DefaultLogFile = "log/dango_#{env}.log"
|
25
28
|
DefaultLogLevel = Logger::INFO
|
26
29
|
DefaultLogMaxSize = 1048576
|
27
30
|
DefaultLogShiftAge = 99
|
28
31
|
DefaultGServerLogFile = ""
|
29
32
|
|
30
33
|
# ここから先は普通は変更しなくていいだろうというもの
|
31
|
-
SendReceiveSleepIntervalSec = 0.2 #
|
34
|
+
SendReceiveSleepIntervalSec = 0.2 # データ送信時の送信間隔秒
|
32
35
|
SendReceiveTimeoutDefaultSec = 5.0 # データ送受信時のデフォルトタイムアウト秒数
|
33
|
-
SendTimeoutSec = 4.0 # データ送受信時の送信のタイムアウト秒数
|
36
|
+
# SendTimeoutSec = 4.0 # データ送受信時の送信のタイムアウト秒数
|
34
37
|
HeartBeatIntervalSec = 10.0 # heart beatのチェック間隔秒数
|
35
|
-
HeartBeatResponseWaitSec = 10.0 # S=>Cのheart beatの返信待ち秒数
|
38
|
+
# HeartBeatResponseWaitSec = 10.0 # S=>Cのheart beatの返信待ち秒数
|
36
39
|
HeartBeatReceiveWaitSec = 30.0 # C=>Sのheart beatの受信待ち秒数
|
37
40
|
GCIntervalSec = 5.0 # GCの発生タイミング
|
38
41
|
|
@@ -95,6 +98,11 @@ class DangoServerFramework
|
|
95
98
|
|
96
99
|
def exit_process() # プロセス終了処理
|
97
100
|
debug_print("shutdown")
|
101
|
+
begin
|
102
|
+
File.delete("tmp/pids/dango.pid")
|
103
|
+
rescue
|
104
|
+
puts "failed delete file. tmp/pids/dango.pid:#{$!.class}:#{$!.message}"
|
105
|
+
end
|
98
106
|
puts "shutdown"
|
99
107
|
exit!
|
100
108
|
end
|
@@ -124,6 +132,10 @@ class DangoServerFramework
|
|
124
132
|
@thr_gr_send_notice = ThreadGroup.new
|
125
133
|
@thr_gr_send_data = ThreadGroup.new
|
126
134
|
|
135
|
+
# データ送信用スレッドとQueue
|
136
|
+
@queue_send_notice = Queue.new
|
137
|
+
Thread.start{ thread_send_notice_queue() }
|
138
|
+
|
127
139
|
# サーバー開始
|
128
140
|
server_start()
|
129
141
|
|
@@ -146,13 +158,13 @@ class DangoServerFramework
|
|
146
158
|
set_server_variables() # 各種サーバー仕様の変数設定
|
147
159
|
|
148
160
|
logger.warn("===== server initialize =====") # loggerの準備
|
161
|
+
logger.warn("ENV['RAILS_ENV']=#{ENV['RAILS_ENV']}")
|
149
162
|
logger.warn("Process.pid=#{Process.pid}")
|
150
|
-
logger.warn("
|
151
|
-
logger.warn("
|
163
|
+
logger.warn("network_port=#{@network_port}")
|
164
|
+
logger.warn("network_host=#{@network_host}")
|
165
|
+
logger.warn("server_host=#{@server_host}")
|
152
166
|
logger.warn("max_connections=#{@server_max_connections}")
|
153
167
|
|
154
|
-
open("tmp/pids/dango.pid", "wb"){|fh| fh.write Process.pid.to_s }
|
155
|
-
|
156
168
|
session_init() # セッション情報の初期化
|
157
169
|
shared_init() # 共有メモリを初期化
|
158
170
|
notice_shared_init() # 通知共有メモリを初期化
|
@@ -169,7 +181,7 @@ class DangoServerFramework
|
|
169
181
|
TCPSocket.do_not_reverse_lookup = true # 逆引きを行わない
|
170
182
|
# TCPSocket.do_not_reverse_lookup = false # 逆引きを行う
|
171
183
|
|
172
|
-
@gserver = DangoGServer.new(self, @
|
184
|
+
@gserver = DangoGServer.new(self, @network_port, @server_host, @server_max_connections)
|
173
185
|
@gserver.audit = true # Turn logging on.
|
174
186
|
@gserver.debug = true # debug
|
175
187
|
|
@@ -180,6 +192,8 @@ class DangoServerFramework
|
|
180
192
|
|
181
193
|
GC.disable
|
182
194
|
|
195
|
+
open("tmp/pids/dango.pid", "wb"){|fh| fh.write Process.pid.to_s } # pidをファイルに保存
|
196
|
+
|
183
197
|
begin
|
184
198
|
@gserver.start
|
185
199
|
rescue Exception
|
@@ -252,14 +266,14 @@ class DangoServerFramework
|
|
252
266
|
|
253
267
|
# gserver開始処理
|
254
268
|
def starting()
|
255
|
-
msg = "#{self.class.to_s} #{@server_host}:#{@
|
269
|
+
msg = "#{self.class.to_s} #{@server_host}:#{@network_port}/#{@server_max_connections} start"
|
256
270
|
logger.warn msg
|
257
271
|
puts "[#{Time.now_to_s}] #{msg}"
|
258
272
|
end
|
259
273
|
|
260
274
|
# gserver終了処理
|
261
275
|
def stopping()
|
262
|
-
msg = "#{self.class.to_s} #{@server_host}:#{@
|
276
|
+
msg = "#{self.class.to_s} #{@server_host}:#{@network_port} stop"
|
263
277
|
logger.warn msg
|
264
278
|
puts "[#{Time.now_to_s}] #{msg}"
|
265
279
|
end
|
@@ -280,12 +294,9 @@ class DangoServerFramework
|
|
280
294
|
socket_list.add(sid, sock)
|
281
295
|
mutex_socket_list.add(sid)
|
282
296
|
|
283
|
-
|
297
|
+
session[:connected] = nil # まだdango_connectを呼び出していない
|
284
298
|
|
285
|
-
|
286
|
-
send_obj = {"_sid"=>sid}
|
287
|
-
send_notice(sid, "_notice_sid", send_obj)
|
288
|
-
logger.debug "_notice_sid #{sid} "
|
299
|
+
is_flash_policy_file = false
|
289
300
|
|
290
301
|
# 誰かが接続したときに60秒以上経った@arr_send_responseを削除
|
291
302
|
@mutex_send_response.synchronize do
|
@@ -299,9 +310,9 @@ class DangoServerFramework
|
|
299
310
|
break
|
300
311
|
end
|
301
312
|
|
302
|
-
|
313
|
+
ret_objs = nil
|
303
314
|
begin
|
304
|
-
|
315
|
+
ret_objs = dango_receive_data(sock) # データ受信処理
|
305
316
|
is_flash_policy_file = false
|
306
317
|
rescue DangoFrameworkFlashPolicyError
|
307
318
|
is_flash_policy_file = true
|
@@ -312,48 +323,72 @@ class DangoServerFramework
|
|
312
323
|
policy_data = <<EOF
|
313
324
|
<?xml version="1.0"?>
|
314
325
|
<cross-domain-policy>
|
315
|
-
<allow-access-from domain="
|
326
|
+
<allow-access-from domain="#{@network_host}" to-ports="#{@network_port}" />
|
316
327
|
</cross-domain-policy>
|
317
328
|
EOF
|
318
|
-
|
329
|
+
|
319
330
|
logger.debug policy_data
|
320
331
|
sock.write policy_data
|
321
332
|
sock.flush
|
322
|
-
sleep 1
|
333
|
+
sleep 0.1
|
323
334
|
raise(DangoFrameworkFlashPolicyError, "policy file sent. disconnectiong...")
|
324
335
|
|
325
|
-
elsif
|
326
|
-
# logger.debug "
|
336
|
+
elsif ret_objs == [] # 受信データがなければ
|
337
|
+
# logger.debug "ret_objs is empty. "
|
327
338
|
|
328
339
|
else # 受信データがあれば
|
329
|
-
if !
|
330
|
-
|
331
|
-
|
340
|
+
if ! session[:connected] # まだdango_connectを呼び出していないなら
|
341
|
+
# 接続直後のsid通知
|
342
|
+
send_obj = {"_sid"=>sid}
|
343
|
+
send_notice("_notice_sid", sid, send_obj)
|
344
|
+
logger.debug "_notice_sid #{sid} "
|
345
|
+
|
346
|
+
session[:connected] = true
|
347
|
+
dango_connect() # 接続時メソッド呼び出し
|
332
348
|
end
|
333
349
|
|
334
|
-
#
|
335
|
-
|
336
|
-
|
337
|
-
|
350
|
+
ret_objs.each do |ret_obj| # 受信データループ
|
351
|
+
if !(ret_obj && ret_obj["action"]) # actionが無い場合はエラー
|
352
|
+
logger.warn "no action error:#{ret_obj.inspect}"
|
353
|
+
raise(DangoFrameworkError, "no action error")
|
354
|
+
end
|
338
355
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
begin
|
349
|
-
__send__("dango_receive_#{action_name}", ret_obj)
|
350
|
-
rescue NoMethodError
|
351
|
-
@recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
|
352
|
-
logger.error "not find action #{action_name}:#{sid}:#{error_message($!, 'u')}"
|
356
|
+
# アクション名
|
357
|
+
action_name = ret_obj["action"].to_s
|
358
|
+
session[:_action_name] = action_name
|
359
|
+
|
360
|
+
# 自動返信用データ
|
361
|
+
session[:_return] = {}
|
362
|
+
ret_obj.each do |key, value|
|
363
|
+
if key =~ /^_return_(.*)$/
|
364
|
+
session[:_return][$1.to_sym] = value
|
353
365
|
end
|
354
366
|
end
|
355
367
|
|
356
|
-
|
368
|
+
@mutex_proc_thread.synchronize do
|
369
|
+
|
370
|
+
if action_name[0, 9] == '_monitor_' # メンテナンスアクション名なら
|
371
|
+
ServerMonitorAction.new(self, @config, sock, ret_obj)
|
372
|
+
|
373
|
+
elsif action_name == '_response' # 送信パケットの返事なら
|
374
|
+
action_name_is_response(ret_obj)
|
375
|
+
|
376
|
+
else # メンテナンスコマンド以外のユーザーアクション名なら
|
377
|
+
logger.debug "receive_action:#{sid}:#{action_name}:"
|
378
|
+
begin
|
379
|
+
__send__("dango_receive_#{action_name}", ret_obj)
|
380
|
+
rescue NoMethodError
|
381
|
+
@recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
|
382
|
+
logger.error "not find action #{action_name}:#{sid}:#{error_message($!, 'u')}"
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
end # @mutex_proc_thread.synchronize
|
387
|
+
|
388
|
+
# 不要になったセッション内のデータを削除(sidは再利用されるので消さない)
|
389
|
+
session.delete(:_action_name)
|
390
|
+
session.delete(:_return)
|
391
|
+
end
|
357
392
|
end
|
358
393
|
|
359
394
|
end # loop
|
@@ -385,8 +420,10 @@ EOF
|
|
385
420
|
|
386
421
|
@mutex_proc_thread.synchronize do
|
387
422
|
begin
|
388
|
-
|
389
|
-
|
423
|
+
if !is_flash_policy_file # Flash Policy Fileなら切断処理不要
|
424
|
+
logger.info "#{sock.inspect} #{sid} is closing"
|
425
|
+
dango_close() # 接続解除時に呼び出されるメソッド
|
426
|
+
end
|
390
427
|
rescue Exception
|
391
428
|
logger.error "#{sock.inspect} #{sid} ERROR\n#{error_message($!, 'u')}"
|
392
429
|
ensure
|
@@ -407,9 +444,9 @@ EOF
|
|
407
444
|
|
408
445
|
# action_nameが送信パケットの返事なら
|
409
446
|
def action_name_is_response(ret_obj)
|
410
|
-
logger.debug "action_name_is_response: #{ret_obj['_id']} #{session[:sid]}
|
447
|
+
logger.debug "action_name_is_response: #{ret_obj['_id'].inspect} #{session[:sid].inspect}"
|
411
448
|
@mutex_send_response.synchronize do
|
412
|
-
@arr_send_response.push({:_id => ret_obj["_id"], :time => Time.now})
|
449
|
+
@arr_send_response.push({:_id => ret_obj["_id"], :_sid => session[:sid], :time => Time.now})
|
413
450
|
end
|
414
451
|
end
|
415
452
|
|
@@ -420,7 +457,8 @@ EOF
|
|
420
457
|
Thread.abort_on_exception = true if @server_debug
|
421
458
|
|
422
459
|
# 変数の初期設定
|
423
|
-
@
|
460
|
+
@network_port = @config['network']['port'] || DefaultNetworkPort
|
461
|
+
@network_host = @config['network']['host'] || DefaultNetworkHost
|
424
462
|
@server_host = @config['server']['host'] || DefaultServerHost
|
425
463
|
@server_max_connections = @config['server']['max_connections'] || DefaultMaxConnections
|
426
464
|
@log_file = @config['server']['log_file'] || DefaultLogFile
|
@@ -431,9 +469,9 @@ EOF
|
|
431
469
|
@policy_file_request = @config['server']['policy_file_request'] || true
|
432
470
|
@send_receive_sleep_interval_sec = @config['server']['send_receive_sleep_interval_sec'] || SendReceiveSleepIntervalSec
|
433
471
|
@send_receive_timeout_default_sec = @config['server']['send_receive_timeout_default_sec'] || SendReceiveTimeoutDefaultSec
|
434
|
-
@send_timeout_sec = @config['server']['send_timeout_sec'] || SendTimeoutSec
|
472
|
+
# @send_timeout_sec = @config['server']['send_timeout_sec'] || SendTimeoutSec
|
435
473
|
@herat_beat_interval_sec = @config['server']['heart_beat_interval_sec'] || HeartBeatIntervalSec
|
436
|
-
@heart_beat_response_wait_sec = @config['server']['heart_beat_response_wait_sec'] || HeartBeatResponseWaitSec
|
474
|
+
# @heart_beat_response_wait_sec = @config['server']['heart_beat_response_wait_sec'] || HeartBeatResponseWaitSec
|
437
475
|
@heart_beat_receive_wait_sec = @config['server']['heart_beat_receive_wait_sec'] || HeartBeatReceiveWaitSec
|
438
476
|
@gc_interval_sec = @config['server']['gc_interval_sec'] || GCIntervalSec
|
439
477
|
|
@@ -545,7 +583,7 @@ EOF
|
|
545
583
|
@parent.logger.debug "self.get_connectables(key):#{self.get_connectables(key).inspect}"
|
546
584
|
|
547
585
|
self.get_connectables(key).each do |sid|
|
548
|
-
@parent.send_notice(
|
586
|
+
@parent.send_notice("notice_shared_#{key}", sid, value)
|
549
587
|
end
|
550
588
|
end
|
551
589
|
|
@@ -646,7 +684,7 @@ EOF
|
|
646
684
|
GC.enable
|
647
685
|
GC.start
|
648
686
|
GC.disable
|
649
|
-
logger.
|
687
|
+
logger.info "GC end #{Time.now - gc_start_time}sec "
|
650
688
|
# Thread.critical = false
|
651
689
|
|
652
690
|
rescue Exception
|
@@ -677,7 +715,7 @@ EOF
|
|
677
715
|
socket_list.keys.each do |sid|
|
678
716
|
sock = socket_list[sid]
|
679
717
|
# logger.debug "heart_beat_thread_start:sid=#{sid} #{sock} #{sock.closed?}"
|
680
|
-
# send_notice(
|
718
|
+
# send_notice("_heart_beat", sid, {}, {:timeout=>@heart_beat_response_wait_sec})
|
681
719
|
|
682
720
|
# クライアントから来たハートビートの時間チェックし、古ければsocketを閉じて、threadを殺す
|
683
721
|
if heart_beat_time_hash[sid] && heart_beat_time_hash[sid] < Time.now - @heart_beat_receive_wait_sec
|
@@ -721,119 +759,196 @@ EOF
|
|
721
759
|
end
|
722
760
|
end
|
723
761
|
|
762
|
+
# サーバーからクライアントへのデータ返信
|
763
|
+
def send_return(send_obj, options = {})
|
764
|
+
logger.info "send_return(#{session[:sid].inspect}) "
|
765
|
+
|
766
|
+
raise(DangoFrameworkError, "session[:sid] is not exist.") if ! session[:sid]
|
767
|
+
raise(DangoFrameworkError, "session[:_action_name] is not exist.") if ! session[:_action_name]
|
768
|
+
|
769
|
+
send_notice("return_#{session[:_action_name]}", session[:sid], send_obj, options)
|
770
|
+
end
|
771
|
+
|
724
772
|
# サーバーからクライアントへのデータ送信
|
725
|
-
def send_notice(
|
726
|
-
logger.info "send_notice(#{
|
727
|
-
# logger.debug "send_notice(#{sid.inspect}, #{notice_name.inspect}, #{send_obj.inspect}, #{options.inspect})"
|
773
|
+
def send_notice(notice_name, sids, send_obj, options = {})
|
774
|
+
logger.info "send_notice(#{notice_name.inspect}, #{sids.inspect}) "
|
728
775
|
|
729
776
|
raise(DangoFrameworkError, "send_obj is not Hash.") if ! send_obj.is_a?(Hash)
|
730
777
|
|
731
|
-
|
778
|
+
sids = [sids] if sids.is_a?(Integer)
|
779
|
+
raise(DangoFrameworkError, "sids is not Array.") if ! sids.is_a?(Array)
|
780
|
+
|
781
|
+
# timeout = options[:timeout] || @send_receive_timeout_default_sec
|
732
782
|
dtype = options[:type] || 0
|
733
783
|
|
734
|
-
|
735
|
-
if !sock || sock.closed? # sockがないという事はすでに切断済み
|
736
|
-
logger.info "send_notice:already closed socket. sid=#{sid.inspect} sock=#{sock.inspect} #{sock ? sock.closed? : nil} "
|
737
|
-
return(self)
|
738
|
-
end
|
784
|
+
# is_error = false
|
739
785
|
|
740
|
-
|
741
|
-
if notice_name.to_s == "_notice_sid"
|
742
|
-
raise(DangoFrameworkError, "not found sid=#{sid}") if !sock
|
743
|
-
raise(DangoFrameworkConnectionError, "socket closed. sid=#{sid}") if sock.closed?
|
744
|
-
|
786
|
+
sids.each do |sid|
|
745
787
|
send_obj_dup = send_obj.deep_dup
|
746
788
|
send_obj_dup["notice"] = notice_name.to_s
|
747
789
|
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
790
|
+
# send_id = sid.to_s + notice_name.to_s + Time.now.to_f.to_s + rand().to_s
|
791
|
+
send_id = notice_name.to_s + Time.now.to_f.to_s + rand().to_s
|
792
|
+
# send_id = Digest::MD5.hexdigest(sid.to_s + notice_name.to_s + Time.now.to_f.to_s + rand().to_s)
|
793
|
+
send_obj_dup["_id"] = send_id
|
794
|
+
|
795
|
+
=begin
|
796
|
+
sock = socket_list[sid]
|
797
|
+
if !sock || sock.closed? # sockがないという事はすでに切断済み
|
798
|
+
logger.info "send_notice:already closed socket. sid=#{sid.inspect} sock=#{sock.inspect} #{sock ? sock.closed? : nil} "
|
799
|
+
return(self)
|
800
|
+
end
|
801
|
+
|
802
|
+
# if !sock
|
803
|
+
# logger.info "send_notice:not found sid=#{sid}"
|
804
|
+
# is_error = true
|
805
|
+
# end
|
806
|
+
|
807
|
+
# if sock.closed?
|
808
|
+
# logger.info "send_notice:socket closed. sid=#{sid}"
|
809
|
+
# is_error = true
|
810
|
+
# end
|
811
|
+
|
812
|
+
# sidの通知の場合はレスポンスを気にしない
|
813
|
+
# if notice_name.to_s == "_notice_sid"
|
814
|
+
dango_send_data(sock, [send_obj_dup], :type=>dtype) # データ送信
|
815
|
+
# else
|
816
|
+
# send_notice_thread(sid, notice_name, send_obj_dup, dtype, timeout, sock) # thread for notice send
|
817
|
+
# end
|
818
|
+
=end
|
819
|
+
|
820
|
+
@queue_send_notice.push([sid, send_obj_dup, dtype])
|
821
|
+
end # end sids.each
|
822
|
+
|
823
|
+
# raise(DangoFrameworkConnectionError, "send_notice:error happened.") if is_error
|
824
|
+
|
825
|
+
self
|
826
|
+
end
|
827
|
+
|
828
|
+
# thread for send_notice_queue
|
829
|
+
def thread_send_notice_queue()
|
830
|
+
loop do
|
831
|
+
begin
|
832
|
+
send_data_list = []
|
833
|
+
send_data_list.push(@queue_send_notice.pop) # Queueデータ待ち
|
834
|
+
logger.debug "thread_send_notice_queue:sending data"
|
835
|
+
while(! @queue_send_notice.empty?) do # 残りのデータもQueueに入れていく
|
836
|
+
send_data_list.push(@queue_send_notice.pop)
|
837
|
+
end
|
838
|
+
|
839
|
+
send_data_sid_list = {}
|
840
|
+
send_data_dtype_list = {}
|
841
|
+
send_data_list.each do |one_send_data| # sidごとに分ける
|
842
|
+
sid = one_send_data[0]
|
843
|
+
send_obj = one_send_data[1]
|
844
|
+
dtype = one_send_data[2]
|
845
|
+
send_data_sid_list[sid] = [] if ! send_data_sid_list.has_key?(sid)
|
846
|
+
send_data_sid_list[sid].push(send_obj)
|
847
|
+
send_data_dtype_list[sid] = dtype
|
848
|
+
end
|
849
|
+
|
850
|
+
# sidごとにデータをまとめ送り
|
851
|
+
send_data_sid_list.each do |sid, one_send_data_sid|
|
852
|
+
sock = socket_list[sid]
|
853
|
+
if !sock
|
854
|
+
logger.info "thread_send_notice_queue:not found sid=#{sid} sock=#{sock.inspect}"
|
855
|
+
next
|
856
|
+
end
|
754
857
|
|
755
|
-
|
756
|
-
|
858
|
+
if sock.closed?
|
859
|
+
logger.info "thread_send_notice_queue:socket closed. sid=#{sid} sock=#{sock.inspect}"
|
860
|
+
next
|
861
|
+
end
|
757
862
|
|
758
|
-
|
759
|
-
|
863
|
+
begin
|
864
|
+
dango_send_data(sock, one_send_data_sid, :type=>send_data_dtype_list[sid]) # データ送信
|
865
|
+
rescue DangoFrameworkConnectionError
|
866
|
+
logger.info "thread_send_notice_queue:failed send. sid=#{sid} sock=#{sock.inspect} #{$!.class}"
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
sleep @send_receive_sleep_interval_sec # スリープ
|
871
|
+
|
872
|
+
rescue Exception
|
873
|
+
logger.warn "ERROR:thread_send_notice_queue:Exception:#{error_message($!, 'u')}"
|
874
|
+
end
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
=begin
|
879
|
+
# thread for notice send
|
880
|
+
def send_notice_thread(sid, notice_name, send_obj_dup, dtype, timeout, sock)
|
881
|
+
Thread.start(sid, notice_name, send_obj_dup, dtype, timeout, sock) do
|
882
|
+
begin
|
883
|
+
@thr_gr_send_notice.add(Thread.current) # send_noticeスレッドグループに登録
|
884
|
+
|
885
|
+
mutex_socket_list.synchronize(sid) do
|
886
|
+
have_came_response = nil
|
760
887
|
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
dango_send_data(sock, send_obj_dup, :type=>dtype) # データ送信
|
773
|
-
# logger.debug "send_notice:sent:notice_name=#{send_obj_dup['_id']} #{notice_name.inspect} #{sid} "
|
774
|
-
rescue DangoFrameworkConnectionError
|
775
|
-
logger.warn "send_notice:DangoFrameworkConnectionError:notice_name=#{notice_name.inspect} #{sid} "
|
776
|
-
rescue DangoFrameworkError
|
777
|
-
logger.warn "ERROR:send_notice:DangoFrameworkError:notice_name=#{notice_name.inspect} #{sid} \n #{error_message($!, 'u')}"
|
778
|
-
rescue Exception
|
779
|
-
logger.warn "ERROR:send_notice:Exception:notice_name=#{notice_name.inspect} #{sid} \n #{error_message($!, 'u')}"
|
780
|
-
end
|
888
|
+
receive_thread = Thread.start(sock, send_obj_dup, dtype) do
|
889
|
+
begin
|
890
|
+
@thr_gr_send_data.add(Thread.current) # send_dataスレッドグループに登録
|
891
|
+
|
892
|
+
dango_send_data(sock, [send_obj_dup], :type=>dtype) # データ送信
|
893
|
+
rescue DangoFrameworkConnectionError
|
894
|
+
logger.warn "send_notice:DangoFrameworkConnectionError:notice_name=#{notice_name.inspect} #{sid} "
|
895
|
+
rescue DangoFrameworkError
|
896
|
+
logger.warn "ERROR:send_notice:DangoFrameworkError:notice_name=#{notice_name.inspect} #{sid} \n #{error_message($!, 'u')}"
|
897
|
+
rescue Exception
|
898
|
+
logger.warn "ERROR:send_notice:Exception:notice_name=#{notice_name.inspect} #{sid} \n #{error_message($!, 'u')}"
|
781
899
|
end
|
900
|
+
end
|
901
|
+
|
902
|
+
# データ送信スレッドの終了待ち
|
903
|
+
if !receive_thread.join(@send_timeout_sec)
|
904
|
+
# タイムアウトの場合は
|
905
|
+
logger.warn "send_notice:send timeout:#{notice_name} #{sid} "
|
906
|
+
else
|
907
|
+
end_reserved_time = Time.now + timeout
|
782
908
|
|
783
|
-
#
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
# タイムアウトチェック
|
792
|
-
catch(:send_timeout) do
|
793
|
-
(timeout.to_f / @send_receive_sleep_interval_sec).to_i.times do
|
794
|
-
sleep @send_receive_sleep_interval_sec # スリープ
|
909
|
+
# タイムアウトチェック
|
910
|
+
catch(:send_timeout) do
|
911
|
+
(timeout.to_f / @send_receive_sleep_interval_sec).to_i.times do
|
912
|
+
sleep @send_receive_sleep_interval_sec # スリープ
|
913
|
+
|
914
|
+
@mutex_send_response.synchronize do # データ送信の返信が来たかどうかの確認
|
915
|
+
find_res = @arr_send_response.find{|r| r[:_id] == send_obj_dup["_id"] && r[:_sid] == sid }
|
795
916
|
|
796
|
-
|
797
|
-
find_res
|
917
|
+
if find_res
|
918
|
+
logger.debug "send_notice:find_res _heart_beat #{sid}" if notice_name.to_s == "_heart_beat"
|
798
919
|
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
@arr_send_response.delete(find_res)
|
803
|
-
have_came_response = true
|
804
|
-
throw(:send_timeout)
|
805
|
-
end
|
920
|
+
@arr_send_response.delete(find_res)
|
921
|
+
have_came_response = true
|
922
|
+
throw(:send_timeout)
|
806
923
|
end
|
924
|
+
end
|
925
|
+
|
926
|
+
if Time.now > end_reserved_time
|
927
|
+
logger.debug "send_notice:receive timeout:#{notice_name} #{sid} #{end_reserved_time}"
|
807
928
|
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
if notice_name.to_s == "_heart_beat" # heart beatだったらsockを止める
|
813
|
-
logger.info "!!!! send_notice:heart_beat timeout"
|
814
|
-
sock.close if !sock.closed?
|
815
|
-
end
|
816
|
-
break
|
929
|
+
# このコードは不要なはずだが念の為取っておいてある、安定したことが確認できたら削除する
|
930
|
+
if notice_name.to_s == "_heart_beat" # heart beatだったらsockを止める
|
931
|
+
logger.info "!!!! send_notice:heart_beat timeout"
|
932
|
+
sock.close if !sock.closed?
|
817
933
|
end
|
818
|
-
|
819
|
-
end
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
934
|
+
break
|
935
|
+
end
|
936
|
+
|
937
|
+
end # タイムアウト処理終わり
|
938
|
+
end # catch 終わり
|
939
|
+
|
940
|
+
if !have_came_response # 戻ってきたデータがあるかどうかチェック
|
941
|
+
logger.warn "!!! received data is none:#{notice_name} #{sid} #{send_obj_dup['_id']} "
|
825
942
|
end
|
826
|
-
end
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
end
|
831
|
-
|
832
|
-
end
|
833
|
-
|
834
|
-
self
|
943
|
+
end
|
944
|
+
end # mutex
|
945
|
+
rescue Exception
|
946
|
+
logger.error "send_response_thread error:#{error_message($!, 'u')}"
|
947
|
+
end
|
948
|
+
end # Thread:end
|
835
949
|
end
|
836
|
-
|
950
|
+
=end
|
951
|
+
|
837
952
|
# 必要に応じて追加するメソッド
|
838
953
|
def method_missing(name, *args)
|
839
954
|
if name.to_s =~ /^dango_receive_action_notice_shared_(.+)/ # 共有メモリ変更通知なら
|