dango 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
1
+ #!ruby -Ku
2
+
3
+ =begin
4
+ = Dangoサーバーのメンテナンス用モニタ
5
+ =end
6
+
7
+ #$LOAD_PATH.push("../../../../svn/rubyforge/dango/lib")
8
+
9
+ #gem "dango"
10
+
11
+ require 'dango/client_framework' # コネクションサーバーフレームワークの呼び出し
12
+
13
+ #
14
+
15
+ # メインクラス
16
+ class DangoMonitorClient < DangoClientFramework
17
+ ConnTimeout = 6
18
+
19
+ def initialize()
20
+ super(ENV['RAILS_ENV'])
21
+ end
22
+
23
+ public
24
+
25
+ # 起動処理
26
+ def cs_client_init
27
+ # ログ出力情報
28
+ @connection_client_log_file = "log/dango_monitor_#{ENV['RAILS_ENV']}.log"
29
+ @connection_client_log_level = Logger::DEBUG
30
+ end
31
+
32
+ # アクセサの定義
33
+ # 読み込みのみ
34
+ attr_reader(:is_session_closed)
35
+
36
+ # サーバーの全情報取得
37
+ def get_all_info
38
+ cs_logger.debug "DangoMonitorClient:get_all_info"
39
+ begin
40
+ ret_obj = cs_client_send_receive_data('monitor_all_info', {})
41
+ rescue DangoFrameworkConnectionError
42
+ raise("monitor_all_info Connection error")
43
+ rescue DangoFrameworkTimeoutError
44
+ raise("monitor_all_info Timeout error")
45
+ end
46
+ raise("code is not 0 (faild). :code=#{ret_obj['code']}") if ret_obj['code'] != 0
47
+ ret_obj['all_info']
48
+ end
49
+
50
+ # サーバーのデータリロード
51
+ def server_reload
52
+ cs_logger.debug "DangoMonitorClient:server_reload"
53
+ begin
54
+ ret_obj = cs_client_send_receive_data('monitor_server_reload', {})
55
+ rescue DangoFrameworkConnectionError
56
+ raise("monitor_server_reload Connection error")
57
+ rescue DangoFrameworkTimeoutError
58
+ raise("monitor_server_reload Timeout error")
59
+ end
60
+ raise("code is not 0 (faild). :code=#{ret_obj['code']}") if ret_obj['code'] != 0
61
+ ret_obj['all_info']
62
+ end
63
+ end
64
+
65
+
66
+
@@ -0,0 +1,42 @@
1
+ #!ruby -Ku
2
+
3
+ #module Dango
4
+ require 'yaml'
5
+ require 'pp'
6
+
7
+ require 'dango/server_framework'
8
+
9
+ # require RAILS_ROOT + '/config/boot'
10
+ require RAILS_ROOT + '/config/environment'
11
+
12
+ # 環境によるコンフィグ読み込み
13
+ env = ENV['RAILS_ENV'] || 'development'
14
+
15
+ config = YAML.load(open("dango/config/#{env}.yml", "rb"){|fh| fh.read})
16
+
17
+ # serverファイル名一覧を取得
18
+ load_files = []
19
+ glob_str = 'dango/server/*.rb'
20
+ Dir.glob(glob_str) do |srv_file|
21
+ load_files.push({:file=>srv_file, :mtime=>File.mtime(srv_file)})
22
+ end
23
+
24
+ # ファイル名順にソート
25
+ load_files = load_files.sort_by{|f| f[:file] }
26
+ #p load_files
27
+
28
+ # config['load_files'] = load_files
29
+
30
+ # config:cache_classesによる処理分け
31
+ # if config['server']['cache_classes'] == true
32
+ # load_files.each do |f|
33
+ # require f[:file]
34
+ # end
35
+ # else
36
+ load_files.each do |f|
37
+ load f[:file]
38
+ end
39
+ # end
40
+
41
+ DangoServer.start(config)
42
+ #end
@@ -0,0 +1,661 @@
1
+ #!ruby -Ku
2
+
3
+ =begin
4
+ = コネクション型サーバーフレームワーク
5
+ =end
6
+
7
+ require 'gserver'
8
+ require 'ipaddr'
9
+
10
+ require "dango/framework_base"
11
+
12
+ # フレームワーククラス
13
+ class DangoServerFramework
14
+ include DangoFrameworkModule
15
+
16
+ SendReceiveSleepIntervalSec = 0.1 # データ送信後の順の際のタイムアウトチェック間隔秒
17
+
18
+ # cs_client_send_receive_data用の共有メモリ
19
+ def send_receive_shared_init
20
+ @send_receive_shared = SharedMemoryStore.new
21
+ end
22
+ def send_receive_shared
23
+ @send_receive_shared
24
+ end
25
+
26
+ class DangoGServer < GServer
27
+ def initialize(parent, *args)
28
+ @parent = parent
29
+ super(*args)
30
+ end
31
+
32
+ def serve(sock)
33
+ @parent.thread_main(sock)
34
+ end
35
+
36
+ def connecting(sock)
37
+ @parent.connecting(sock)
38
+ end
39
+
40
+ def disconnecting(sock)
41
+ @parent.disconnecting(sock)
42
+ end
43
+ end
44
+
45
+ def initialize(config)
46
+ @config = config
47
+
48
+ @gserver = nil # Gserver用の変数
49
+ @server_reload = nil # サーバーのリロード用フラグ
50
+
51
+ # SIGINT の捕捉
52
+ Signal.trap(:INT) do
53
+ puts "shutdown"
54
+ exit!
55
+ end
56
+
57
+ # サーバー開始
58
+ server_start()
59
+
60
+ loop do # 待ちで無限ループに入る
61
+ sleep 3
62
+ # p( Time.now.to_s + ":#{@server_reload.inspect}")
63
+ check_reload_class()
64
+ end
65
+ end
66
+
67
+ attr_reader(:log_file, :shared) # 読み書き
68
+
69
+ # 起動用のインスタンスメソッド
70
+ def self.start(config = {})
71
+ self.new(config)
72
+ end
73
+
74
+
75
+ # サーバー開始処理
76
+ def server_start()
77
+ set_server_variables() # 各種サーバー仕様の変数設定
78
+ shared_init() # 共有メモリを初期化
79
+ notice_shared_init() # 通知共有メモリを初期化
80
+ socket_list_init() # ソケット一覧を初期化
81
+ mutex_socket_list_init(cs_logger()) # ソケット毎用のmutexを初期化
82
+ send_receive_shared_init() # データ送受信用の共有メモリ初期化
83
+ cs_server_init() # 初期設定読み込み
84
+
85
+ cs_logger.debug("===== server initialize =====") # loggerの準備
86
+ cs_logger.debug("port=#{@connection_server_port}")
87
+ cs_logger.debug("host=#{@connection_server_host}")
88
+ cs_logger.debug("max_connections=#{@connection_server_max_connections}")
89
+
90
+ @gserver = DangoGServer.new(self, @connection_server_port,
91
+ @connection_server_host,
92
+ @connection_server_max_connections)
93
+ @gserver.audit = true # Turn logging on.
94
+ @gserver.start
95
+ end
96
+
97
+ # サーバーのループ時のクラス読み直し処理
98
+ def check_reload_class()
99
+ begin
100
+ # @config:cache_classesによる処理分け
101
+ # if @config['server']['cache_classes'] != true
102
+
103
+ # ロードファイルの変更確認
104
+ # changed = false
105
+ # @config['load_files'].each do |f|
106
+ # this_mtime = File.mtime(f[:file])
107
+ # if this_mtime > f[:mtime]
108
+ # f[:mtime] = this_mtime
109
+ # changed = true
110
+ # end
111
+ # end
112
+
113
+ # 変更していたら
114
+ # changed = nil
115
+ # if changed
116
+ if @server_reload
117
+ @server_reload = nil
118
+
119
+ puts "-- stopping server"
120
+
121
+ # 強制的に接続しているsocketをクローズ
122
+ cs_logger.debug "socket_list.keys:#{socket_list.keys.inspect}"
123
+ socket_list.keys.each do |sk|
124
+ cs_logger.debug "sk:#{socket_list[sk].inspect}"
125
+ socket_list[sk].close if ! socket_list[sk].closed?
126
+ socket_list[sk]
127
+ end
128
+
129
+ # サーバーを停止
130
+ @gserver.shutdown
131
+ @gserver.stop
132
+ while(!@gserver.stopped?) do
133
+ sleep 1
134
+ puts "waiting... #{@gserver.stopped?}"
135
+ cs_logger.debug "waiting... #{@gserver.stopped?} #{@gserver.connections}"
136
+ end
137
+
138
+ @gserver = nil
139
+
140
+ puts "-- stopped server"
141
+
142
+ # GCを行う
143
+ GC.start
144
+
145
+ # サーバーファイルを読み直し
146
+ puts "-- reload classes"
147
+ tmp_verbose = $VERBOSE
148
+ $VERBOSE = nil
149
+
150
+ # serverファイル名一覧を取得
151
+ load_files = []
152
+ glob_str = 'dango/server/*.rb'
153
+ Dir.glob(glob_str) do |srv_file|
154
+ load_files.push({:file=>srv_file, :mtime=>File.mtime(srv_file)})
155
+ end
156
+
157
+ # ファイル名順にソート
158
+ load_files = load_files.sort_by{|f| f[:file] }
159
+ load_files.each do |f|
160
+ begin
161
+ load f[:file]
162
+ rescue Exception
163
+ p $!.class
164
+ p $!.message
165
+ p $!.backtrace
166
+ end
167
+ end
168
+
169
+ $VERBOSE = tmp_verbose
170
+
171
+ # サーバーを再度起動
172
+ puts "-- start server"
173
+ server_start() # サーバー開始
174
+ end
175
+ # end
176
+ rescue Exception
177
+ cs_logger.error "#{$!.class}:#{$!.message}\n#{$!.backtrace.pretty_inspect}"
178
+ end
179
+ end
180
+
181
+ # gserver接続開始処理
182
+ def connecting(sock)
183
+ cs_logger.debug "connecting:sock=#{sock}"
184
+ end
185
+
186
+ # gserver接続開始処理
187
+ def disconnecting(port)
188
+ cs_logger.debug "disconnecting:port=#{port}"
189
+ end
190
+
191
+ # gserverのserveメソッド:スレッド開始処理
192
+ def thread_main(sock)
193
+ cs_logger.debug "thread_main:start"
194
+ cs_logger.debug "#{sock} is accepted. key=#{Thread.current.object_id}"
195
+
196
+ begin
197
+ session[:session_id] = Thread.current.object_id
198
+ socket_list.add(session[:session_id], sock)
199
+ mutex_socket_list.add(session[:session_id])
200
+
201
+ sock.binmode
202
+ sock.sync = true
203
+
204
+ cs_connect() # 接続時メソッド呼び出し
205
+
206
+ # メインループ入り
207
+ loop do
208
+ if sock.closed?
209
+ cs_logger.debug "#{sock.inspect}:sock is closed..."
210
+ break
211
+ end
212
+
213
+ cs_logger.debug "start cs_receive_data"
214
+ ret_obj = nil
215
+ # mutex_socket_list.synchronize(session[:session_id]) do
216
+ ret_obj = cs_receive_data(sock) # データ受信処理
217
+ # end
218
+ cs_logger.debug "finished cs_receive_data"
219
+
220
+ if ret_obj != {} # 受信データがあれば
221
+ if !(ret_obj && ret_obj["action"]) # actionが無い場合はエラー
222
+ cs_logger.error "no action error:#{ret_obj.inspect}"
223
+ raise(DangoFrameworkError, "no action error")
224
+ end
225
+
226
+ # アクション名
227
+ action_name = ret_obj["action"].to_s
228
+ cs_logger.debug "action_name=#{action_name}"
229
+
230
+ if action_name == 'monitor_all_info' # メンテナンスアクション名なら
231
+ cs_check_monitor_error(sock, "return_monitor_all_info")
232
+ cs_server_monitor_all_info()
233
+ elsif action_name == 'monitor_server_reload' # メンテナンスアクション名なら
234
+ cs_check_monitor_error(sock, "return_monitor_server_reload")
235
+ cs_server_monitor_server_reload()
236
+ else # メンテナンスコマンド以外のユーザーアクション名なら
237
+ begin
238
+ __send__("cs_receive_#{action_name}", ret_obj)
239
+ rescue NoMethodError
240
+ @recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
241
+ cs_logger.error "not find action #{action_name}:#{error_message($!, 'u')}"
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ rescue DangoFrameworkConnectionError
248
+ @recv_fail_count += 1 if @recv_fail_count # 受信失敗回数カウント
249
+ cs_logger.debug "connection error. \n#{error_message($!, 'u')}"
250
+
251
+ rescue Exception
252
+ cs_logger.error "#{error_message($!, 'u')}"
253
+
254
+ ensure
255
+ cs_logger.debug "#{sock.inspect} is gone"
256
+
257
+ begin
258
+ cs_close() # 接続解除時に呼び出されるメソッド
259
+ rescue
260
+ cs_logger.error "#{error_message($!, 'u')}"
261
+ ensure
262
+ socket_list.delete(Thread.current.object_id) # ソケットリストから削除
263
+ sock.close # ソケットを閉じる
264
+
265
+ cs_logger.debug "#{sock.inspect} is gone 2"
266
+ end
267
+
268
+ end
269
+ end
270
+
271
+ # 各種サーバー仕様の変数設定
272
+ def set_server_variables()
273
+ # 変数の初期設定
274
+ @connection_server_port = @config['network']['port'] || 15000
275
+ @connection_server_host = @config['server']['host'] || "localhost"
276
+ @connection_server_max_connections = @config['server']['max_connections'] || 10
277
+ @log_file = @config['server']['log_file'] || ""
278
+
279
+ log_level_hash = {
280
+ "FATAL" => Logger::FATAL,
281
+ "ERROR" => Logger::ERROR,
282
+ "WARN" => Logger::WARN,
283
+ "INFO" => Logger::INFO,
284
+ "DEBUG" => Logger::DEBUG,
285
+ }
286
+ @log_level = log_level_hash.find do |level|
287
+ level == @config['server']['log_level']
288
+ end
289
+ @log_level = @connection_server_log_level || Logger::DEBUG
290
+
291
+ @start_time = Time.now # サーバー起動時間
292
+ @recv_count = 0 # 受信回数
293
+ @send_count = 0 # 送信回数
294
+ @recv_fail_count = 0 # 受信失敗回数
295
+ @send_fail_count = 0 # 送信失敗回数
296
+ end
297
+
298
+ def cs_server_init # 初期設定
299
+ end
300
+
301
+ # コンフィグのshared_database_managerによる使用クラスの選択
302
+ def select_shared_database_manager()
303
+ if @config['server']['shared_database_manager'] == 'MemoryStore'
304
+ SharedMemoryStore.new
305
+ else
306
+ SharedMemoryStore.new
307
+ end
308
+ end
309
+
310
+ # 共有メモリ
311
+ def shared_init
312
+ @shared = select_shared_database_manager()
313
+ end
314
+ def shared
315
+ @shared
316
+ end
317
+
318
+ # 通知共有メモリ
319
+
320
+ def notice_shared_init
321
+ # @notice_shared = NoticeShared.new(self)
322
+ @notice_shared = select_shared_database_manager()
323
+
324
+ class << @notice_shared ## 各種メソッド追加
325
+ def initialize2(parent)
326
+ @parent = parent
327
+ self[:notice_list] = {}
328
+ end
329
+
330
+ def init_key(key) # そのキーを作成する
331
+ if self[:notice_list].has_key?(key) || key == :notice_list # キーがすでにあるか予約語なら
332
+ raise(DangoFrameworkError, "notice_list already has key. key=#{key.inspect}")
333
+ end
334
+
335
+ self.transaction(:notice_list) do |notice_list|
336
+ notice_list[key] = []
337
+ notice_list
338
+ end
339
+ end
340
+
341
+ def add_connectable(key, session_id) # 接続許可にする
342
+ if !self[:notice_list].has_key?(key) # キーがなければ
343
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
344
+ end
345
+
346
+ self.transaction(:notice_list) do |notice_list|
347
+ notice_list[key] << session_id
348
+ notice_list
349
+ end
350
+ end
351
+
352
+ def remove_connectable(key, session_id) # 接続を不許可にする
353
+ if !self[:notice_list].has_key?(key) # キーがなければ
354
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
355
+ end
356
+
357
+ self.transaction(:notice_list) do |notice_list|
358
+ notice_list[key].delete(session_id)
359
+ notice_list
360
+ end
361
+ end
362
+
363
+ def get_connectables(key) # 接続許可一覧を返す
364
+ if !self[:notice_list].has_key?(key) # キーがなければ
365
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
366
+ end
367
+
368
+ self[:notice_list][key]
369
+ end
370
+
371
+ def notice_change(key, value) # 変更時に通知する変更
372
+ if !self[:notice_list].has_key?(key) # キーがなければ
373
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
374
+ end
375
+
376
+ self[key] = value
377
+
378
+ @parent.cs_logger.debug "self.get_connectables(key):#{self.get_connectables(key).inspect}"
379
+
380
+ self.get_connectables(key).each do |session_id|
381
+ @parent.cs_server_send_data(session_id, "notice_shared_#{key}".to_sym, value)
382
+ end
383
+ end
384
+
385
+ def not_notice_change(key, value) # 変更時に通知しない変更
386
+ if !self[:notice_list].has_key?(key) # キーがなければ
387
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
388
+ end
389
+
390
+ self[key] = value
391
+ end
392
+
393
+ def []=(key, value) # データの変更
394
+ if key != :notice_list && !self[:notice_list].has_key?(key) # キーがなければ
395
+ raise(DangoFrameworkError, "notice_list not has key. key=#{key.inspect}")
396
+ end
397
+
398
+ super(key, value) # データの変更
399
+ end
400
+ end
401
+ end
402
+
403
+ def notice_shared
404
+ @notice_shared
405
+ end
406
+
407
+ # セッション
408
+ class Session < Hash
409
+ end
410
+ def session
411
+ Thread.current[:session] = Session.new if !Thread.current[:session]
412
+ Thread.current[:session]
413
+ end
414
+
415
+ # ソケットとIDの対応
416
+ class SocketList
417
+ def initialize
418
+ @sl_hash = Hash.new
419
+ @sl_mutex = Mutex.new
420
+ end
421
+ def keys()
422
+ @sl_mutex.synchronize do
423
+ @sl_hash.keys
424
+ end
425
+ end
426
+ def delete(key)
427
+ @sl_mutex.synchronize do
428
+ @sl_hash.delete(key)
429
+ end
430
+ end
431
+ def add(key, sock)
432
+ @sl_mutex.synchronize do
433
+ raise("already exist key(#{key})") if @sl_hash.has_key?(key)
434
+ raise("sock(#{sock.ins}) is not Socket") if sock.kind_of?(Socket)
435
+ @sl_hash[key] = sock
436
+ end
437
+ end
438
+ def [](key)
439
+ @sl_mutex.synchronize do
440
+ raise("not exist key(#{key})") if ! @sl_hash.has_key?(key)
441
+ @sl_hash[key]
442
+ end
443
+ end
444
+ def []=(key, sock)
445
+ @sl_mutex.synchronize do
446
+ raise("not exist key(#{key})") if ! @sl_hash.has_key?(key)
447
+ raise("sock(#{sock.class}) is not Socket") if sock.kind_of?(Socket)
448
+ @sl_hash[key] = sock
449
+ end
450
+ end
451
+ end
452
+ def socket_list_init
453
+ @socket_list = SocketList.new
454
+ end
455
+ def socket_list
456
+ @socket_list
457
+ end
458
+
459
+ # ソケット毎用のmutex
460
+ class MutexSocketList
461
+ def initialize(cs_logger)
462
+ @cs_logger = cs_logger
463
+ @msl_hash = Hash.new
464
+ end
465
+ def keys()
466
+ @msl_hash.keys
467
+ end
468
+ def delete(key)
469
+ @msl_hash.delete(key)
470
+ end
471
+ def add(key)
472
+ @msl_hash[key] = Mutex.new
473
+ end
474
+ # def [](key)
475
+ # raise("not exist key(#{key})") if ! @msl_hash.has_key?(key)
476
+ ## add(key) if @msl_hash.has_key?(key)
477
+ # @msl_hash[key]
478
+ # end
479
+ def synchronize(key)
480
+ raise("not exist key(#{key})") if ! @msl_hash.has_key?(key)
481
+ @cs_logger.debug("mutex_socket_list starting synchronize. key=#{key}")
482
+ ret = nil
483
+ @msl_hash[key].synchronize do
484
+ @cs_logger.debug("mutex_socket_list started synchronize. key=#{key}")
485
+ ret = yield
486
+ @cs_logger.debug("mutex_socket_list finished synchronize. key=#{key}")
487
+ end
488
+ ret
489
+ end
490
+ end
491
+ def mutex_socket_list_init(cs_logger)
492
+ @mutex_sock_list = MutexSocketList.new(cs_logger) # ソケット毎用のmutex
493
+ end
494
+ def mutex_socket_list
495
+ @mutex_sock_list
496
+ end
497
+
498
+ # 接続時に呼び出されるメソッド
499
+ def cs_connect; end
500
+
501
+ # 接続解除時に呼び出されるメソッド
502
+ def cs_close; end
503
+
504
+
505
+ # サーバーの暗号化処理
506
+ def cs_server_send_encrypt(str) # 継承用
507
+ str
508
+ end
509
+ def cs_send_encrypt(str) # フレームワークから呼ばれる部分
510
+ cs_server_send_encrypt(str)
511
+ end
512
+
513
+ # サーバーの復号化処理
514
+ def cs_server_receive_decrypt(str) # 継承用
515
+ str
516
+ end
517
+ def cs_receive_decrypt(str) # フレームワークから呼ばれる部分
518
+ cs_server_receive_decrypt(str)
519
+ end
520
+
521
+ # サーバーからクライアントへのデータ送信
522
+ def cs_server_send_data(session_id, notice_name, send_obj, options = {})
523
+ cs_logger.debug "cs_server_send_data(#{session_id.inspect}, #{notice_name.inspect}, #{send_obj.inspect}, #{options.inspect})"
524
+
525
+ timeout = options[:timeout] || 6
526
+ dtype = options[:type] || 0
527
+
528
+ sock = socket_list[session_id]
529
+ raise(DangoFrameworkError, "not found session_id=#{session_id}") if !sock
530
+ raise(DangoFrameworkConnectionError, "socket closed. s_id=#{session_id}") if sock.closed?
531
+
532
+ cs_logger.debug "cs_server_send_data:sending data notice_name=#{notice_name.inspect}"
533
+ send_obj_dup = send_obj.deep_dup
534
+ send_obj_dup["notice"] = notice_name.to_s
535
+
536
+ # データ送信時にクライアントからのレスポンスを確認する(Flashのバグらしきもの対策)
537
+ if notice_name.to_s =~ /^return_/
538
+ cs_send_data(sock, send_obj_dup, :type=>dtype) # データ送信
539
+ cs_logger.debug "cs_server_send_data:finish send data notice_name=#{notice_name.inspect}\n"
540
+ else
541
+ Thread.start do
542
+ mutex_socket_list.synchronize(session_id) do
543
+ send_receive_shared[notice_name] = nil
544
+
545
+ receive_thread = nil
546
+ end_reserved_time = Time.now + timeout
547
+
548
+ # 戻ってきたデータのチェック
549
+ notice_name_sym = (notice_name.class == Symbol) ? (":"+notice_name.to_s) : ('"'+notice_name+'"')
550
+ instance_method_name = "cs_receive_response_#{notice_name}"
551
+ expr = <<-EOF
552
+ def self.#{instance_method_name}(ret_obj)
553
+ cs_logger.debug "ret_obj:" + ret_obj.inspect
554
+ send_receive_shared[#{notice_name_sym}] = ret_obj
555
+ end
556
+ cs_logger.debug "defined:#{instance_method_name}"
557
+ EOF
558
+ instance_eval expr
559
+
560
+ # タイムアウトチェック
561
+ (timeout.to_f / SendReceiveSleepIntervalSec).to_i.times do
562
+ raise(DangoFrameworkTimeoutError, "timeout:#{notice_name}") if Time.now > end_reserved_time
563
+
564
+ # 送信スレッドが開始していなければ開始
565
+ if !receive_thread
566
+ receive_thread = Thread.start do
567
+ cs_send_data(sock, send_obj_dup, :type=>dtype) # データ送信
568
+ cs_logger.debug "cs_server_send_data:finish send data notice_name=#{notice_name.inspect}\n"
569
+ end
570
+ end
571
+
572
+ # 戻ってきたデータがあれば
573
+ if send_receive_shared[notice_name]
574
+ cs_logger.debug "notice_name:#{send_receive_shared[notice_name].inspect}"
575
+ break
576
+ end
577
+
578
+ cs_logger.debug "sleep:#{SendReceiveSleepIntervalSec}"
579
+ sleep SendReceiveSleepIntervalSec # スリープ
580
+ end
581
+
582
+ if !send_receive_shared[notice_name] # 戻ってきたデータがあるかどうかチェック
583
+ raise(DangoFrameworkError, "received data is none")
584
+ end
585
+
586
+ remove_method(instance_method_name) # 定義したインスタンスメソッドを削除しておく
587
+ end
588
+ end
589
+ end
590
+
591
+ self
592
+ end
593
+
594
+ # メンテナンスコマンド:エラーの場合
595
+ def cs_check_monitor_error(sock, return_command)
596
+ peerhost, peeraddr = sock.peeraddr[2, 2]
597
+ backdoor_host = @config['server']['backdoor_host']
598
+ match = false
599
+ if peerhost == backdoor_host # ホスト名で書いてある時の一致確認
600
+ match = true
601
+ else
602
+ begin # IPアドレスの一致確認
603
+ match = true if IPAddr.new(peeraddr) == IPAddr.new(backdoor_host)
604
+ rescue
605
+ end
606
+ end
607
+
608
+ if !match
609
+ send_obj = {'code'=>1, 'message'=>"error your ip address"}
610
+ cs_server_send_data(session[:session_id], return_command, send_obj, :type=>2)
611
+ raise(DangoFrameworkError)
612
+ end
613
+ end
614
+
615
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
616
+ def cs_server_monitor_all_info()
617
+ all_info = {
618
+ 'shareds' => shared.to_hash,
619
+ 'socket_list' => socket_list.keys,
620
+
621
+ 'server_start_time' => @start_time.strftime("%Y-%m-%d %H:%M:%S"),
622
+ 'up_time' => Time.now - @start_time,
623
+
624
+ 'recv_count' => @recv_count, # 受信回数
625
+ 'send_count' => @send_count, # 送信回数
626
+ 'recv_fail_count' => @recv_fail_count, # 受信失敗回数
627
+ 'send_fail_count' => @send_fail_count, # 送信失敗回数
628
+ # 'dummy' => "dummy "*1000, # ダミー情報
629
+ }
630
+
631
+ send_obj = {'code'=>0, 'all_info'=>all_info}
632
+ cs_server_send_data(session[:session_id], 'return_monitor_all_info', send_obj, :type=>2)
633
+ end
634
+
635
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
636
+ def cs_server_monitor_server_reload()
637
+ cs_logger.debug "cs_server_monitor_server_reload"
638
+ @server_reload = true
639
+ cs_logger.debug "@server_reload=#{@server_reload.inspect}"
640
+ send_obj = {'code'=>0, 'message'=>'success'}
641
+ cs_server_send_data(session[:session_id], 'return_monitor_server_reload', send_obj, :type=>2)
642
+ end
643
+
644
+ # 必要に応じて追加するメソッド
645
+ def method_missing(name, *args)
646
+ if name.to_s =~ /^cs_receive_action_notice_shared_(.+)/ # 共有メモリ変更通知なら
647
+ key = $1
648
+ method_action_notice_shared(key, name, *args)
649
+ else
650
+ # raise(NameError, "method not found. #{name.inspect} #{args.inspect}")
651
+ end
652
+ end
653
+
654
+ def method_action_notice_shared(key, name, *args) # 共有メモリ変更通知のメソッド
655
+ cs_logger.debug "method_name:#{name}"
656
+ send_obj = args[0]
657
+ notice_shared.notice_change(key.to_sym, send_obj)
658
+ end
659
+
660
+ end
661
+