Class: DangoRakeUtil

Inherits:
Object show all
Includes:
DangoUtilModule
Defined in:
lib/dango/tasks/dango_rake.rb

Constant Summary collapse

CheckConnectLogFile =

テスト接続のログ

"log/check_dango_connect.log"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DangoUtilModule

#array_random, #get_process_info

Methods included from ErrorMessage

#error_message

Constructor Details

#initializeDangoRakeUtil

Returns a new instance of DangoRakeUtil.



19
20
21
# File 'lib/dango/tasks/dango_rake.rb', line 19

def initialize
  @log = ""
end

Instance Attribute Details

#logObject

Returns the value of attribute log.



22
23
24
# File 'lib/dango/tasks/dango_rake.rb', line 22

def log
  @log
end

Instance Method Details

#check_dango_connectObject

サーバーへの通信を使ったチェック



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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
# File 'lib/dango/tasks/dango_rake.rb', line 140

def check_dango_connect()
  require 'dango/tester/dango_tester_client'
  
  # コンフィグから check_dango_process_cmd を取得

  config = YAML.load(open("#{RAILS_ROOT}/config/dango/#{ENV['RAILS_ENV']}.yml", "rb"){|fh| fh.read})
  
  serv_info = {}
  serv_info["host"] = config['network']['host'] || 'localhost'
  serv_info["port"] = config['network']['port'] || 15000
  serv_info["log_file"] = CheckConnectLogFile
  serv_info["log_level"] = Logger::DEBUG
  serv_info["log_max_size"] = 10000000
  serv_info["log_shift_age"] = 1
  
#  pp serv_info

  
  sid = nil
  
  tester = DangoTesterClient.new # 開始

  3.times do |i| # 3回接続確認する

    begin
      tester1 = nil
      timeout(6) do
        tester1 = tester.new_client("tester1", serv_info) # テスター1

        
        5.times do |j|
          sleep 1
          sid = tester1.sid.deep_dup
          tester1.logger.warn "count=#{j} sid=#{sid}"
          puts_verbose "count=#{j} sid=#{sid}"
          break if sid
        end
        tester1.dango_client_close if tester1.respond_to?(:dango_client_close)
      end
    rescue TimeoutError
      sid = nil
      puts_verbose "DangoTesterClient.TimeoutError"
    end
    
    tester1 = nil
    
    break if sid # 接続に成功していたらスキップ

    
    puts_verbose "test connect failed #{i}"
  end
  
  tester.gc_thread_stop
  
  if sid
    is_alive_server = true
  else
    is_alive_server = false
  end
  
  is_alive_server
end

#check_exist_dango_process(pid) ⇒ Object

pidのプロセスがあるかどうかのチェック



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/dango/tasks/dango_rake.rb', line 53

def check_exist_dango_process(pid)
  puts_verbose "check_exist_dango_process(pid=#{pid})"
  
  # そのpidのプロセスがあるかのチェック

  is_pid_exist = nil
  
  if RUBY_PLATFORM == 'i386-mswin32'
    # WbemからProcessIDを取得

    require "win32ole"
    begin
      n_locator = WIN32OLE.new("WbemScripting.SWbemLocator.1")
      n_service = n_locator.ConnectServer
    rescue
      puts_verbose "failed connect to Wbem:#{$!.inspect}"
      return
    end
    
    set = n_service.ExecQuery("select Caption, ProcessID from Win32_Process where ProcessID = #{pid}")
    set.each do |one|
      puts_verbose(sprintf("Win32_Process %8d %s", one.ProcessID, one.Caption))
      if one.ProcessID == pid
        is_pid_exist = true
      end
    end
    
  else ## i386-mswin32以外

    is_pid_exist = FileTest.exist?("/proc/#{pid}")
  end
  
  if is_pid_exist
    puts_verbose "dango_process is exist."
  else
    puts_verbose "dango_process is not exist."
  end
  
  is_pid_exist
end

#check_verbose_modeObject

verboseモードのフラグを立てる処理



25
26
27
# File 'lib/dango/tasks/dango_rake.rb', line 25

def check_verbose_mode()
  $is_verbose = (ENV["verbose"] == "true" || ENV["verbose"] == "on") ? true : false
end

#drb_call(method_name, arg = nil) ⇒ Object

drbからのサーバー呼び出し



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/dango/tasks/dango_rake.rb', line 198

def drb_call(method_name, arg = nil)
  config = YAML.load(open("#{RAILS_ROOT}/config/dango/#{ENV['RAILS_ENV']}.yml", "rb"){|fh| fh.read})
  
  raise("backdoor_run_drb_server is false.") if !config['server']['backdoor_run_drb_server']
  
  if ENV['url']
    drb_uri = ENV['url']
  else
    drb_uri = config['server']['backdoor_run_drb_url']
  end
  puts_verbose drb_uri
  
  ret = nil
  begin
    timeout(3) do
      drb_obj = DRbObject.new_with_uri(drb_uri)
      ret = drb_obj.__send__(method_name.to_s, arg)
    end
  rescue Exception
    raise("DRbError:#{$!.class} #{$!.message} #{$!.backtrace.pretty_inspect}")
  end
  ret
end

#get_dango_pidObject

pid保存ファイルの読み出し



42
43
44
45
46
47
48
49
50
# File 'lib/dango/tasks/dango_rake.rb', line 42

def get_dango_pid()
  begin
    pid = open("tmp/pids/dango.#{ENV['RAILS_ENV']}.pid", "rb"){|fh| fh.read }.to_i
  rescue
    pid = nil
  end
  puts_verbose "pid=#{pid.inspect}"
  pid
end

#get_trouble_status(config, pid = nil) ⇒ Object

落ちた時の情報収集処理



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/dango/tasks/dango_rake.rb', line 223

def get_trouble_status(config, pid = nil)
  # フォルダ作成

  time_str = Time.now.strftime('%Y%m%d_%H%M%S')
  dir_name = "log/#{time_str}_#{ENV['RAILS_ENV']}"
  FileUtils.mkdir(dir_name) rescue nil
  
  # サーバーログの保管

  old_file = config['server']['log_file'].to_s
  if File.file?(old_file)
    new_file = "#{dir_name}/#{File.basename(old_file)}"
    puts_verbose "copy #{old_file} #{new_file}"
    FileUtils.copy(old_file, new_file) rescue nil
  end
  
  # 接続ログの保管

  if File.file?(CheckConnectLogFile)
    new_file = "#{dir_name}/#{File.basename(CheckConnectLogFile)}"
    puts_verbose "copy #{CheckConnectLogFile} #{new_file}"
    FileUtils.copy(CheckConnectLogFile, new_file) rescue nil
  end
  
  # スレッド情報と排他処理情報収集

  begin
    open("#{dir_name}/thread_status.txt", "wb") do |fh|
      
      fh.puts "==== log"
      fh.puts log
      
      fh.puts "==== get_process_info"
      fh.puts get_process_info(pid)
      
      fh.puts "==== get_server_info"
      fh.puts drb_call(:_monitor_get_server_info).pretty_inspect
      
      fh.puts "==== thread_list"
      fh.puts drb_call(:_monitor_thread_status).pretty_inspect
      
      fh.puts "==== mutex_list"
      fh.puts drb_call(:_monitor_mutex_status).pretty_inspect
      
      fh.puts "==== get_socket_list"
      fh.puts drb_call(:_monitor_get_socket_list).pretty_inspect
      
      fh.puts "==== get_shared"
      fh.puts drb_call(:_monitor_get_shared).pretty_inspect
      
    end
  rescue Exception
    puts_verbose "failed get thread_status."
  end
  
  # モード変更

  FileUtils.chmod_R(0777, [dir_name]) rescue nil
  
  # ファイルの圧縮

  begin
    require "zip/zip"
    can_zip = true
  rescue LoadError
    can_zip = false
  end
  
  if can_zip
    outzipfile = "log/#{time_str}_#{ENV['RAILS_ENV']}.zip"
    
    files = []
    Find.find(dir_name) do |filename|
      if FileTest::readable?(filename) and FileTest::file?(filename)
        files.push(filename)
      end
    end
    
    Zip::ZipOutputStream.open(outzipfile) do |zos|
      files.each do |name|
        zos.put_next_entry(name)
        File.open(name, "rb"){|f| zos.puts(f.read) }
      end
    end
    
    FileUtils.rm_f(files) rescue nil
    FileUtils.remove_entry(dir_name, true) rescue nil
    
    FileUtils.chmod_R(0666, [outzipfile]) rescue nil
  end
  
end

#puts_noverbose(str) ⇒ Object

出力+ログ



30
31
32
33
# File 'lib/dango/tasks/dango_rake.rb', line 30

def puts_noverbose(str)
  @log += "#{Time.now_to_s} #{str.to_s}\n"
  puts str.to_s
end

#puts_verbose(str) ⇒ Object

出力+ログ(verbose)



36
37
38
39
# File 'lib/dango/tasks/dango_rake.rb', line 36

def puts_verbose(str)
  @log += "#{Time.now_to_s} #{str.to_s}\n"
  puts str.to_s if $is_verbose
end

#stop_process(pid) ⇒ Object

プロセス停止



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/dango/tasks/dango_rake.rb', line 92

def stop_process(pid)
  puts_verbose "stop process (pid=#{pid})"
  
  if RUBY_PLATFORM == 'i386-mswin32'
    # WbemからProcessIDを取得

    require "win32ole"
    begin
      n_locator = WIN32OLE.new("WbemScripting.SWbemLocator.1")
      n_service = n_locator.ConnectServer
    rescue
      puts_verbose "failed connect to Wbem:#{$!.inspect}"
      return
    end
    
    set = n_service.ExecQuery("select Caption, name, ProcessID from Win32_Process where ProcessID = '#{pid}'")
    set.each do |process|
      puts_verbose "stopping #{process.Caption} #{process.name} #{process.ProcessID}"
      process.Terminate 0
    end
    
  else ## i386-mswin32以外

#    system("kill #{pid}")

    ret_kill = Process.kill("TERM", pid) rescue nil
    puts_verbose "kill TERM ret_kill=#{ret_kill.inspect}"
    
    
    # きちんと落ちたかチェック

    is_kill = false
    20.times do
      sleep 1
      if !File.exist?("/proc/#{pid}")
        is_kill = true
        break
      end
    end
    
    if !is_kill # 落ちていなければ、-9で終了

#      system("kill -9 #{pid}")

      begin
        Process.kill("KILL", pid)
      rescue
        puts_verbose "process pid(#{pid}) is exist. but failed kill -9 #{pid}"
      end
    end
  end
end