dango 0.1.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- dango_client_init() # 初期設定読み込み
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
- ret_obj = nil
114
+ ret_objs = nil
108
115
  begin
109
- ret_obj = dango_receive_data(@sock) # データ受信処理
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:#{ret_obj.inspect} #{@sid}"
124
+ logger.debug "finished dango_receive_data:#{ret_objs.inspect} #{@sid}"
118
125
 
119
- if !(ret_obj && ret_obj["notice"])
120
- logger.info "no notice:#{ret_obj["notice"].inspect} #{@sid}"
121
- end
122
-
123
- # メソッド呼び出し
124
- logger.info "calling method=#{ret_obj["notice"].inspect} #{@sid} "
125
- begin
126
- __send__("dango_receive_#{ret_obj["notice"]}", ret_obj)
127
- rescue
128
- logger.error "error in dango_receive_#{ret_obj["notice"]} #{@sid} \n#{error_message($!, 'u')}"
129
- ensure
130
- # データの受信の送信返し
131
- response_notice_name = "_response"
132
- send_obj = {"_id" => ret_obj["_id"]}
133
- send_action(response_notice_name, send_obj)
134
- logger.debug "response_notice_name=#{response_notice_name.inspect} #{@sid} "
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
  # サーバーからクライアントへのデータ送信
@@ -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, send_obj, options = {})
227
- # logger.debug "dango_send_data:send_obj=#{send_obj.inspect}"
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 send_obj == {}
232
+ if send_objs == []
232
233
  send_data_orig = ""
233
234
  elsif dtype == 0
234
- send_data_orig = JSON.generate(send_obj)
235
+ send_data_orig = JSON.generate(send_objs)
235
236
  elsif dtype == 1
236
- send_data_orig = send_obj.to_yaml
237
+ send_data_orig = send_objs.to_yaml
237
238
  elsif dtype == 2
238
- send_data_orig = Marshal.dump(send_obj)
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], notice_name, send_obj, :type=>2)
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], 'return__monitor_get_server_info', send_obj, :type=>2)
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], 'return__monitor_get_shared', send_obj, :type=>2)
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], 'return__monitor_get_session_list', send_obj, :type=>2)
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], 'return__monitor_get_socket_list', send_obj, :type=>2)
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], 'return__monitor_server_reload', send_obj, :type=>2)
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(sid, '_notice_system_message', send_obj)
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], 'return__monitor_send_system_message', send_obj, :type=>2)
143
+ @parent.send_notice('return__monitor_send_system_message', session[:sid], send_obj, :type=>2)
144
144
  end
145
145
 
146
146
  end
@@ -1,9 +1,11 @@
1
1
  #!ruby -Ku
2
2
 
3
-
4
3
  require 'yaml'
5
4
  require 'pp'
6
5
 
6
+ require 'rubygems'
7
+ require 'active_support'
8
+
7
9
  require 'dango/server_framework'
8
10
 
9
11
  require RAILS_ROOT + '/config/environment'
@@ -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
- DefaultServerHost = 'localhost' # デフォルトのホスト名 # 接続制限ホスト "0.0.0.0"にすれば全接続オッケイ
23
+ DefaultNetworkHost = 'localhost' # デフォルトのサーバーホスト名
24
+ DefaultServerHost = 'localhost' # 接続制限ホスト "0.0.0.0"にすれば全接続オッケイ
22
25
  DefaultMaxConnections = 10 # デフォルトの最大接続人数
23
26
 
24
- DefaultLogFile = "log/dango_development.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("port=#{@server_port}")
151
- logger.warn("host=#{@server_host}")
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, @server_port, @server_host, @server_max_connections)
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}:#{@server_port}/#{@server_max_connections} start"
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}:#{@server_port} stop"
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
- dango_connect() # 接続時メソッド呼び出し
297
+ session[:connected] = nil # まだdango_connectを呼び出していない
284
298
 
285
- # 接続直後のsid通知
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
- ret_obj = nil
313
+ ret_objs = nil
303
314
  begin
304
- ret_obj = dango_receive_data(sock) # データ受信処理
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="*" to-ports="*" />
326
+ <allow-access-from domain="#{@network_host}" to-ports="#{@network_port}" />
316
327
  </cross-domain-policy>
317
328
  EOF
318
- policy_data += "\0" + "\n"
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 ret_obj == {} # 受信データがなければ
326
- # logger.debug "ret_obj is empty. "
336
+ elsif ret_objs == [] # 受信データがなければ
337
+ # logger.debug "ret_objs is empty. "
327
338
 
328
339
  else # 受信データがあれば
329
- if !(ret_obj && ret_obj["action"]) # actionが無い場合はエラー
330
- logger.warn "no action error:#{ret_obj.inspect}"
331
- raise(DangoFrameworkError, "no action error")
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
- action_name = ret_obj["action"].to_s
336
-
337
- @mutex_proc_thread.synchronize do
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
- if action_name == '_response' # 送信パケットの返事なら
340
- # logger.debug "action_name=#{action_name} #{ret_obj['_id']} "
341
- action_name_is_response(ret_obj)
342
-
343
- elsif action_name[0, 9] == '_monitor_' # メンテナンスアクション名なら
344
- ServerMonitorAction.new(self, @config, sock, ret_obj)
345
-
346
- else # メンテナンスコマンド以外のユーザーアクション名なら
347
- logger.info "receive_action:#{sid}:#{action_name}:"
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
- end # @mutex_proc_thread.synchronize
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
- logger.info "#{sock.inspect} #{sid} is closing"
389
- dango_close() # 接続解除時に呼び出されるメソッド
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
- @server_port = @config['network']['port'] || DefaultNetworkPort
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(sid, "notice_shared_#{key}".to_sym, value)
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.debug "GC end #{Time.now - gc_start_time}sec "
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(sid, "_heart_beat", {}, {:timeout=>@heart_beat_response_wait_sec})
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(sid, notice_name, send_obj, options = {})
726
- logger.info "send_notice(#{sid.inspect}, #{notice_name.inspect}) "
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
- timeout = options[:timeout] || @send_receive_timeout_default_sec
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
- sock = socket_list[sid]
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
- # sidの通知の場合はレスポンスを気にしない
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
- dango_send_data(sock, send_obj_dup, :type=>dtype) # データ送信
749
- # logger.debug "send_notice:finish send data notice_name=#{notice_name.inspect}\n"
750
- else
751
- Thread.start(sid, notice_name, send_obj, dtype, timeout, sock) do
752
- begin
753
- @thr_gr_send_notice.add(Thread.current) # send_noticeスレッドグループに登録
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
- raise(DangoFrameworkError, "not found sid=#{sid}") if !sock
756
- raise(DangoFrameworkConnectionError, "socket closed. sid=#{sid}") if sock.closed?
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
- send_obj_dup = send_obj.deep_dup
759
- send_obj_dup["notice"] = notice_name.to_s
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
- mutex_socket_list.synchronize(sid) do
762
- # logger.debug "mutex_socket_list:synchronize:#{notice_name} #{sid} "
763
-
764
- digest_key = sid.to_s + notice_name.to_s + Time.now.to_f.to_s + rand().to_s
765
- send_obj_dup["_id"] = Digest::MD5.hexdigest(digest_key)
766
- have_came_response = nil
767
-
768
- receive_thread = Thread.start(sock, send_obj_dup, dtype) do
769
- begin
770
- @thr_gr_send_data.add(Thread.current) # send_dataスレッドグループに登録
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
- if !receive_thread.join(@send_timeout_sec)
785
- # タイムアウトの場合は
786
- logger.warn "send_notice:send timeout:#{notice_name} #{sid} "
787
- else
788
- # logger.warn "send_notice:sent after join:#{notice_name} #{sid} "
789
- end_reserved_time = Time.now + timeout
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
- @mutex_send_response.synchronize do # データ送信の返信が来たかどうかの確認
797
- find_res = @arr_send_response.find{|r| r[:_id] == send_obj_dup["_id"]}
917
+ if find_res
918
+ logger.debug "send_notice:find_res _heart_beat #{sid}" if notice_name.to_s == "_heart_beat"
798
919
 
799
- if find_res
800
- logger.debug "send_notice:find_res _heart_beat #{sid}" if notice_name.to_s == "_heart_beat"
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
- if Time.now > end_reserved_time
809
- logger.debug "send_notice:receive timeout:#{notice_name} #{sid} #{end_reserved_time}"
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
- end # catch 終わり
821
-
822
- if !have_came_response # 戻ってきたデータがあるかどうかチェック
823
- logger.warn "!!! received data is none:#{notice_name} #{sid} #{send_obj_dup['_id']} "
824
- end
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 # mutex
827
- rescue Exception
828
- logger.error "send_response_thread error:#{error_message($!, 'u')}"
829
- end
830
- end # Thread: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_(.+)/ # 共有メモリ変更通知なら