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.
@@ -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_(.+)/ # 共有メモリ変更通知なら