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
@@ -0,0 +1,30 @@
|
|
1
|
+
#!ruby -Ku
|
2
|
+
|
3
|
+
=begin
|
4
|
+
= エラーメッセージ出力用
|
5
|
+
=end
|
6
|
+
|
7
|
+
|
8
|
+
require 'pp'
|
9
|
+
|
10
|
+
|
11
|
+
# エラー出力用モジュール
|
12
|
+
module ErrorMessage
|
13
|
+
# デバッグ出力用のメソッド
|
14
|
+
def error_message(exception_class, code = nil)
|
15
|
+
if exception_class.kind_of?(Exception)
|
16
|
+
"#{exception_class.class} is not Exception class"
|
17
|
+
end
|
18
|
+
|
19
|
+
str = "class=#{exception_class.class}\n" +
|
20
|
+
"message=#{exception_class.message}\n" +
|
21
|
+
"backtrace=#{exception_class.backtrace.pretty_inspect}"
|
22
|
+
if code.to_s.downcase == "u" || code.to_s.downcase == "utf8"
|
23
|
+
str = str.toutf8
|
24
|
+
elsif code.to_s.downcase == "s" || code.to_s.downcase == "sjis"
|
25
|
+
str = str.tosjis
|
26
|
+
end
|
27
|
+
str
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/lib/dango/framework_base.rb
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
require 'socket'
|
9
9
|
require 'logger'
|
10
|
-
require 'thread'
|
11
10
|
require 'timeout'
|
12
11
|
require 'yaml'
|
13
12
|
require "stringio"
|
@@ -18,8 +17,26 @@ require "fcntl"
|
|
18
17
|
require "rubygems"
|
19
18
|
require 'json/add/rails'
|
20
19
|
|
20
|
+
require 'thread'
|
21
|
+
#require 'fastthread'
|
21
22
|
|
22
|
-
require "dango/
|
23
|
+
require "dango/error_message"
|
24
|
+
require "dango/dango_logger"
|
25
|
+
require "dango/dango_mutex"
|
26
|
+
require "dango/shared/memory_store"
|
27
|
+
|
28
|
+
|
29
|
+
# 例外定義
|
30
|
+
class DangoFrameworkException < StandardError; end
|
31
|
+
class DangoFrameworkTimeoutException < DangoFrameworkException; end
|
32
|
+
class DangoFrameworkConnectionException < DangoFrameworkException; end
|
33
|
+
class DangoFrameworkDisconnectException < DangoFrameworkException; end
|
34
|
+
class DangoFrameworkReadNoDataException < DangoFrameworkException; end
|
35
|
+
class DangoFrameworkReadTimeoutException < DangoFrameworkException; end
|
36
|
+
class DangoFrameworkFlashPolicyException < DangoFrameworkException; end
|
37
|
+
class DangoFrameworkMonitorSecurityException < DangoFrameworkException; end
|
38
|
+
class DangoFrameworkTransactionException < DangoFrameworkException; end
|
39
|
+
class DangoFrameworkMutexTimeoutException < DangoFrameworkException; end
|
23
40
|
|
24
41
|
|
25
42
|
class Object
|
@@ -31,7 +48,6 @@ class Object
|
|
31
48
|
sio.rewind
|
32
49
|
sio.read
|
33
50
|
end
|
34
|
-
|
35
51
|
str
|
36
52
|
end
|
37
53
|
end
|
@@ -44,45 +60,18 @@ end
|
|
44
60
|
# Timeクラスの表示形式修正
|
45
61
|
class Time
|
46
62
|
def self.now_to_s
|
47
|
-
# self.strftime("%Y-%m-%d %H:%M:%S")
|
48
63
|
now = self.now
|
49
64
|
now.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % now.usec
|
50
65
|
end
|
51
|
-
|
52
|
-
|
53
|
-
# 例外定義
|
54
|
-
class DangoFrameworkException < StandardError; end
|
55
|
-
class DangoFrameworkTimeoutException < DangoFrameworkException; end
|
56
|
-
class DangoFrameworkConnectionException < DangoFrameworkException; end
|
57
|
-
class DangoFrameworkDisconnectException < DangoFrameworkException; end
|
58
|
-
class DangoFrameworkReadNoDataException < DangoFrameworkException; end
|
59
|
-
class DangoFrameworkReadTimeoutException < DangoFrameworkException; end
|
60
|
-
class DangoFrameworkFlashPolicyException < DangoFrameworkException; end
|
61
|
-
class DangoFrameworkMonitorSecurityException < DangoFrameworkException; end
|
62
|
-
class DangoFrameworkTransactionException < DangoFrameworkException; end
|
63
|
-
|
64
|
-
|
65
|
-
# エラー出力用モジュール
|
66
|
-
module ErrorMessage
|
67
|
-
# デバッグ出力用のメソッド
|
68
|
-
def error_message(exception_class, code = nil)
|
69
|
-
if exception_class.kind_of?(Exception)
|
70
|
-
"#{exception_class.class} is not Exception class"
|
71
|
-
end
|
72
|
-
|
73
|
-
str = "#{exception_class.class}:#{exception_class.message}\n" +
|
74
|
-
"#{exception_class.backtrace.pretty_inspect}"
|
75
|
-
if code.to_s.downcase == "u" || code.to_s.downcase == "utf8"
|
76
|
-
str = str.toutf8
|
77
|
-
elsif code.to_s.downcase == "s" || code.to_s.downcase == "sjis"
|
78
|
-
str = str.tosjis
|
79
|
-
end
|
80
|
-
str
|
66
|
+
def to_ss
|
67
|
+
self.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % self.usec
|
81
68
|
end
|
82
69
|
end
|
83
70
|
|
84
71
|
# ユーティティ
|
85
72
|
module DangoUtilModule
|
73
|
+
include ErrorMessage
|
74
|
+
|
86
75
|
# 配列をランダムに並べ替え
|
87
76
|
# arrは順番を入れ替えたい配列
|
88
77
|
# numは入れ替え回数(省略時2、大きな数を入れると確実にランダムになるが時間が掛かる)
|
@@ -97,11 +86,71 @@ module DangoUtilModule
|
|
97
86
|
# end
|
98
87
|
# ret_arr
|
99
88
|
end
|
89
|
+
|
90
|
+
def get_process_info(pid_orig = nil) # プロセス情報取得
|
91
|
+
if pid_orig
|
92
|
+
pid = pid_orig.deep_dup
|
93
|
+
else
|
94
|
+
pid = Process.pid
|
95
|
+
end
|
96
|
+
|
97
|
+
ret = ""
|
98
|
+
ret += "=== get_process_info ===\n"
|
99
|
+
ret += "DangoUtilModule::pid = #{pid}\n"
|
100
|
+
ret += "DangoUtilModule::RUBY_VERSION = #{RUBY_VERSION}\n"
|
101
|
+
ret += "DangoUtilModule::RUBY_RELEASE_DATE = #{RUBY_RELEASE_DATE}\n"
|
102
|
+
ret += "DangoUtilModule::RUBY_PLATFORM = #{RUBY_PLATFORM}\n"
|
103
|
+
|
104
|
+
if RUBY_PLATFORM == 'i386-mswin32'
|
105
|
+
|
106
|
+
else
|
107
|
+
proc_process_dir = "/proc/#{pid}"
|
108
|
+
begin
|
109
|
+
if File.directory?(proc_process_dir)
|
110
|
+
# 開始時間
|
111
|
+
ret += "DangoUtilModule::process start time=#{File.mtime(proc_process_dir).to_ss}\n"
|
112
|
+
|
113
|
+
# /proc/#{pid}/statusを読み込む
|
114
|
+
proc_process_status = "/proc/#{pid}/status"
|
115
|
+
|
116
|
+
if File.file?(proc_process_status) && File.readable?(proc_process_status)
|
117
|
+
if RUBY_PLATFORM != 'i386-cygwin' # cygwinだとなぜか落ちるので分離
|
118
|
+
open(proc_process_status, "rb") do |fh|
|
119
|
+
ret += "DangoUtilModule::get_process_info:proc_process_status\n#{fh.read}\n"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# /proc/#{pid}/fdの中の一覧を取得
|
125
|
+
proc_process_fd = "/proc/#{pid}/fd"
|
126
|
+
if File.directory?(proc_process_fd) && File.executable?(proc_process_fd)
|
127
|
+
ret += "DangoUtilModule::get_process_info:proc_process_fd:#{proc_process_fd}\n"
|
128
|
+
Dir.foreach(proc_process_fd) do |file|
|
129
|
+
file_fullpath = "#{proc_process_fd}/#{file}"
|
130
|
+
if File.symlink?(file_fullpath)
|
131
|
+
ret += " #{file_fullpath} -> #{File.readlink(file_fullpath)}\n"
|
132
|
+
else
|
133
|
+
ret += " #{file_fullpath}\n"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
else
|
138
|
+
ret += "DangoUtilModule::#{proc_process_dir} is not exist"
|
139
|
+
end
|
140
|
+
rescue
|
141
|
+
ret += "DangoUtilModule:: #{error_message($!, 'u')}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
ret
|
146
|
+
end
|
147
|
+
|
100
148
|
end
|
101
149
|
|
102
150
|
# クライアントとサーバーで共有するモジュール
|
103
151
|
module DangoFrameworkModule
|
104
152
|
include ErrorMessage
|
153
|
+
include DangoLoggerModule
|
105
154
|
|
106
155
|
CommMaxDigit = 5 # 通信の最大桁数
|
107
156
|
MaxLenRecv = 1024 # 通信の一度の送信バイト数
|
@@ -131,45 +180,14 @@ module DangoFrameworkModule
|
|
131
180
|
puts str
|
132
181
|
end
|
133
182
|
|
134
|
-
# ロガーの定義
|
135
|
-
def logger
|
136
|
-
# if !@dango_logger # これだと警告が出てうざいので
|
137
|
-
if !self.instance_variables.find{|iv| iv == '@dango_logger'} # @dango_loggerが未定義なら
|
138
|
-
|
139
|
-
if @log_file == "" # ログを取らない設定の場合は
|
140
|
-
@dango_logger = "LOG NONE"
|
141
|
-
def @dango_logger.fatal(str); end
|
142
|
-
def @dango_logger.error(str); end
|
143
|
-
def @dango_logger.info(str) ; end
|
144
|
-
def @dango_logger.warn(str) ; end
|
145
|
-
def @dango_logger.debug(str); end
|
146
|
-
|
147
|
-
else # ログを取る設定の場合は
|
148
|
-
log_dir = File.dirname(@log_file)
|
149
|
-
Dir.mkdir(log_dir) if !File.exist?(log_dir)
|
150
|
-
@dango_logger = Logger.new(@log_file, @log_shift_age, @log_max_size)
|
151
|
-
@dango_logger.level = @log_level
|
152
|
-
def @dango_logger.format_message(severity, timestamp, msg, progname)
|
153
|
-
now = Time.now
|
154
|
-
now_str = now.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % now.usec
|
155
|
-
"%1.1s, [%s] %d:%s %s\n" % [severity, now_str, Thread.current.object_id, progname, msg]
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
|
161
|
-
@dango_logger
|
162
|
-
end
|
163
|
-
|
164
|
-
attr(:dango_logger)
|
165
|
-
|
166
183
|
# データ受信処理
|
167
184
|
def dango_receive_data(sock)
|
168
|
-
logger.debug "dango_receive_data:start:sock=#{sock}"
|
169
185
|
ret_data = ""
|
170
186
|
|
171
187
|
begin
|
172
188
|
size_str = sock.recv(CommMaxDigit + 1)
|
189
|
+
logger.debug "dango_receive_data:read header:sock=#{sock}"
|
190
|
+
|
173
191
|
rescue EOFError, IOError, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ECONNABORTED
|
174
192
|
# 接続終了時の切断と思われるものはDangoFrameworkConnectionExceptionにしない
|
175
193
|
raise(DangoFrameworkDisconnectException, "failed to read sock for EOF reached (and so on). " +
|
@@ -205,7 +223,10 @@ module DangoFrameworkModule
|
|
205
223
|
raise(DangoFrameworkConnectionException, "too big... size=#{size}:size_str=#{size_str.inspect}")
|
206
224
|
end
|
207
225
|
|
208
|
-
|
226
|
+
logger.warn "warn size is too big ? size=#{size}:size_str=#{size_str.inspect}" if size > 10000
|
227
|
+
|
228
|
+
|
229
|
+
recv_data_orig = ""
|
209
230
|
|
210
231
|
# 10秒でタイムアウトを起こす
|
211
232
|
timeout(ReadTimeoutSec, DangoFrameworkReadTimeoutException) do
|
@@ -214,34 +235,41 @@ module DangoFrameworkModule
|
|
214
235
|
while size > 0
|
215
236
|
read_len = MaxLenRecv > size ? size : MaxLenRecv
|
216
237
|
begin
|
217
|
-
|
238
|
+
this_recv_data_orig = sock.recv(read_len)
|
218
239
|
rescue
|
219
240
|
raise(DangoFrameworkConnectionException, "failed to read sock(data).\n#{error_message($!, 'u')}")
|
220
241
|
end
|
221
242
|
|
222
|
-
|
243
|
+
recv_data_orig += this_recv_data_orig
|
223
244
|
|
224
|
-
size -=
|
245
|
+
size -= this_recv_data_orig.size
|
225
246
|
end
|
226
247
|
end
|
227
248
|
|
228
|
-
|
249
|
+
recv_data = receive_decrypt(recv_data_orig[0..-2])
|
229
250
|
|
230
251
|
@recv_count += 1 if @recv_count # 受信回数カウント
|
231
252
|
|
232
253
|
begin
|
233
|
-
if
|
234
|
-
|
254
|
+
if recv_data == "" || recv_data == "{}" # データが空ならparseしない
|
255
|
+
ret_data = []
|
235
256
|
elsif encode_type == EncodeTypeJSON
|
236
|
-
|
257
|
+
ret_data = JSON.parse(recv_data)
|
237
258
|
elsif encode_type == EncodeTypeYAML
|
238
|
-
|
259
|
+
ret_data = YAML::load(recv_data)
|
239
260
|
elsif encode_type == EncodeTypeMarshal
|
240
|
-
|
261
|
+
ret_data = Marshal.load(recv_data)
|
262
|
+
end
|
263
|
+
|
264
|
+
if ret_data.class != Array
|
265
|
+
raise(DangoFrameworkConnectionException, "data is not array.#{$!.class}\nret_data=#{ret_data}")
|
241
266
|
end
|
267
|
+
|
242
268
|
rescue
|
243
269
|
raise(DangoFrameworkConnectionException, "data parse error.#{$!.class}\nret_data=#{ret_data}")
|
244
270
|
end
|
271
|
+
|
272
|
+
ret_data
|
245
273
|
end
|
246
274
|
|
247
275
|
# データ送信処理
|
@@ -251,7 +279,12 @@ module DangoFrameworkModule
|
|
251
279
|
if send_objs == []
|
252
280
|
send_data_orig = ""
|
253
281
|
elsif encode_type == EncodeTypeJSON
|
254
|
-
|
282
|
+
begin
|
283
|
+
send_data_orig = JSON.generate(send_objs)
|
284
|
+
rescue
|
285
|
+
pp send_objs
|
286
|
+
raise
|
287
|
+
end
|
255
288
|
elsif encode_type == EncodeTypeYAML
|
256
289
|
send_data_orig = send_objs.to_yaml
|
257
290
|
elsif encode_type == EncodeTypeMarshal
|
@@ -260,7 +293,7 @@ module DangoFrameworkModule
|
|
260
293
|
send_data_orig = JSON.generate(send_objs)
|
261
294
|
end
|
262
295
|
|
263
|
-
send_data =
|
296
|
+
send_data = send_encrypt(send_data_orig) + "\n"
|
264
297
|
|
265
298
|
size = send_data.size
|
266
299
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#!ruby -Ku
|
2
|
+
|
3
|
+
=begin
|
4
|
+
= Dangoサーバーのメインモジュール(drbで呼び出す用)
|
5
|
+
=end
|
6
|
+
|
7
|
+
# メインモジュール(drbで呼び出す用)
|
8
|
+
module ServerMonitorModule
|
9
|
+
# drbから呼ばれるメンテナンス:サーバーからクライアントへのデータ送信
|
10
|
+
def _monitor_get_server_info(ret_obj)
|
11
|
+
logger.debug "_monitor_get_server_info"
|
12
|
+
|
13
|
+
get_server_info = {
|
14
|
+
'server_start_time' => start_time.strftime("%Y-%m-%d %H:%M:%S"),
|
15
|
+
'up_time' => Time.now - start_time,
|
16
|
+
|
17
|
+
'recv_count' => recv_count, # 受信回数
|
18
|
+
'send_count' => send_count, # 送信回数
|
19
|
+
'recv_fail_count' => recv_fail_count, # 受信失敗回数
|
20
|
+
'send_fail_count' => send_fail_count, # 送信失敗回数
|
21
|
+
|
22
|
+
# 'log_level' => log_level_str,
|
23
|
+
# 'log_file' => log_file,
|
24
|
+
# 'log_max_size' => log_max_size,
|
25
|
+
# 'log_shift_age' => log_shift_age,
|
26
|
+
}
|
27
|
+
|
28
|
+
get_server_info
|
29
|
+
end
|
30
|
+
|
31
|
+
# drbから呼ばれるメンテナンス:サーバーデータ再読み込み
|
32
|
+
def _monitor_server_reload(ret_obj)
|
33
|
+
logger.debug "_monitor_server_reload"
|
34
|
+
@server_reload = true
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
# drbから呼ばれるメンテナンス:接続者全員へメッセージ送信
|
39
|
+
def _monitor_send_system_message(ret_obj)
|
40
|
+
logger.debug "_monitor_send_system_message"
|
41
|
+
|
42
|
+
# 全員へ_notice_system_messageを通知
|
43
|
+
socket_list.all_sid.each do |sid|
|
44
|
+
next if session[:sid] == sid
|
45
|
+
send_obj = { "message" => ret_obj["message"] }
|
46
|
+
send_notice('_notice_system_message', sid, send_obj)
|
47
|
+
end
|
48
|
+
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
# drbから呼ばれるメンテナンス:スレッド一覧
|
53
|
+
def _monitor_thread_status(ret_obj)
|
54
|
+
logger.debug "_monitor_thread_status"
|
55
|
+
ret = []
|
56
|
+
|
57
|
+
Thread.list.each do |th|
|
58
|
+
ret.push({
|
59
|
+
:object_id => th.object_id,
|
60
|
+
:name => th[:_name] ? th[:_name] : "unknown(maybe drb thread)",
|
61
|
+
})
|
62
|
+
end
|
63
|
+
|
64
|
+
ret
|
65
|
+
end
|
66
|
+
|
67
|
+
# drbから呼ばれるメンテナンス:排他処理一覧
|
68
|
+
def _monitor_mutex_status(ret_obj)
|
69
|
+
logger.debug "_monitor_mutex_status"
|
70
|
+
ret = []
|
71
|
+
|
72
|
+
ObjectSpace.each_object(DangoMutex) do |object|
|
73
|
+
ret.push({
|
74
|
+
:name => object.mutex_name,
|
75
|
+
:is_lock => object.locked?,
|
76
|
+
})
|
77
|
+
end
|
78
|
+
|
79
|
+
# mutex_list = [
|
80
|
+
# [:mutex_send_response, @mutex_send_response],
|
81
|
+
# [:mutex_send_notice , @mutex_send_notice],
|
82
|
+
# [:mutex_proc_thread , @mutex_proc_thread],
|
83
|
+
# [:mutex_send_response, @mutex_send_response],
|
84
|
+
# ]
|
85
|
+
# @mutex_sock.each do |key, value|
|
86
|
+
# mutex_list.push(["mutex_sock #{key}", value])
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# mutex_list.each do |name, mutex|
|
90
|
+
# ret.push({
|
91
|
+
# :name => name.to_s,
|
92
|
+
# :is_lock => mutex.locked?,
|
93
|
+
# })
|
94
|
+
# end
|
95
|
+
|
96
|
+
ret
|
97
|
+
end
|
98
|
+
|
99
|
+
# drbから呼ばれるメンテナンス:shareの取得
|
100
|
+
# key value
|
101
|
+
def _monitor_get_shared(ret_obj)
|
102
|
+
logger.debug "_monitor_get_shared:ret_obj=#{ret_obj.inspect}"
|
103
|
+
shared.to_hash
|
104
|
+
end
|
105
|
+
|
106
|
+
# drbから呼ばれるメンテナンス:shareの強制書き換え
|
107
|
+
# key value
|
108
|
+
def _monitor_write_shared(ret_obj)
|
109
|
+
logger.debug "_monitor_write_shared:ret_obj=#{ret_obj.inspect}"
|
110
|
+
logger.debug "_monitor_write_shared:value=#{eval(ret_obj['value']).inspect}"
|
111
|
+
|
112
|
+
shared[ret_obj["key"]] = eval(ret_obj['value'])
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
# drbから呼ばれるメンテナンス:session_listの取得
|
117
|
+
def _monitor_get_session_list(ret_obj)
|
118
|
+
logger.debug "_monitor_get_session_list:#{ret_obj.inspect}"
|
119
|
+
session_list
|
120
|
+
end
|
121
|
+
|
122
|
+
# drbから呼ばれるメンテナンス:socket_listの取得
|
123
|
+
def _monitor_get_socket_list(ret_obj)
|
124
|
+
logger.debug "_monitor_get_socket_list:#{ret_obj.inspect}"
|
125
|
+
ret = {}
|
126
|
+
socket_list.all_sid.each{|sid| ret[sid] = socket_list[sid].object_id}
|
127
|
+
ret
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|