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.
@@ -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
+