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.
- data/lib/dango/client_framework.rb +13 -12
- data/lib/dango/controller_plugin/dango_controller_plugin.rb +7 -3
- data/lib/dango/dango_g_server.rb +7 -6
- data/lib/dango/dango_logger.rb +115 -0
- data/lib/dango/dango_mutex.rb +64 -0
- data/lib/dango/default_dango_receive.rb +140 -0
- data/lib/dango/error_message.rb +30 -0
- data/lib/dango/framework_base.rb +112 -79
- data/lib/dango/monitor/server_monitor_module.rb +131 -0
- data/lib/dango/server_framework.rb +215 -145
- data/lib/dango/session_manager.rb +15 -10
- data/lib/dango/shared/memory_store.rb +10 -10
- data/lib/dango/socket_list.rb +5 -5
- data/lib/dango/tasks/dango_rake.rb +379 -166
- data/lib/dango/tester/dango_tester_client.rb +1 -6
- data/lib/dango/version.rb +2 -2
- metadata +8 -3
@@ -73,7 +73,8 @@ class DangoClientFramework
|
|
73
73
|
@log_shift_age = @connection_client_log_shift_age
|
74
74
|
|
75
75
|
# loggerの準備
|
76
|
-
logger.
|
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 =
|
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 =
|
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
|
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
|
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.
|
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
|
-
|
24
|
-
|
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
|
data/lib/dango/dango_g_server.rb
CHANGED
@@ -98,10 +98,10 @@ class GServer
|
|
98
98
|
end
|
99
99
|
|
100
100
|
@@services = {} # Hash of opened ports, i.e. services
|
101
|
-
@@servicesMutex =
|
101
|
+
@@servicesMutex = DangoMutex.new(:gServer_servicesMutex)
|
102
102
|
|
103
103
|
def GServer.stop(port, host = DEFAULT_HOST)
|
104
|
-
@@servicesMutex.
|
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.
|
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 =
|
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.
|
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
|
+
|