Class: Sixconfig

Inherits:
ActiveRecord::Base show all
Defined in:
lib/six-updater-web/app/models/sixconfig.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ActiveRecord::Base

#associated_valid?, #no_errors_in_associated?, #save_associated, #save_associated!, #save_with_unsaved_flag, #to_label, #unsaved=, #unsaved?

Class Method Details

.backtrace(e, log) ⇒ Object



153
154
155
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 153

def self.backtrace(e, log)
  log.info "ERROR!!! #{e.class}: #{e.message} #{e.backtrace.join("\n")}"
end

.execObject



157
158
159
160
161
162
163
164
165
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 157

def self.exec
  # Dirty workaround for Windows six-updater.rb inside BASE_PATH will take precedence over ruby\bin\six-updater(.bat)
  case RUBY_PLATFORM
    when /-mingw32$/, /-mswin32$/
      "six-updater.bat"
    else
      "six-updater"
  end
end

.process_msg(msg, messages, ses, previous_r = nil) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 180

def self.process_msg(msg, messages, ses, previous_r = nil)
  # Create new logentry when no previous_r is found
  entry = previous_r ? previous_r : Log.new(:logsession_id => ses)
  entry.content = msg
  #p [msg, entry]

  # Set new previous_r unless last message had return
  previous_r = msg[/\n$/] ? nil : entry #&& ! msg[/.+\r\n$/]

  messages << entry unless messages.include?(entry)
  previous_r
end

.start_updater(cl) ⇒ Object



176
177
178
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 176

def self.start_updater(cl)
  SixUpdaterWeb.run_program(self.exec, SixUpdaterWeb::BASE_PATH, cl)
end

.start_updater_inweb(cli) ⇒ Object

TODO: FIXME, Can’t run this in development atm!



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
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
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 197

def self.start_updater_inweb(cli)
  logger.info "Starting #{exec} with #{cli} from #{SixUpdaterWeb::BASE_PATH}"

  ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
  Thread.new(cli, logger) do |cl, log|
    Dir.chdir SixUpdaterWeb::BASE_PATH do |dir|
      # Setup session
      ses = Logsession.new
      ses.save
      ses = ses.id # Workaround for some issue with throwing around this record, in development mode.
      messages, buff = [], []
      shebang = nil
      found_r, previous_r = nil, nil
      status = nil
      cmd = case RUBY_PLATFORM
        when /-mingw32$/, /-mswin32$/
          "ruby \"#{File.join(RAILS_ROOT, "lib", "wrapper.rb")}\" #{exec} #{cl}"
        else
          "#{exec} #{cl}"
      end
      
      begin
        status = IO.popen(cmd) do |io_out| #Open3.popen3("#{exec} #{cl}") do |io_in, io_out, io_err, waitth|
          previous = Time.now
          #io_in.close
          io_out.sync = true
          io_out.each_byte do |b|
            begin
              char = b.chr
              case RUBY_PLATFORM
                when /-mingw32$/, /-mswin32$/
                  if found_r
                    # Found \r
                    found_r = false
                    if ["\n"].include?(char)
                      # Line ending: Add to buffer, then process it
                      buff << char
                      msg = buff.join("")
                      buff = []
                      if msg =~ /^SIX-SHEBANG: /
                        shebang = msg
                      else
                        previous_r = process_msg(msg, messages, ses, previous_r)
                      end
                    else
                      # Other char; Process buffer, then add it to a new buffer
                      msg = buff.join("")
                      buff = []
                      if msg =~ /^SIX-SHEBANG: /
                        shebang = msg
                      else
                        previous_r = process_msg(msg, messages, ses, previous_r)
                      end
                      found_r = true if ["\r"].include?(char)
                      buff << char
                    end
                  else
                    # Default processing
                    buff << char
                    case char
                      when "\r"
                        found_r = true
                      when "\n"
                        msg = buff.join("")
                        buff = []
                        if msg =~ /^SIX-SHEBANG: /
                          shebang = msg
                        else
                          previous_r = process_msg(msg, messages, ses, previous_r)
                        end
                    end
                  end
                else
                  # Default processing
                  buff << char
                  if ["\r","\n"].include?(char)
                    msg = buff.join("")
                    buff = []
                    #if msg =~ /^SIX-SHEBANG: /
                    #  shebang = msg
                    #else
                      previous_r = process_msg(msg, messages, ses, previous_r)
                    #end
                  end                    
              end
            rescue => e
              backtrace(e, log)
            end
            unless messages.empty?
              # Write the messages buffer to database
              # only check every 2 seconds
              if Time.now - previous > 2
                previous = Time.now
                done = []
                messages.uniq!
                begin
                  messages.each {|msg| msg.save; done << msg}
                rescue => e
                  backtrace(e, log)
                end
                messages -= done
              end
            end
          end
          #status = waitth.value
        end
      rescue => e
        backtrace(e, log)
      end

      pid, status = nil, 1
      case RUBY_PLATFORM
        when /-mingw32$/, /-mswin32$/
          # Handle last bits in the buffer
          unless buff.empty?
            msg = buff.join("")
            if msg =~ /^SIX-SHEBANG: /
              shebang = msg
            else
              previous_r = process_msg(msg, messages, ses, previous_r)
            end
          end

          # Handle status and pid
          if shebang
            if shebang[/^SIX-SHEBANG: (-?.*), (-?.*)/]
              pid = $1.to_i if $1
              status = $2.to_i if $2
            end
          end
        else
          # Handle last bits in the buffer
          unless buff.empty?
            msg = buff.join("")
            previous_r = process_msg(msg, messages, ses, previous_r)
          end

          # Handle status and pid
          pid, status = $?.pid, $?.exitstatus
      end

      if status > 0
        messages << Log.new(:logsession_id => ses, :content => "Abnormal program termination. #{pid}: #{status}")
      else
        messages << Log.new(:logsession_id => ses, :content => "Normal program termination. #{pid}: #{status}")
      end

      unless messages.empty?
        i = 0; done = false
        until done || i > 3
          i += 1
          begin
            messages.each {|msg| msg.save}
            done = true
          rescue => e
            backtrace(e, log)
            sleep 2
          end
        end
      end
    end
    ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
  end
  sleep 2
end

Instance Method Details

#all_mods(srv = self.get_server, setting = Appsetting.new) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 17

def all_mods(srv = self.get_server, setting = Appsetting.new)
  m = []
  m += srv.mods if srv
  self.mods.each { |mod| m << mod unless m.include?(mod) }
  if setting.beta
    t = setting.found_type
    if t
      t::DEFAULT_BETA_MODS.each do |mf|
        mod = Mod.find_by_name(mf)
        next unless mod
        m << mod unless m.include?(mod)
      end
    end
  end
  m.each {|mod| if (mod.new_record? && !mod.exists?(self.appsetting)); mod.disabled = true; end }
  ms = []
  m.each {|mod| ms += mod.all_dependentmods; ms << mod } 
  ms.uniq
end

#auto_skip_status(setting_override = false, server_override = nil, force = false) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 93

def auto_skip_status(setting_override = false, server_override = nil, force = false)
  setting = if setting_override
    setting_override
  else
    self.appsetting
  end
  srv = if server_override
    server_override
  else
    self.get_server
  end

  setting = Appsetting.new unless setting

  self.all_mods(srv, setting).each do |mod|
    if force
      mod.skip = false
    else
      mod.update_version(setting.real_modpath)
      mod.update_skip
    end
    mod.save
  end
end

#clear_skip_status(server_override = nil) ⇒ Object



67
68
69
70
71
72
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 67

def clear_skip_status(server_override = nil)
  self.all_mods(server_override).each do |mod|
    mod.skip = false
    mod.save
  end
end

#execObject



37
38
39
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 37

def exec
  ""
end

#execute(action, setting, server, autoskip, inweb) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 41

def execute(action, setting, server, autoskip, inweb)
  #self.auto_skip_status(setting, server, false) if autoskip
  h = self.output_yml(setting, server)

  cl = ""

  if action
    action.tasks.each do |task|
      cl += " --#{task}" unless task == "Default"
    end
  end

  if inweb
    Sixconfig.start_updater_inweb(cl)
    return h
  end

  case RUBY_PLATFORM
    when /-mingw32$/, /-mswin32$/
      cl += " --wait"
  end

  Sixconfig.start_updater(cl)
  h
end

#from_updater_yml(yml) ⇒ Object



11
12
13
14
15
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 11

def from_updater_yml(yml)
  yml.each_pair do |key, value|
    
  end
end

#get_serverObject



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 75

def get_server
  if self.queryserver.nil?
    if self.server.nil?
      return nil
    else
      begin
        self.server
      rescue
      end
    end
  else
    begin
      self.queryserver
    rescue
    end
  end
end

#imp(setting = Appsetting.new) ⇒ Object



167
168
169
170
171
172
173
174
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 167

def imp(setting = Appsetting.new)
  Mod.find(:all).each do |mod|
    mod.update_version(setting.real_path)
    mod.save if mod.changed?
    next unless mod.installed?
    self.mods << mod unless self.mods.include?(mod)
  end
end

#output_yml(setting = nil, server = nil) ⇒ Object



118
119
120
121
122
123
124
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 118

def output_yml(setting = nil, server = nil)
  yml = self.to_updater_yml(setting, server)
  File.open(File.join(SixUpdaterWeb::DATA_PATH, 'six-updater.yml'), 'w') do |file|
    file.puts yml.to_yaml
  end
  yml
end

#to_updater_yml(setting_override = nil, server_override = nil) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/six-updater-web/app/models/sixconfig.rb', line 126

def to_updater_yml(setting_override = nil, server_override = nil)
  setting = if setting_override
    setting_override
  else
    self.appsetting
  end

  srv = if server_override
    server_override
  else
    self.get_server
  end

  setting = Appsetting.new unless setting
  hash = setting.to_updater_yml
  hash[:folders] = []

  self.all_mods(srv, setting).each do |mod|
    y = mod.to_updater_yml
    hash[:folders] << y unless hash[:folders].include?(y)
  end

  hash[:server] = srv.to_updater_yml if srv

  hash
end