dango 0.4.8 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -73,7 +73,8 @@ class DangoClientFramework
73
73
  @log_shift_age = @connection_client_log_shift_age
74
74
 
75
75
  # loggerの準備
76
- logger.debug("-------client initialize host=#{@connection_client_host} port=#{@connection_client_port}")
76
+ logger.info("-------client initialize")
77
+ logger.info("host=#{@connection_client_host} port=#{@connection_client_port}")
77
78
  logger.info("@log_file = #{@log_file}")
78
79
  logger.info("@log_level = #{@log_level}")
79
80
  logger.info("@log_max_size = #{@log_max_size}")
@@ -81,7 +82,7 @@ class DangoClientFramework
81
82
 
82
83
  # データ送受信用の共有メモリ初期化
83
84
  send_return_shared_init()
84
- @send_receive_mutex = Mutex.new # 送受信用の排他処理
85
+ @send_receive_mutex = DangoMutex.new(:send_receive_mutex) # 送受信用の排他処理
85
86
 
86
87
  # 通知共有メモリの初期化
87
88
  dango_client_notice_shared_init()
@@ -101,7 +102,7 @@ class DangoClientFramework
101
102
  @sock.sync = true
102
103
  logger.debug("addr:#{@sock.addr.inspect}")
103
104
 
104
- @tmutex = Mutex.new # sockの排他処理用
105
+ @tmutex = DangoMutex.new(:tmutex) # sockの排他処理用
105
106
 
106
107
  dango_heart_beat_thread_init() # ハートビート送信スレッドの起動
107
108
 
@@ -150,12 +151,12 @@ class DangoClientFramework
150
151
  __send__("dango_receive_#{notice_name}", ret_obj)
151
152
  rescue
152
153
  logger.error "error in dango_receive_#{notice_name} #{@sid} \n#{error_message($!, 'u')}"
153
- ensure
154
- # データの受信の送信返し
155
- response_notice_name = "_response"
156
- send_obj = {"_id" => ret_obj["_id"]}
157
- send_action(response_notice_name, send_obj)
158
- logger.debug "response_notice_name=#{response_notice_name.inspect} #{@sid} "
154
+ # ensure
155
+ # # データの受信の送信返し
156
+ # response_notice_name = "_response"
157
+ # send_obj = {"_id" => ret_obj["_id"]}
158
+ # send_action(response_notice_name, send_obj)
159
+ # logger.debug "response_notice_name=#{response_notice_name.inspect} #{@sid} "
159
160
  end
160
161
  logger.debug "called method=#{notice_name.inspect} #{@sid} "
161
162
  end
@@ -243,7 +244,7 @@ class DangoClientFramework
243
244
  def dango_client_send_encrypt(str) # 継承用
244
245
  str
245
246
  end
246
- def dango_send_encrypt(str) # フレームワークから呼ばれる部分
247
+ def send_encrypt(str) # フレームワークから呼ばれる部分
247
248
  dango_client_send_encrypt(str)
248
249
  end
249
250
 
@@ -251,7 +252,7 @@ class DangoClientFramework
251
252
  def dango_client_receive_decrypt(str) # 継承用
252
253
  str
253
254
  end
254
- def dango_receive_decrypt(str) # フレームワークから呼ばれる部分
255
+ def receive_decrypt(str) # フレームワークから呼ばれる部分
255
256
  dango_client_receive_decrypt(str)
256
257
  end
257
258
 
@@ -275,7 +276,7 @@ class DangoClientFramework
275
276
  return_name = options[:return_name] || ("return_" + action_name.to_s).to_sym
276
277
  timeout = options[:timeout] || 6
277
278
 
278
- @send_receive_mutex.synchronize do
279
+ @send_receive_mutex.timeout_sync(10, :send_return) do
279
280
  send_return_shared[action_name] = nil
280
281
 
281
282
  receive_thread = nil
@@ -4,6 +4,7 @@
4
4
  = Dangoサーバーのメンテナンス用モニタ
5
5
  =end
6
6
 
7
+ require "timeout"
7
8
 
8
9
  # モニター用のdangoクライアントクラス
9
10
  module DangoControllerPlugin
@@ -18,10 +19,13 @@ module DangoControllerPlugin
18
19
  def self.dango_server_call(method_name, arg, options = {})
19
20
  config = dango_server_config(options)
20
21
  raise("backdoor_run_drb_server is false.") if !config['server']['backdoor_run_drb_server']
21
- drb_uri = "druby://#{config['network']['host']}:#{config['server']['backdoor_run_drb_port']}"
22
+ # drb_uri = "druby://#{config['network']['host']}:#{config['server']['backdoor_run_drb_port']}"
23
+ drb_uri = config['server']['backdoor_run_drb_url']
22
24
  begin
23
- drb_obj = DRbObject.new_with_uri(drb_uri)
24
- drb_obj.__send__(method_name.to_s, arg)
25
+ timeout(3) do
26
+ drb_obj = DRbObject.new_with_uri(drb_uri)
27
+ drb_obj.__send__(method_name.to_s, arg)
28
+ end
25
29
  rescue Exception
26
30
  raise("DRbError:#{$!.class} #{$!.message} #{$!.backtrace.inspect}")
27
31
  end
@@ -98,10 +98,10 @@ class GServer
98
98
  end
99
99
 
100
100
  @@services = {} # Hash of opened ports, i.e. services
101
- @@servicesMutex = Mutex.new
101
+ @@servicesMutex = DangoMutex.new(:gServer_servicesMutex)
102
102
 
103
103
  def GServer.stop(port, host = DEFAULT_HOST)
104
- @@servicesMutex.synchronize {
104
+ @@servicesMutex.timeout_sync(10, :GServer_stop) {
105
105
  @@services[host][port].stop
106
106
  }
107
107
  end
@@ -112,9 +112,9 @@ class GServer
112
112
  end
113
113
 
114
114
  def stop
115
- @connectionsMutex.synchronize {
115
+ @connectionsMutex.timeout_sync(10, :stop) {
116
116
  if @tcpServerThread
117
- @tcpServerThread.raise "stop"
117
+ @tcpServerThread.raise "stop. "
118
118
  end
119
119
  }
120
120
  end
@@ -182,7 +182,7 @@ class GServer
182
182
  @host = host
183
183
  @maxConnections = maxConnections
184
184
  @connections = []
185
- @connectionsMutex = Mutex.new
185
+ @connectionsMutex = DangoMutex.new(:gServer_connectionsMutex)
186
186
  @connectionsCV = ConditionVariable.new
187
187
  @stdlog = stdlog
188
188
  @audit = audit
@@ -204,6 +204,7 @@ class GServer
204
204
  @@services[@host][@port] = self;
205
205
  }
206
206
  @tcpServerThread = Thread.new {
207
+ Thread.current[:_name] = "thread gserver tcpServerThread"
207
208
  begin
208
209
  starting if @audit
209
210
  while !@shutdown
@@ -249,7 +250,7 @@ class GServer
249
250
  @connections.each { |c| c.raise "stop" }
250
251
  end
251
252
  @tcpServerThread = nil
252
- @@servicesMutex.synchronize {
253
+ @@servicesMutex.timeout_sync(10, :stopping) {
253
254
  @@services[@host].delete(@port)
254
255
  }
255
256
  stopping if @audit
@@ -0,0 +1,115 @@
1
+ #!ruby -Ku
2
+
3
+ =begin
4
+ = dango用のlogger
5
+ =end
6
+
7
+
8
+ require 'logger'
9
+ require 'thread'
10
+ require 'pp'
11
+
12
+
13
+ # クライアントとサーバーで共有するモジュール
14
+ module DangoLoggerModule
15
+ # ロガーの定義
16
+ def logger
17
+ # if !@dango_logger # これだと警告が出てうざいので
18
+ if !self.instance_variables.find{|iv| iv == '@dango_logger'} # @dango_loggerが未定義なら
19
+ # loggerの初回呼び出し時
20
+ @dango_logger = DangoLogger.new(@log_file, @log_shift_age, @log_max_size, @log_level)
21
+ end
22
+
23
+ @dango_logger
24
+ end
25
+ end
26
+
27
+ # Dango用のロガークラス
28
+ class DangoLogger
29
+ include ErrorMessage
30
+
31
+ def initialize(log_file, log_shift_age, log_max_size, log_level)
32
+ @log_file = log_file
33
+ @log_shift_age = log_shift_age
34
+ @log_max_size = log_max_size
35
+ @log_level = log_level
36
+
37
+ if @log_file && @log_file != "" # 出力ファイルが空なら何もしない
38
+ @is_logging = true
39
+ else
40
+ @is_logging = false
41
+ end
42
+
43
+ if @is_logging
44
+ log_dir = File.dirname(@log_file)
45
+ Dir.mkdir(log_dir) if !File.exist?(log_dir)
46
+ @dango_logger = Logger.new(@log_file, @log_shift_age, @log_max_size)
47
+ @dango_logger.level = @log_level
48
+ def @dango_logger.format_message(severity, timestamp, msg, progname)
49
+ now = Time.now
50
+ now_str = now.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % now.usec
51
+ "%1.1s, [%s] %s:%s\n" % [severity, now_str, msg,
52
+ progname]
53
+ end
54
+ @dango_logger.add(1, "--- start log ---", "logger")
55
+
56
+ @log_queue = Queue.new
57
+
58
+ Thread.start do
59
+ # logger作成
60
+ loop do
61
+ begin
62
+ data = @log_queue.pop
63
+ @dango_logger.add(data[:sev], data[:msg], data[:prg])
64
+ rescue Exception
65
+ puts "dango_logger:#{error_message($!, 'u')}"
66
+ exit! # ログのトラブルが出た場合は強制終了
67
+ end
68
+ end
69
+ end # Thread.end
70
+ end
71
+ end
72
+
73
+ def debug(msg = "")
74
+ if @is_logging
75
+ @log_queue.push({:sev=>0, :msg=>msg, :prg=>Thread.current.object_id})
76
+ end
77
+ end
78
+
79
+ def info(msg = "")
80
+ if @is_logging
81
+ @log_queue.push({:sev=>1, :msg=>msg, :prg=>Thread.current.object_id})
82
+ end
83
+ end
84
+
85
+ def warn(msg = "")
86
+ if @is_logging
87
+ @log_queue.push({:sev=>2, :msg=>msg, :prg=>Thread.current.object_id})
88
+ end
89
+ end
90
+
91
+ def error(msg = "")
92
+ if @is_logging
93
+ @log_queue.push({:sev=>3, :msg=>msg, :prg=>Thread.current.object_id})
94
+ end
95
+ end
96
+
97
+ def fatal(msg = "")
98
+ if @is_logging
99
+ @log_queue.push({:sev=>4, :msg=>msg, :prg=>Thread.current.object_id})
100
+ end
101
+ end
102
+
103
+ def unknown(msg = "")
104
+ if @is_logging
105
+ @log_queue.push({:sev=>5, :msg=>msg, :prg=>Thread.current.object_id})
106
+ end
107
+ end
108
+
109
+ def add(sev, msg = "")
110
+ if @is_logging
111
+ @log_queue.push({:sev=>sev, :msg=>str, :prg=>Thread.current.object_id})
112
+ end
113
+ end
114
+ end
115
+
@@ -0,0 +1,64 @@
1
+ #!ruby -Ku
2
+
3
+ =begin
4
+ = Dango用のMutex
5
+ =end
6
+
7
+
8
+ require 'thread'
9
+
10
+ # Mutexクラスの名前情報機能追加
11
+ class DangoMutex < Mutex
12
+ def initialize(mutex_name = nil)
13
+ @mutex_name = mutex_name.to_s
14
+ @lock_name = ""
15
+ super()
16
+ end
17
+
18
+ attr_reader(:mutex_name, :lock_name)
19
+
20
+ # タイムアウトする排他処理
21
+ def timeout_sync(sec = 10, lock_name = "")
22
+ ret = nil
23
+ begin
24
+ timeout(sec, DangoFrameworkMutexTimeoutException) do
25
+ self.synchronize do
26
+ @lock_name = lock_name
27
+ ret = yield
28
+ end
29
+ end
30
+
31
+ rescue DangoFrameworkMutexTimeoutException, Timeout::Error, TimeoutError
32
+
33
+ # なぜかDangoFrameworkMutexTimeoutException以外の例外クラスが飛ぶことがあるので
34
+ if $!.class == DangoFrameworkMutexTimeoutException
35
+ error_msg = ""
36
+ else
37
+ error_msg = "#{$!.class}:"
38
+ end
39
+
40
+ locked_msg = ""
41
+ ObjectSpace.each_object(DangoMutex) do |object|
42
+ if object.locked?
43
+ locked_msg += "#{object.mutex_name.to_s}(#{object.lock_name.to_s}) "
44
+ end
45
+ end
46
+
47
+ error_msg += "DangoFrameworkMutexTimeoutException" +
48
+ "self=#{self.mutex_name}(#{lock_name})\n" +
49
+ "locked_mutex=#{locked_msg}\n" +
50
+ "#{$!.message}\n" +
51
+ "#{$!.backtrace.pretty_inspect}"
52
+
53
+ raise(DangoFrameworkMutexTimeoutException, error_msg)
54
+
55
+ rescue Exception
56
+ puts "#{$!.class} #{$!.message}\n#{$!.backtrace.pretty_inspect}"
57
+
58
+ raise
59
+ end
60
+
61
+ ret
62
+ end
63
+ end
64
+
@@ -0,0 +1,140 @@
1
+ #!ruby -Ku
2
+
3
+ =begin
4
+ = デフォルトのdango_receive_*群
5
+ =end
6
+
7
+ # デフォルトのdango_receive_*群
8
+ module DefaultDangoReceive
9
+ # クライアントから来たheart_beatなら
10
+ def dango_receive__notice_heart_beat(ret_obj)
11
+ logger.debug "dango_receive__notice_heart_beat:#{session[:sid]}:#{ret_obj['_hb_id']} "
12
+
13
+ shared.transaction(:_heart_beat_time_hash) do |heart_beat_time_hash|
14
+ heart_beat_time_hash[session[:sid]] = Time.now
15
+ shared.commit(heart_beat_time_hash)
16
+ end
17
+ end
18
+
19
+ # action_nameがエンコード変更なら
20
+ def dango_receive__change_encode_type(ret_obj)
21
+ logger.debug "dango_receive__change_encode_type: #{ret_obj['encode_type'].inspect}"
22
+ session[:encode_type] = ret_obj['encode_type']
23
+ end
24
+
25
+
26
+
27
+ ################## メンテナンスアクション系 ##################
28
+
29
+ public
30
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
31
+ def dango_receive__monitor_get_server_info(ret_obj)
32
+ logger.debug "dango_receive__monitor_get_server_info:#{ret_obj.inspect}"
33
+ dango_check_monitor_error()
34
+
35
+ get_server_info = {
36
+ 'server_start_time' => start_time.strftime("%Y-%m-%d %H:%M:%S"),
37
+ 'up_time' => Time.now - start_time,
38
+
39
+ 'recv_count' => recv_count, # 受信回数
40
+ 'send_count' => send_count, # 送信回数
41
+ 'recv_fail_count' => recv_fail_count, # 受信失敗回数
42
+ 'send_fail_count' => send_fail_count, # 送信失敗回数
43
+
44
+ 'log_level' => log_level_str,
45
+ 'log_file' => log_file,
46
+ 'log_max_size' => log_max_size,
47
+ 'log_shift_age' => log_shift_age,
48
+ }
49
+
50
+ send_obj = {'code'=>0, 'get_server_info'=>get_server_info}
51
+ send_notice('return__monitor_get_server_info', session[:sid], send_obj, :type=>2)
52
+ end
53
+
54
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
55
+ def dango_receive__monitor_get_shared(ret_obj)
56
+ logger.debug "dango_receive__monitor_get_shared:#{ret_obj.inspect}"
57
+ dango_check_monitor_error()
58
+
59
+ send_obj = {'code'=>0, 'get_shared'=>shared.to_hash}
60
+ send_notice('return__monitor_get_shared', session[:sid], send_obj, :type=>2)
61
+ end
62
+
63
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
64
+ def dango_receive__monitor_get_session_list(ret_obj)
65
+ logger.debug "dango_receive__monitor_get_session_list:#{ret_obj.inspect}"
66
+ dango_check_monitor_error()
67
+
68
+ send_obj = {'code'=>0, 'get_session_list'=>session_list}
69
+ send_notice('return__monitor_get_session_list', session[:sid], send_obj, :type=>2)
70
+ end
71
+
72
+ # メンテナンスコマンド:サーバーからクライアントへのデータ送信
73
+ def dango_receive__monitor_get_socket_list(ret_obj)
74
+ logger.debug "dango_receive__monitor_get_socket_list:#{ret_obj.inspect}"
75
+ dango_check_monitor_error()
76
+
77
+ send_obj = {'code'=>0, 'get_socket_list'=>socket_list.keys}
78
+ send_notice('return__monitor_get_socket_list', session[:sid], send_obj, :type=>2)
79
+ end
80
+
81
+ # メンテナンスコマンド:サーバーデータ再読み込み
82
+ def dango_receive__monitor_server_reload(ret_obj)
83
+ logger.debug "dango_receive__monitor_server_reload"
84
+ dango_check_monitor_error()
85
+
86
+ @server_reload = true
87
+ logger.debug "@server_reload=#{@server_reload.inspect}"
88
+ send_obj = {'code'=>0, 'message'=>'success'}
89
+ send_notice('return__monitor_server_reload', session[:sid], send_obj, :type=>2)
90
+ end
91
+
92
+ # メンテナンスコマンド:接続者全員へメッセージ送信
93
+ def dango_receive__monitor_send_system_message(ret_obj)
94
+ logger.debug "dango_receive__monitor_send_system_message:#{ret_obj.inspect}"
95
+ dango_check_monitor_error()
96
+
97
+ # 全員へ_notice_system_messageを通知
98
+ socket_list.keys.each do |sid|
99
+ next if session[:sid] == sid
100
+ send_obj = { "message" => ret_obj["message"] }
101
+ send_notice('_notice_system_message', sid, send_obj)
102
+ end
103
+
104
+ send_obj = {'code'=>0, }
105
+ send_notice('return__monitor_send_system_message', session[:sid], send_obj, :type=>2)
106
+ end
107
+
108
+ private
109
+ # メンテナンスコマンド:エラーの場合
110
+ def dango_check_monitor_error()
111
+ action_name = session[:_action_name]
112
+ peerhost = session[:peer_host]
113
+ peeraddr = session[:peer_ip_address]
114
+
115
+ logger.debug "dango_check_monitor_error:peerhost=#{peerhost.inspect} peeraddr=#{peeraddr.inspect} @backdoor_host=#{@backdoor_host.inspect}"
116
+
117
+ match = false
118
+ if peerhost == backdoor_host # ホスト名で書いてある時の一致確認
119
+ match = true
120
+ else
121
+ begin # IPアドレスの一致確認
122
+ # match = true if IPAddr.new(@backdoor_host).include?(peeraddr)
123
+ if IPAddr.new(@backdoor_host).include?(IPAddr.new(peeraddr))
124
+ match = true
125
+ end
126
+ rescue
127
+ end
128
+ end
129
+
130
+ if !match
131
+ notice_name = "return_" + action_name
132
+ send_obj = {'code'=>1, 'message'=>"error your ip address"}
133
+ send_notice(notice_name, session[:sid], send_obj, :type=>2)
134
+ raise(DangoFrameworkMonitorSecurityError)
135
+ end
136
+ end
137
+
138
+
139
+ end
140
+