Module: DangoFrameworkModule

Includes:
ErrorMessage
Included in:
DangoClientFramework, DangoServerFramework
Defined in:
lib/dango/framework_base.rb,
lib/dango/shared/memory_store.rb

Overview

クライアントとサーバーで共有するモジュール

Defined Under Namespace

Classes: SharedMemoryStore

Constant Summary collapse

CommMaxDigit =

通信の最大桁数

5
MaxLenRecv =

通信の一度の送信バイト数

1024
MaxLenSend =

通信の一度の送信バイト数

1024 * 1024
EncodeTypeJSON =

4294967296 # 本当はuint最大値なんだけれど、policyファイルの都合で変えてある

1886350440 
1886350441
0
EncodeTypeYAML =

エンコードのタイプのJSON

1
EncodeTypeMarshal =

エンコードのタイプのYAML

2
DefaultEncodeType =

エンコードのタイプのMarshal

EncodeTypeJSON
ReadTimeoutSec =

デフォルトのエンコードのタイプ

10.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ErrorMessage

#error_message

Instance Attribute Details

#dango_loggerObject (readonly)

Returns the value of attribute dango_logger.



164
165
166
# File 'lib/dango/framework_base.rb', line 164

def dango_logger
  @dango_logger
end

Instance Method Details

#dango_receive_data(sock) ⇒ Object

データ受信処理



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/dango/framework_base.rb', line 167

def dango_receive_data(sock)
  logger.debug "dango_receive_data:start:sock=#{sock}"
  ret_data = ""
  
  begin
    size_str = sock.recv(CommMaxDigit + 1)
  rescue EOFError, IOError, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ECONNABORTED
    # 接続終了時の切断と思われるものはDangoFrameworkConnectionExceptionにしない
    raise(DangoFrameworkDisconnectException, "failed to read sock for EOF reached (and so on). " + 
                                             "sock=#{sock.inspect} #{$!.class} toid=#{Thread.current.object_id}")
  rescue
    raise(DangoFrameworkConnectionException, "failed to read sock. sock=#{sock.inspect} " + 
                                             "toid=#{Thread.current.object_id}\n#{error_message($!, 'u')}")
  end
  
  if size_str == ""
    raise(DangoFrameworkReadNoDataException, "toid=#{Thread.current.object_id}:size_str=#{size_str.inspect}") 
  end
  
  ## Flash のpolicyファイルだった場合(特殊)
  if size_str == "<polic"
    logger.debug "size_str=#{size_str.inspect}"
    receive_data = sock.recv(18)
    logger.info "flash policy file: dango_receive_data:receive_data=#{receive_data}"
    raise(DangoFrameworkFlashPolicyException) 
  end
  
  ## サイズとデータタイプを取得
  encode_type, size = size_str[0, 5].unpack("cN")
  
  ## データがない場合
  if size == nil || size == 0
    raise(DangoFrameworkConnectionException, "toid=#{Thread.current.object_id}" + 
                                             ":size=#{size}:size_str=#{size_str.inspect}") 
  end
  
  ## データが大きすぎる場合
  if size >= MaxLenSend
    raise(DangoFrameworkConnectionException, "too big... size=#{size}:size_str=#{size_str.inspect}")
  end
  
  ret_data_orig = ""
  
  # 10秒でタイムアウトを起こす
  timeout(ReadTimeoutSec, DangoFrameworkReadTimeoutException) do 
    
    # サイズが0になるまで受信し続ける
    while size > 0
      read_len = MaxLenRecv > size ? size : MaxLenRecv
      begin
        this_ret_data_orig = sock.recv(read_len)
      rescue
        raise(DangoFrameworkConnectionException, "failed to read sock(data).\n#{error_message($!, 'u')}")
      end
      
      ret_data_orig += this_ret_data_orig
      
      size -= this_ret_data_orig.size
    end
  end
  
  ret_data = dango_receive_decrypt(ret_data_orig[0..-2])
  
  @recv_count += 1 if @recv_count # 受信回数カウント
  
  begin
    if ret_data == "" || ret_data == "{}" # データが空ならparseしない
      data = []
    elsif encode_type == EncodeTypeJSON
      data = JSON.parse(ret_data)
    elsif encode_type == EncodeTypeYAML
      data = YAML::load(ret_data)
    elsif encode_type == EncodeTypeMarshal
      data = Marshal.load(ret_data)
    end
  rescue
    raise(DangoFrameworkConnectionException, "data parse error.#{$!.class}\nret_data=#{ret_data}")
  end
end

#dango_send_data(sock, send_objs, options = {}) ⇒ Object

データ送信処理



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/dango/framework_base.rb', line 248

def dango_send_data(sock, send_objs, options = {})
  encode_type = options[:encode_type] || DefaultEncodeType
  
  if send_objs == []
    send_data_orig = ""
  elsif encode_type == EncodeTypeJSON
    send_data_orig = JSON.generate(send_objs)
  elsif encode_type == EncodeTypeYAML
    send_data_orig = send_objs.to_yaml
  elsif encode_type == EncodeTypeMarshal
    send_data_orig = Marshal.dump(send_objs)
  else
    send_data_orig = JSON.generate(send_objs)
  end
  
  send_data = dango_send_encrypt(send_data_orig) + "\n"
  
  size = send_data.size
  
  if size >= MaxLenSend
    raise(DangoFrameworkException, "max size over. size:#{size} >= #{MaxLenSend}") 
  end
  
  size_str = [encode_type, size].pack("cN")
  send_buf = size_str + "\n" + send_data
  begin
    sock.write send_buf
    sock.flush
  rescue
    raise(DangoFrameworkConnectionException, "sock write failed.\n#{error_message($!, 'u')}")
  end
  
  @send_count += 1 if @send_count # 受信回数カウント
  
  sock
end

#debug_print(str) ⇒ Object

デバッグ出力用のメソッド



123
124
125
126
# File 'lib/dango/framework_base.rb', line 123

def debug_print(str)
  logger.debug str
  puts str if $VERBOSE
end

#error_print(str) ⇒ Object

エラー出力用のメソッド



129
130
131
132
# File 'lib/dango/framework_base.rb', line 129

def error_print(str)
  logger.error str
  puts str
end

#loggerObject

ロガーの定義



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/dango/framework_base.rb', line 135

def logger
#   if !@dango_logger                                            # これだと警告が出てうざいので
  if !self.instance_variables.find{|iv| iv == '@dango_logger'} # @dango_loggerが未定義なら
    
    if @log_file == "" # ログを取らない設定の場合は
      @dango_logger = "LOG NONE"
      def @dango_logger.fatal(str); end
      def @dango_logger.error(str); end
      def @dango_logger.info(str) ; end
      def @dango_logger.warn(str) ; end
      def @dango_logger.debug(str); end
      
    else               # ログを取る設定の場合は
      log_dir = File.dirname(@log_file)
      Dir.mkdir(log_dir) if !File.exist?(log_dir)
      @dango_logger = Logger.new(@log_file, @log_shift_age, @log_max_size)
      @dango_logger.level = @log_level
      def @dango_logger.format_message(severity, timestamp, msg, progname) 
        now = Time.now
        now_str = now.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % now.usec
        "%1.1s, [%s] %d:%s %s\n" % [severity, now_str, Thread.current.object_id, progname, msg]
      end
    end
    
  end
  
  @dango_logger
end