dango 0.4.8 → 0.5.0

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.
@@ -10,11 +10,15 @@ require "dango/framework_base"
10
10
  require "dango/socket_list"
11
11
  require "dango/version"
12
12
  require "dango/session_manager"
13
- require "dango/monitor/server_monitor_action"
13
+ #require "dango/monitor/server_monitor_action"
14
+ require "dango/monitor/server_monitor_module"
15
+ require "dango/default_dango_receive"
14
16
 
15
17
  # フレームワーククラス
16
18
  class DangoServerFramework
17
19
  require "dango/dango_g_server"
20
+ include DefaultDangoReceive
21
+ include ServerMonitorModule
18
22
 
19
23
  include DangoFrameworkModule
20
24
 
@@ -107,14 +111,15 @@ class DangoServerFramework
107
111
 
108
112
  # スレッドグループの初期化
109
113
  @thr_gr_gserver_serve = ThreadGroup.new
110
- @thr_gr_send_notice = ThreadGroup.new
111
- @thr_gr_send_data = ThreadGroup.new
112
114
 
113
115
  # データ送信用スレッドとQueue
114
116
  @queue_send_notice = Queue.new
115
- @mutex_send_notice = Mutex.new
117
+ @mutex_send_notice = DangoMutex.new(:mutex_send_notice)
116
118
  Thread.start{ thread_send_notice_queue() }
117
119
 
120
+ # メインスレッドの名前
121
+ Thread.current[:_name] = "main"
122
+
118
123
  # サーバー開始
119
124
  server_start()
120
125
 
@@ -146,31 +151,42 @@ class DangoServerFramework
146
151
  logger.warn("max_connections=#{@server_max_connections}")
147
152
  logger.warn("RAILS_ENV=#{RAILS_ENV}")
148
153
  logger.warn("Process.pid=#{Process.pid}")
149
- logger.warn("Dango Version=#{Dango::VERSION::STRING}")
150
- # logger.debug("$LOADED_FEATURES=#{$LOADED_FEATURES.pretty_inspect}")
154
+ logger.warn("Dango Version=#{Dango::VERSION::STRING} p11")
155
+ # logger.debug("$LOADED_FEATURES=#{$LOADED_FEATURES.pretty_inspect}")
151
156
 
152
157
  shared_init() # 共有メモリを初期化
153
158
  socket_list_init() # ソケット一覧を初期化
154
159
  @mutex_sock = {} # ソケットの排他処理ハッシュ
155
160
  @session_manager = SessionManager.new(shared, RAILS_ENV) # セッション情報の初期化
156
161
 
157
- @mutex_proc_thread = Mutex.new # スレッドが同時起動しないようにするためのMutex
162
+ @mutex_proc_thread = DangoMutex.new(:mutex_proc_thread) # スレッドが同時起動しないようにするためのMutex
158
163
  heart_beat_thread_start() # ハートビートスレッドの開始
159
164
  gc_thread_start() # GCスレッドの開始
160
165
 
161
166
  dango_server_init() # 初期設定読み込み
162
167
 
163
- @mutex_send_response = Mutex.new # 送信レスポンス用のMutex
164
- @arr_send_response = [] # 送信レスポンス用のキャッシュ
168
+ @mutex_send_response = DangoMutex.new(:mutex_send_response) # 送信レスポンス用のMutex
169
+ @arr_send_response = [] # 送信レスポンス用のキャッシュ
165
170
 
166
171
 
167
172
  TCPSocket.do_not_reverse_lookup = true # 逆引きを行わない
168
173
  # TCPSocket.do_not_reverse_lookup = false # 逆引きを行う
169
174
 
170
175
  if @backdoor_run_drb_server # backdoor用のdrbを起動
171
- uri = "druby://#{@network_host}:#{@backdoor_run_drb_port}"
172
- DRb.start_service(uri, self)
173
- logger.warn("start drb server: uri=#{DRb.uri}")
176
+ require "drb"
177
+ require "drb/acl"
178
+ # uri = "druby://#{@network_host}:#{@backdoor_run_drb_port}"
179
+ uri = @backdoor_run_drb_url
180
+ list = ["deny", "all", "allow", @backdoor_host]
181
+ acl = ACL.new(list, ACL::DENY_ALLOW)
182
+ @drb = DRb.start_service(uri, self, acl)
183
+ # @drb = DRb.start_service(uri, self)
184
+ DRb.thread[:_name] = "thread_drb_main"
185
+ message = "start drb server: uri=#{DRb.uri}"
186
+ logger.warn(message)
187
+ puts message
188
+ else
189
+ @drb = nil
174
190
  end
175
191
 
176
192
  set_loop_setting(@loop_setting) if @loop_setting # ループ処理を定義
@@ -193,9 +209,9 @@ class DangoServerFramework
193
209
  @gserver.start(@server_max_connections, 20) # backlogを20に設定
194
210
 
195
211
  rescue Exception
196
- puts error_message($!)
212
+ puts "gserver.start:" + error_message($!)
197
213
  # error_print(error_message($!, 'u'))
198
- exit
214
+ exit!
199
215
  end
200
216
  end
201
217
 
@@ -207,9 +223,14 @@ class DangoServerFramework
207
223
 
208
224
  debug_print("-- stopping server")
209
225
  stop_gserver() # gserverの停止
210
-
211
226
  @gserver = nil
212
227
 
228
+ if @drb # drbを起動していればそれの停止
229
+ DRb.stop_service()
230
+ puts "stop drb server"
231
+ @drb = nil
232
+ end
233
+
213
234
  debug_print("-- stopped server")
214
235
 
215
236
  # GCを行う
@@ -221,14 +242,14 @@ class DangoServerFramework
221
242
  debug_print("-- reload classes")
222
243
  tmp_verbose = $VERBOSE
223
244
  $VERBOSE = nil
224
-
245
+
225
246
  # serverファイル名一覧を取得
226
247
  load_files = []
227
248
  glob_str = 'dango/server/*.rb'
228
249
  Dir.glob(glob_str) do |srv_file|
229
250
  load_files.push({:file=>srv_file, :mtime=>File.mtime(srv_file)})
230
251
  end
231
-
252
+
232
253
  # ファイル名順にソート
233
254
  load_files = load_files.sort_by{|f| f[:file] }
234
255
  load_files.each do |f|
@@ -238,7 +259,7 @@ class DangoServerFramework
238
259
  debug_print("#{error_message($!, 'u')}")
239
260
  end
240
261
  end
241
-
262
+
242
263
  $VERBOSE = tmp_verbose
243
264
 
244
265
  # サーバーを再度起動
@@ -252,7 +273,7 @@ class DangoServerFramework
252
273
 
253
274
  # gserver接続開始処理
254
275
  def connecting(sock)
255
- logger.info "connecting:sock=#{sock} peeraddr=#{sock.peeraddr.inspect} addr=#{sock.addr.inspect}"
276
+ logger.info "connecting:sock=#{sock.object_id} peeraddr=#{sock.peeraddr.inspect} addr=#{sock.addr.inspect}"
256
277
  end
257
278
 
258
279
  # gserver接続開始処理
@@ -276,7 +297,8 @@ class DangoServerFramework
276
297
 
277
298
  # gserverのserveメソッド:スレッド開始処理
278
299
  def thread_main(sock)
279
- logger.info "thread_main:connect. sock=#{sock} thread.current=#{Thread.current.object_id}"
300
+ logger.info "thread_main:connect. sock=#{sock.object_id} thread.current=#{Thread.current.object_id}"
301
+ Thread.current[:_name] = "thread_main #{sock.object_id}"
280
302
 
281
303
  @thr_gr_gserver_serve.add(Thread.current) # スレッドグループに登録
282
304
 
@@ -285,9 +307,9 @@ class DangoServerFramework
285
307
  sid = session[:sid]
286
308
 
287
309
  # sockに対しての=nil write close などの書き換えに対する排他処理
288
- @mutex_sock[sock.object_id] = Mutex.new
310
+ @mutex_sock[sock.object_id] = DangoMutex.new("mutex_sock_#{sock.object_id}")
289
311
 
290
- @mutex_sock[sock.object_id].synchronize do
312
+ @mutex_sock[sock.object_id].timeout_sync(2, "start #{sock.object_id}") do
291
313
  sock.binmode
292
314
  sock.sync = true
293
315
 
@@ -298,7 +320,7 @@ class DangoServerFramework
298
320
 
299
321
  session[:encode_type] = DefaultEncodeType
300
322
 
301
- logger.debug "thread_main:start_session. sid=#{sid} sock=#{sock} thread.current=#{Thread.current.object_id}"
323
+ logger.debug "thread_main:start_session. sid=#{sid} sock=#{sock.object_id} thread.current=#{Thread.current.object_id}"
302
324
 
303
325
  socket_list.add(sid, sock)
304
326
 
@@ -306,28 +328,32 @@ class DangoServerFramework
306
328
 
307
329
  is_flash_policy_file = false
308
330
 
309
- # 誰かが接続したときに60秒以上経った@arr_send_responseを削除
310
- @mutex_send_response.synchronize do
311
- @arr_send_response.delete_if{|r| r[:time] < Time.now - 60}
312
- end
313
-
314
331
  logger.debug "thread_main:do main loop."
315
332
 
316
333
  # メインループ入り
334
+ count = 0
317
335
  loop do
318
336
  if sock.closed?
319
- logger.info "#{sock.inspect}:sock is closed..."
337
+ logger.info "#{sock.object_id}:sock is closed... #{count}"
320
338
  break
321
339
  end
322
340
 
323
341
  ret_objs = nil
324
342
  begin
343
+ logger.debug "dango_receive_data:start:sock=#{sock.object_id} #{count}" if count % 100 == 0
325
344
  ret_objs = dango_receive_data(sock) # データ受信処理
345
+ logger.debug "dango_receive_data:finish:sock=#{sock.object_id} #{count}" if count % 100 == 0
326
346
  is_flash_policy_file = false
327
347
  rescue DangoFrameworkFlashPolicyException
328
348
  is_flash_policy_file = true
329
349
  end
330
350
 
351
+ # メンテナンス機能
352
+ if shared[:_is_server_sleep]
353
+ logger.info "thread_main SLEEP !!!"
354
+ sleep 10000
355
+ end
356
+
331
357
  if is_flash_policy_file # Flashのポリシーファイルが来たら
332
358
  logger.debug "is_flash_policy_file"
333
359
  do_flash_policy_file(sid, sock)
@@ -340,6 +366,8 @@ class DangoServerFramework
340
366
  logger.debug "ret_objs is empty. "
341
367
 
342
368
  else # 受信データがあれば
369
+ logger.debug "dango_receive_data:ret_objs=#{ret_objs.class} #{count}" if count % 100 == 0
370
+
343
371
  ret_objs.each do |ret_obj| # 受信データループ
344
372
  if !(ret_obj && ret_obj["_action_name"]) # action_nameが無い場合はエラー
345
373
  logger.warn "no action_name error:#{ret_obj.inspect}"
@@ -351,37 +379,27 @@ class DangoServerFramework
351
379
  session[:_action_name] = action_name
352
380
 
353
381
  # 自動返信用データ
354
- session[:_return] = {}
382
+ return_data = {}
355
383
  ret_obj.each do |key, value|
356
384
  if key =~ /^_return_(.*)$/
357
- session[:_return][$1.to_sym] = value
385
+ return_data[$1.to_sym] = value
358
386
  end
359
387
  end
388
+ session[:_return] = return_data
360
389
 
361
- @mutex_proc_thread.synchronize do
362
-
363
- if action_name[0, 9] == '_monitor_' # メンテナンスアクション名なら
364
- peerhost = session[:peer_host]
365
- peeraddr = session[:peer_ip_address]
366
- ServerMonitorAction.new(self, @config, peerhost, peeraddr, ret_obj)
367
-
368
- elsif action_name == '_response' # 送信パケットの返事なら
369
- action_name_is_response(ret_obj)
370
-
371
- elsif action_name == '_change_encode_type' # エンコードタイプの変更なら
372
- action_name_is_change_encode_type(ret_obj)
373
-
374
- else # メンテナンスコマンド以外のユーザーアクション名なら
375
- logger.debug "receive_action:#{sid}:#{action_name}:"
376
- begin
377
- __send__("dango_receive_#{action_name}", ret_obj)
378
- rescue NoMethodError
379
- @recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
380
- logger.error "not find action #{action_name}:#{sid}:#{error_message($!, 'u')}"
381
- end
390
+ logger.debug "mpth:1:receive_action:session=#{sid} #{count}"
391
+ @mutex_proc_thread.timeout_sync(4, "receive_action_#{action_name}") do
392
+ logger.debug "mpth:2:receive_action:#{sid}:#{action_name}:"
393
+ begin
394
+ __send__("dango_receive_#{action_name}", ret_obj)
395
+ rescue NoMethodError
396
+ @recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
397
+ logger.error "not find action #{action_name}:#{sid}:#{error_message($!, 'u')}"
398
+ rescue DangoFrameworkTimeoutException
399
+ logger.error "action is timeout:#{action_name}:#{sid}:#{error_message($!, 'u')}"
382
400
  end
383
401
 
384
- end # @mutex_proc_thread.synchronize
402
+ end # @mutex_proc_thread
385
403
 
386
404
  # 不要になったセッション内のデータを削除(sidは再利用されるので消さない)
387
405
  session.delete(:_action_name)
@@ -389,7 +407,9 @@ class DangoServerFramework
389
407
  end
390
408
 
391
409
  if ! session[:connected] # まだdango_connectを呼び出していないなら
392
- @mutex_proc_thread.synchronize do
410
+ logger.debug "mpth:1:dango_connect"
411
+ @mutex_proc_thread.timeout_sync(4, :dango_connect) do
412
+ logger.debug "mpth:2:dango_connect"
393
413
  # 接続直後のsid通知
394
414
  send_obj = {"_sid"=>sid}
395
415
  send_notice("_notice_sid", sid, send_obj)
@@ -397,10 +417,12 @@ class DangoServerFramework
397
417
 
398
418
  dango_connect() # 接続時メソッド呼び出し
399
419
  session[:connected] = true
420
+
400
421
  end # mutex_proc_thread
401
422
  end
402
423
  end
403
424
 
425
+ count += 1
404
426
  end # loop
405
427
 
406
428
  rescue DangoFrameworkFlashPolicyException
@@ -424,6 +446,9 @@ class DangoServerFramework
424
446
  rescue DangoFrameworkDisconnectException
425
447
  logger.debug "DangoFrameworkDisconnectException. #{sid} \n#{error_message($!, 'u')}"
426
448
 
449
+ rescue DangoFrameworkMutexTimeoutException
450
+ logger.warn "DangoFrameworkMutexTimeoutException. #{sid} \n#{error_message($!, 'u')}"
451
+
427
452
  rescue DangoFrameworkException
428
453
  logger.debug "DangoFrameworkException. #{sid} \n#{error_message($!, 'u')}"
429
454
 
@@ -434,37 +459,62 @@ class DangoServerFramework
434
459
  # 接続切断の処理
435
460
 
436
461
  if !is_flash_policy_file # Flash Policy Fileなら切断処理不要
437
- logger.info "#{sock.inspect} #{sid} is closing"
462
+ logger.info "#{sock.object_id} #{sid} is closing"
438
463
  if session[:connected] # dango_connect()が実行済みなら
439
464
  begin
440
- @mutex_proc_thread.synchronize do
465
+ logger.debug "mpth:1:dango_close"
466
+ @mutex_proc_thread.timeout_sync(4, :dango_close) do
467
+ logger.debug "mpth:2:dango_close"
441
468
  dango_close() # 接続解除時に呼び出されるメソッド
469
+
470
+ # ハートビートのごみを削除
471
+ shared.transaction(:_heart_beat_time_hash) do |hbt_hash|
472
+ hbt_hash.delete(sid)
473
+ shared.commit(hbt_hash)
474
+ end
475
+
442
476
  end # mutex_proc_thread
477
+ logger.debug "dango_close end"
478
+
479
+ rescue DangoFrameworkMutexTimeoutException
480
+ logger.warn "DangoFrameworkMutexTimeoutException " +
481
+ "#{sock.object_id} #{sid} \n#{error_message($!, 'u')}"
443
482
  rescue Exception
444
- logger.error "#{sock.inspect} #{sid} ERROR\n#{error_message($!, 'u')}"
483
+ logger.error "#{sock.object_id} #{sid} ERROR\n#{error_message($!, 'u')}"
445
484
  end
446
485
  end
447
486
  end
448
487
 
449
488
  begin
450
- @mutex_sock[sock.object_id].synchronize do
489
+ @mutex_sock[sock.object_id].timeout_sync(2, "close #{sock.object_id}") do
451
490
  sock.close # ソケットを閉じる
452
491
  end
453
492
  rescue IOError
454
- logger.info "IOError #{sock.inspect} #{sid}"
493
+ logger.info "IOError #{sock.object_id} #{sid}"
494
+ rescue DangoFrameworkMutexTimeoutException
495
+ logger.warn "DangoFrameworkMutexTimeoutException #{sock.object_id} #{sid}\n" +
496
+ "#{error_message($!, 'u')}"
455
497
  rescue Exception
456
- logger.error "#{sock.inspect} #{sid} Exception\n#{error_message($!, 'u')}"
498
+ logger.error "#{sock.object_id} #{sid} Exception\n#{error_message($!, 'u')}"
457
499
  end
458
500
 
459
- logger.info "#{sock.inspect} #{sid} is closed"
501
+ logger.info "#{sock.object_id} #{sid} is closed"
460
502
 
461
503
  socket_list.delete(sid) # ソケットリストから削除
462
504
 
463
- @mutex_sock[sock.object_id].synchronize do
464
- sock = nil # ソケット削除
505
+ sock_object_id = sock.object_id
506
+ begin
507
+ @mutex_sock[sock_object_id].timeout_sync(2, "delete #{sock.object_id}") do
508
+ sock = nil # ソケット削除
509
+ end
510
+ rescue DangoFrameworkMutexTimeoutException
511
+ logger.warn "DangoFrameworkMutexTimeoutException #{sock.object_id} #{sid}\n" +
512
+ "#{error_message($!, 'u')}"
513
+ rescue Exception
514
+ logger.error "#{sock.object_id} #{sid} Exception\n#{error_message($!, 'u')}"
465
515
  end
466
516
 
467
- @mutex_sock.delete(sock.object_id) # ソケット排他処理から削除
517
+ @mutex_sock.delete(sock_object_id) # ソケット排他処理から削除
468
518
 
469
519
  @session_manager.close_session(sid) # sessionの終了処理
470
520
  end
@@ -492,7 +542,7 @@ class DangoServerFramework
492
542
  EOF
493
543
 
494
544
  logger.debug policy_data
495
- @mutex_sock[sock.object_id].synchronize do
545
+ @mutex_sock[sock.object_id].timeout_sync(2, "policy_send #{sock.object_id}") do
496
546
  sock.write policy_data
497
547
  sock.flush
498
548
  end
@@ -501,20 +551,6 @@ EOF
501
551
  end
502
552
  end
503
553
 
504
- # action_nameが送信パケットの返事なら
505
- def action_name_is_response(ret_obj)
506
- logger.debug "action_name_is_response: #{ret_obj['_id'].inspect} #{session[:sid].inspect}"
507
- @mutex_send_response.synchronize do
508
- @arr_send_response.push({:_id => ret_obj["_id"], :_sid => session[:sid], :time => Time.now})
509
- end
510
- end
511
-
512
- # action_nameが送信パケットの返事なら
513
- def action_name_is_change_encode_type(ret_obj)
514
- logger.debug "action_name_is_change_encode_type: #{ret_obj['encode_type'].inspect}"
515
- session[:encode_type] = ret_obj['encode_type']
516
- end
517
-
518
554
  # 各種サーバー仕様の変数設定
519
555
  def set_server_variables()
520
556
  # 変数の初期設定
@@ -552,7 +588,7 @@ EOF
552
588
  @statistics_process_memory = @config['server']['statistics_process_memory'] || false # プロセスのメモリ使用量統計取る
553
589
 
554
590
  @backdoor_run_drb_server = @config['server']['backdoor_run_drb_server'] || false # drbサーバーを起動するか
555
- @backdoor_run_drb_port = @config['server']['backdoor_run_drb_port'] || 12345 # drbサーバーのポート番号
591
+ @backdoor_run_drb_url = @config['server']['backdoor_run_drb_url'] || 12345 # drbサーバーのポート番号
556
592
  @backdoor_host = @config['server']['backdoor_host'] || '127.0.0.1' # バックドアのアクセス可能ホスト名
557
593
 
558
594
  @loop_setting = @config['server']['loop_setting'] # メインループ用の定義
@@ -612,6 +648,10 @@ EOF
612
648
  @session_manager.session
613
649
  end
614
650
 
651
+ def session_list
652
+ @session_manager.session_list
653
+ end
654
+
615
655
 
616
656
  # ソケットとIDの対応
617
657
  def socket_list_init
@@ -633,7 +673,7 @@ EOF
633
673
  def dango_server_send_encrypt(str) # 継承用
634
674
  str
635
675
  end
636
- def dango_send_encrypt(str) # フレームワークから呼ばれる部分
676
+ def send_encrypt(str) # フレームワークから呼ばれる部分
637
677
  dango_server_send_encrypt(str)
638
678
  end
639
679
 
@@ -641,32 +681,38 @@ EOF
641
681
  def dango_server_receive_decrypt(str) # 継承用
642
682
  str
643
683
  end
644
- def dango_receive_decrypt(str) # フレームワークから呼ばれる部分
684
+ def receive_decrypt(str) # フレームワークから呼ばれる部分
645
685
  dango_server_receive_decrypt(str)
646
686
  end
647
687
 
648
688
  # GCスレッドの開始(メモリ使用量統計も含む)
649
689
  def gc_thread_start
650
690
  th = Thread.start do
691
+ Thread.current[:_name] = "thread_gc"
651
692
  loop do
652
693
  begin
653
694
  sleep @gc_interval_sec
654
695
 
655
- @mutex_proc_thread.synchronize do
656
- logger.debug "GC start "
696
+ logger.debug "mpth:1:GC start mutex start"
697
+ @mutex_proc_thread.timeout_sync(4, :gc) do
698
+ logger.debug "mpth:2:GC start #{Time.now_to_s}"
657
699
  gc_start_time = Time.now
658
700
  GC.enable
659
701
  GC.start
660
702
  GC.disable
661
703
  logger.debug "GC end #{Time.now - gc_start_time}sec "
662
704
  end
705
+ logger.debug "GC start mutex end"
663
706
 
664
707
  output_memory_statistics() if @statistics_process_memory # メモリ使用量統計
665
708
 
709
+ rescue DangoFrameworkMutexTimeoutException
710
+ logger.warn "DangoFrameworkMutexTimeoutException gc_thread_start" +
711
+ "#{error_message($!, 'u')}"
666
712
  rescue Exception
667
713
  logger.error "Exception gc_thread_start #{error_message($!, 'u')}"
668
714
  end
669
- end
715
+ end # loop end
670
716
  end
671
717
  th.priority = 3
672
718
  end
@@ -699,16 +745,16 @@ EOF
699
745
  shared[:_heart_beat_time_hash] = {}
700
746
 
701
747
  th = Thread.start do
702
- count = 0
748
+ Thread.current[:_name] = "thread_heart_beat"
703
749
  loop do
704
750
  begin
705
751
  sleep @herat_beat_interval_sec
706
752
 
707
753
  next if @gserver.stopped? # gserverが起動していればスキップ
708
754
 
709
- logger.debug "heart_beat_thread_start "
710
-
711
- @mutex_proc_thread.synchronize do
755
+ logger.debug "mpth:1:heart_beat_thread_start "
756
+ @mutex_proc_thread.timeout_sync(4, :heart_beat_thread) do
757
+ logger.debug "mpth:2:heart_beat_thread_start "
712
758
  # クライアントから来るハートビートのチェック
713
759
  heart_beat_time_hash = shared[:_heart_beat_time_hash]
714
760
 
@@ -717,62 +763,53 @@ EOF
717
763
  sock = socket_list[sid]
718
764
 
719
765
  if ! sock # すでにsocketが無い場合は、スキップ
720
- logger.warn "!!!! heart_beat_thread_start:sock is not found. #{sid}:#{sock}"
766
+ logger.warn "!!!! heart_beat_thread_start:sock is not found. #{sid}:#{sock.object_id}"
767
+ shared.transaction(:_heart_beat_time_hash) do |hbt_hash|
768
+ hbt_hash.delete(sid)
769
+ shared.commit(hbt_hash)
770
+ end
721
771
  next
722
772
  end
723
773
 
724
774
  # クライアントから来たハートビートの時間チェックし、古ければsocketを閉じる
725
775
  if heart_beat_time_hash[sid] &&
726
776
  heart_beat_time_hash[sid] < Time.now - @heart_beat_receive_wait_sec
777
+
727
778
  logger.warn "!!!! heart_beat_thread_start:heart beat old:#{sid}:" +
728
- "#{heart_beat_time_hash[sid]}:#{sock}:#{sock.closed?}"
779
+ "#{heart_beat_time_hash[sid]}:#{sock.object_id}:#{sock.closed?}"
780
+
781
+ shared.transaction(:_heart_beat_time_hash) do |hbt_hash|
782
+ hbt_hash.delete(sid)
783
+ shared.commit(hbt_hash)
784
+ end
785
+
729
786
  begin
730
- @mutex_sock[sock.object_id].synchronize do
787
+ @mutex_sock[sock.object_id].timeout_sync(2, "hb_close #{sock.object_id}") do
731
788
  sock.close
732
- end # @mutex_sock[sock.object_id].synchronize
789
+ end
733
790
  rescue IOError
734
- logger.debug "heart_beat_thread_start:maybe already closed. IOError:#{sid}:#{sock}"
735
- rescue
791
+ logger.debug "heart_beat_thread_start:maybe already closed. IOError:#{sid}:#{sock.object_id}"
792
+ rescue Exception
736
793
  logger.warn "heart_beat_thread_start:failed close socket:#{error_message($!, 'u')}"
737
794
  end
738
795
  next
739
796
  end
740
797
  end # socket_list
798
+
741
799
  end # @mutex_proc_thread
800
+ logger.debug "heart_beat_thread_start end"
742
801
 
743
- # # スレッド情報をログに出力
744
- # if logger.debug?
745
- # count += 1
746
- # if count % 100 == 0
747
- # sids = socket_list.all_sid
748
- # thr_list = @thr_gr_gserver_serve.list.collect{|th| th.object_id }
749
- #
750
- # logger.debug "heart_beat_thread_start:sids=#{sids.inspect}"
751
- # logger.debug "heart_beat_thread_start:thr_list=#{thr_list.inspect}"
752
- # logger.debug "heart_beat_thread_start:sids-thr_list=#{(sids-thr_list).inspect}"
753
- # logger.debug "heart_beat_thread_start:thr_list-sids=#{(thr_list-sids).inspect}"
754
- # end
755
- # end
756
-
802
+ rescue DangoFrameworkMutexTimeoutException
803
+ logger.warn "DangoFrameworkMutexTimeoutException heart_beat_thread_start" +
804
+ "#{error_message($!, 'u')}"
757
805
  rescue Exception
758
806
  logger.error "Exception heart_beat_thread_start #{error_message($!, 'u')}"
759
807
  end
760
- end
808
+ end # loop end
761
809
  end
762
810
  th.priority = 1
763
811
  end
764
812
 
765
- # クライアントから来たheart_beatなら
766
- def dango_receive__notice_heart_beat(ret_obj)
767
- logger.debug "dango_receive__notice_heart_beat:#{session[:sid]}:#{ret_obj['_hb_id']} "
768
-
769
- shared.transaction(:_heart_beat_time_hash) do |heart_beat_time_hash|
770
- heart_beat_time_hash[session[:sid]] = Time.now
771
- heart_beat_time_hash
772
- shared.commit(heart_beat_time_hash)
773
- end
774
- end
775
-
776
813
  # サーバーからクライアントへのデータ返信
777
814
  def send_return(send_obj, options = {})
778
815
  logger.info "send_return(#{session[:sid].inspect}) "
@@ -805,8 +842,15 @@ EOF
805
842
  send_id = notice_name.to_s + Time.now.to_f.to_s + rand().to_s
806
843
  send_obj_dup["_id"] = send_id
807
844
 
808
- @mutex_send_notice.synchronize do # queue_send_noticeに排他処理
809
- @queue_send_notice.push([sid, send_obj_dup, encode_type].deep_dup)
845
+ # queue_send_noticeに排他処理
846
+ begin
847
+ @mutex_send_notice.timeout_sync(10, :queue_push) do
848
+ @queue_send_notice.push([sid, send_obj_dup, encode_type].deep_dup)
849
+ end
850
+ rescue DangoFrameworkMutexTimeoutException
851
+ logger.warn "mutex_send_notice #{error_message($!, 'u')}"
852
+ rescue Exception
853
+ logger.error "mutex_send_notice #{error_message($!, 'u')}"
810
854
  end
811
855
  end # end sids.each
812
856
 
@@ -815,6 +859,7 @@ EOF
815
859
 
816
860
  # thread for send_notice_queue
817
861
  def thread_send_notice_queue()
862
+ Thread.current[:_name] = "thread_send_notice_queue"
818
863
  loop do
819
864
  begin
820
865
  before_time = Time.now
@@ -824,7 +869,8 @@ EOF
824
869
  pop_data = @queue_send_notice.pop
825
870
  send_data_list.push(pop_data) # Queueデータ待ち
826
871
 
827
- @mutex_send_notice.synchronize do # queue_send_noticeに排他処理(sizeとpopの実行の間にpushが起きないように)
872
+ # queue_send_noticeに排他処理(sizeとpopの実行の間にpushが起きないように)
873
+ @mutex_send_notice.timeout_sync(10, :queue_pop) do
828
874
  @queue_send_notice.size.times do
829
875
  # while(! @queue_send_notice.empty?) do # 残りのデータもQueueに入れていく
830
876
  pop_data = @queue_send_notice.pop
@@ -848,25 +894,32 @@ EOF
848
894
  sock = socket_list[sid]
849
895
 
850
896
  if !sock
851
- logger.info "thread_send_notice_queue:not found sid=#{sid} sock=#{sock.inspect}"
897
+ logger.info "thread_send_notice_queue:not found sid=#{sid} sock=#{sock.object_id}"
852
898
  next
853
899
  end
854
900
 
855
901
  if sock.closed?
856
- logger.info "thread_send_notice_queue:socket closed. sid=#{sid} sock=#{sock.inspect}"
902
+ logger.info "thread_send_notice_queue:socket closed. sid=#{sid} sock=#{sock.object_id}"
857
903
  next
858
904
  end
859
905
 
860
906
  begin
861
- logger.debug "thread_send_notice_queue:dango_send_data:sid=#{sid} sock=#{sock.inspect} " +
907
+ logger.debug "thread_send_notice_queue:dango_send_data:sid=#{sid} sock=#{sock.object_id} " +
862
908
  "#{one_send_data_list.collect{|d| d['_notice_name'] + ','}}"
863
909
 
864
- @mutex_sock[sock.object_id].synchronize do
910
+ @mutex_sock[sock.object_id].timeout_sync(2, "send #{sock.object_id}") do
865
911
  dango_send_data(sock, one_send_data_list, :type=>send_data_encode_type_list[sid]) # データ送信
866
- end # mutex_sock[sock.object_id].synchronize
912
+ end
867
913
 
868
914
  rescue DangoFrameworkConnectionException
869
- logger.info "thread_send_notice_queue:failed send. sid=#{sid} sock=#{sock.inspect} #{$!.class}"
915
+ logger.info "thread_send_notice_queue:failed send. sid=#{sid} " +
916
+ "sock=#{sock.object_id} #{$!.class}"
917
+ rescue DangoFrameworkMutexTimeoutException
918
+ logger.warn "thread_send_notice_queue:failed send. sid=#{sid} " +
919
+ "sock=#{sock.object_id} #{$!.class}"
920
+ rescue Exception
921
+ logger.error "thread_send_notice_queue:unknown failed. sid=#{sid} " +
922
+ "sock=#{sock.object_id} #{error_message($!, 'u')}"
870
923
  end
871
924
  end
872
925
 
@@ -877,10 +930,13 @@ EOF
877
930
 
878
931
  sleep @send_receive_sleep_interval_sec # スリープ
879
932
 
933
+ rescue DangoFrameworkMutexTimeoutException
934
+ logger.warn "ERROR:thread_send_notice_queue:DangoFrameworkMutexTimeoutException" +
935
+ "#{error_message($!, 'u')}"
880
936
  rescue Exception
881
- logger.warn "ERROR:thread_send_notice_queue:Exception:#{error_message($!, 'u')}"
937
+ logger.error "ERROR:thread_send_notice_queue:Exception:#{error_message($!, 'u')}"
882
938
  end
883
- end
939
+ end # loop end
884
940
  end
885
941
 
886
942
  # 必要に応じて追加するメソッド
@@ -903,9 +959,10 @@ EOF
903
959
 
904
960
  # メインループ用の定義をするためのメソッド
905
961
  def set_loop_setting(options={})
906
- logger.debug "loop_setting options:#{options.inspect}"
907
962
  options = options.deep_dup
908
963
 
964
+ shared[:_is_server_sleep] = nil # メンテナンス停止用
965
+
909
966
  if options["method_name"] # メソッド名が無ければ処理しない
910
967
  method_name = options["method_name"]
911
968
 
@@ -914,23 +971,36 @@ EOF
914
971
  logger.warn "set_loop_setting wait_sec:#{wait_sec.inspect} method_name=#{method_name}"
915
972
 
916
973
  th = Thread.new do
917
- begin
918
- loop do
974
+ logger.debug "set_loop_setting start"
975
+ count = 0
976
+
977
+ loop do
978
+ begin
919
979
  before_time = Time.now
920
- @mutex_proc_thread.synchronize do
921
- begin
922
- __send__(method_name)
923
- rescue Exception
924
- logger.error "set_loop_setting error:#{error_message($!, 'u')}"
925
- end
926
- end
927
980
 
928
- real_wait_sec = wait_sec - (Time.now - before_time)
981
+ logger.debug "mpth:1:sls start"
982
+ @mutex_proc_thread.timeout_sync(4, "set_loop_setting_send_#{method_name}") do
983
+ __send__(method_name)
984
+ end # mutex_proc_thread
985
+ logger.debug "mpth:2:sls end"
986
+ # if count % 1000 == 0
929
987
 
988
+ real_wait_sec = wait_sec - (Time.now - before_time)
930
989
  sleep real_wait_sec if real_wait_sec > 0
990
+
991
+ count += 1
992
+ count = 0 if count >= 10000000
993
+
994
+ # メンテナンス機能
995
+ if shared[:_is_server_sleep]
996
+ logger.info "set_loop_setting SLEEP !!!"
997
+ sleep 10000
998
+ end
999
+ rescue DangoFrameworkMutexTimeoutException
1000
+ logger.warn "set_loop_setting error:#{error_message($!, 'u')}"
1001
+ rescue Exception
1002
+ logger.error "set_loop_setting error:#{error_message($!, 'u')}"
931
1003
  end
932
- rescue Exception
933
- logger.error "set_loop_setting error:#{error_message($!, 'u')}"
934
1004
  end
935
1005
  end # th.end
936
1006
  end