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.
@@ -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
+
@@ -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/shared/memory_store.rb"
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
- end
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
- ret_data_orig = ""
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
- this_ret_data_orig = sock.recv(read_len)
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
- ret_data_orig += this_ret_data_orig
243
+ recv_data_orig += this_recv_data_orig
223
244
 
224
- size -= this_ret_data_orig.size
245
+ size -= this_recv_data_orig.size
225
246
  end
226
247
  end
227
248
 
228
- ret_data = dango_receive_decrypt(ret_data_orig[0..-2])
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 ret_data == "" || ret_data == "{}" # データが空ならparseしない
234
- data = []
254
+ if recv_data == "" || recv_data == "{}" # データが空ならparseしない
255
+ ret_data = []
235
256
  elsif encode_type == EncodeTypeJSON
236
- data = JSON.parse(ret_data)
257
+ ret_data = JSON.parse(recv_data)
237
258
  elsif encode_type == EncodeTypeYAML
238
- data = YAML::load(ret_data)
259
+ ret_data = YAML::load(recv_data)
239
260
  elsif encode_type == EncodeTypeMarshal
240
- data = Marshal.load(ret_data)
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
- send_data_orig = JSON.generate(send_objs)
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 = dango_send_encrypt(send_data_orig) + "\n"
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
+