diff options
Diffstat (limited to 'Master/texmf-dist/scripts/context/ruby/wwwwatch.rb')
-rw-r--r-- | Master/texmf-dist/scripts/context/ruby/wwwwatch.rb | 497 |
1 files changed, 0 insertions, 497 deletions
diff --git a/Master/texmf-dist/scripts/context/ruby/wwwwatch.rb b/Master/texmf-dist/scripts/context/ruby/wwwwatch.rb deleted file mode 100644 index 0faa45aec44..00000000000 --- a/Master/texmf-dist/scripts/context/ruby/wwwwatch.rb +++ /dev/null @@ -1,497 +0,0 @@ -#!/usr/bin/env ruby - -banner = ['WWWWatch', 'version 1.0.0', '2003-2006', 'PRAGMA ADE/POD'] - -$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq! - -require 'base/switch' -require 'base/logger' - -require 'www/common' - -require 'monitor' -require 'fileutils' -require 'ftools' -require 'tempfile' -require 'timeout' -require 'thread' - -class Watch < Monitor - - include Common - - @@session_prefix = '' - @@check_factor = 4 - @@process_timeout = 1*60*60 - @@fast_wait_loop = false - - @@session_line = /^\s*(?![\#\%])(.*?)\s*\=\s*(.*?)\s*$/o - @@session_begin = 'begin exa session' - @@session_end = 'end exa session' - - attr_accessor :root_path, :work_path, :create, :cache_path, :delay, :max_threads, :max_age, :verbose - - def initialize(logger) # we need to register all @vars here becase of the monitor - @threads = Hash.new - @files = Array.new - @stats = Hash.new - @skips = Hash.new - @root_path = '' - @work_path = Dir.tmpdir - @cache_path = @work_path - @last_action = Time.now - @delay = 1 - @max_threads = 5 - @max_age = @@process_timeout - @logger = logger - @verbose = false - @create = false - @onlyonerun = false - # [:INT, :TERM, :EXIT].each do |signal| - # trap(signal) do - # kill - # exit # rescue false - # end - # end - # at_exit do - # kill - # end - end - - def trace - if @verbose && @logger then - @logger.report("exception: #{$!})") - $@.each do |t| - @logger.report(">> #{t}") - end - end - end - - def report(str) - @logger.report(str) if @logger - end - - def setup - @threads = Hash.new - @files = Array.new - @stats = Hash.new - @skips = Hash.new - @root_path = File.expand_path(File.join(File.dirname(Dir.pwd),'.')) if @root_path.empty? - @work_path = File.expand_path(File.join(@root_path,'work','watch')) if @work_path.empty? - # @cache_path = File.expand_path(File.join(@root_path,'work','cache')) if @cache_path.empty? - @cache_path = File.expand_path(File.join(File.dirname(@work_path),'cache')) if @cache_path.empty? - if @create then - begin File.makedirs(@work_path) ; rescue ; end - begin File.makedirs(@cache_path) ; rescue ; end - end - unless File.writable?(@work_path) then - @work_path = File.expand_path(File.join(Dir.tmpdir,'work','watch')) - if @create then - begin File.makedirs(@work_path) ; rescue ; end - end - end - unless File.writable?(@cache_path) then - @cache_path = File.expand_path(File.join(Dir.tmpdir,'work','cache')) - if @create then - begin File.makedirs(@cache_path) ; rescue ; end - end - end - unless File.writable?(@work_path) then - puts "no valid work path: #{@work_path}" - exit! rescue false # no checking, no at_exit done - end - unless File.writable?(@cache_path) then - puts "no valid cache path: #{@cache_path}" ; # no reason to exit - end - @last_action = Time.now - report("watching path #{@work_path}") if @verbose - end - - def lock(lck) - begin - report("watchdog: locking #{lck}") if @verbose - File.open(lck,'w') do |f| - f << Time.now - end - rescue - trace - end - end - - def unlock(lck) - begin - report("watchdog: unlocking #{lck}") if @verbose - File.delete(lck) - rescue - trace - end - end - - def kill - @threads.each do |t| - t.kill rescue false - end - end - - def restart - @files = Array.new - @skips = Hash.new - @stats = Hash.new - kill # threads - end - - def collect - begin - @files = Array.new - Dir.glob("#{@work_path}/#{@@session_prefix}*.ses").each do |sessionfile| - sessionfile = File.expand_path(sessionfile) - begin - if @threads.key?(sessionfile) then - # leave alone - elsif (Time.now - File.mtime(sessionfile)) > @max_age.to_i then - # delete - FileUtils::rm_r(sessionfile) rescue false - FileUtils::rm_r(sessionfile.sub(/ses$/,'dir')) rescue false - FileUtils::rm_r(sessionfile.sub(/ses$/,'lck')) rescue false - begin - FileUtils::rm_r(File.join(@cache_path, File.basename(sessionfile.sub(/ses$/,'dir')))) - rescue - report("watchdog: problems in cache cleanup #{$!}") # if @verbose - end - @stats.delete(sessionfile) rescue false - @skips.delete(sessionfile) rescue false - report("watchdog: removing session #{sessionfile}") if @verbose - elsif ! @skips.key?(sessionfile) then - @files << sessionfile - report("watchdog: checking session #{sessionfile}") if @verbose - end - rescue - # maybe purged in the meantime - end - end - rescue - if File.directory?(@work_path) then - @files = Array.new - else - # maybe dir is deleted (manual cleanup) - restart - end - end - begin - Dir.glob("#{@cache_path}/*.dir").each do |dirname| - begin - if (Time.now - File.mtime(dirname)) > @max_age.to_i then - begin - FileUtils::rm_r(dirname) - rescue - report("watchdog: problems in cache cleanup #{$!}") # if @verbose - end - end - rescue - # maybe purged in the meantime - end - end - rescue - end - end - - def purge - begin - Dir.glob("#{@work_path}/#{@@session_prefix}*").each do |sessionfile| - sessionfile = File.expand_path(sessionfile) - begin - if (Time.now - File.mtime(sessionfile)) > @max_age.to_i then - begin - if FileTest.directory?(sessionfile) then - FileUtils::rm_r(sessionfile) - else - File.delete(sessionfile) - end - rescue - end - begin - @stats.delete(sessionfile) - @skips.delete(sessionfile) - rescue - end - report("watchdog: purging session #{sessionfile}") if @verbose - end - rescue - # maybe purged in the meantime - end - end - rescue - end - end - - def loaded_session_data(filename) - begin - if data = IO.readlines(filename) then - return data if (data.first =~ /^[\#\%]\s*#{@@session_begin}/o) && (data.last =~ /^[\#\%]\s*#{@@session_end}/o) - end - rescue - trace - end - return nil - end - - def load(sessionfile) - # we assume that we get an exception when the file is locked - begin - if data = loaded_session_data(sessionfile) then - report("watchdog: loading session #{sessionfile}") if @verbose - vars = Hash.new - data.each do |line| - begin - if line.chomp =~ /^(.*?)\s*\=\s*(.*?)\s*$/o then - key, value = $1, $2 - vars[key] = value - end - rescue - end - end - return vars - else - return nil - end - rescue - trace - return nil - end - end - - def save(sessionfile, vars) - begin - report("watchdog: saving session #{sessionfile}") if @verbose - if @stats.key?(sessionfile) then - @stats[sessionfile] = File.mtime(sessionfile) - elsif @stats[sessionfile] == File.mtime(sessionfile) then - else - # construct data first - str = "\# #{@@session_begin}\n" - for k,v in vars do - str << "#{k}=#{v}\n" - end - str << "\# #{@@session_end}\n" - # save as fast as possible - File.open(sessionfile,'w') do |f| - f.puts(str) - end - end - rescue - report("watchdog: unable to save session #{sessionfile}") if @verbose - trace - return false - else - return true - end - end - - def launch - begin - @files.each do |sessionfile| - if @threads.length < @max_threads then - begin - if ! @skips.key?(sessionfile) && (vars = load(sessionfile)) then - if (id = vars['id']) && vars['status'] then - if vars['status'] == 'running: background' then - @last_action = Time.now - @threads[sessionfile] = Thread.new(vars, sessionfile) do |vars, sessionfile| - begin - report("watchdog: starting thread #{sessionfile}") if @verbose - dir = File.expand_path(sessionfile.sub(/ses$/,'dir')) - lck = File.expand_path(sessionfile.sub(/ses$/,'lck')) - start_of_run = Time.now - start_of_job = start_of_run.dup - max_time = @max_age - begin - start_of_job = vars['starttime'].to_i || start_of_run - start_of_job = start_of_run if start_of_job == 0 - rescue - start_of_job = Time.now - end - begin - max_runtime = vars['maxtime'].to_i || @max_age - max_runtime = @max_age if max_runtime == 0 - max_runtime = max_runtime - (Time.now.to_i - start_of_job.to_i) - rescue - max_runtime = @max_age - end - lock(lck) - if max_runtime > 0 then - command = vars['command'] || '' - if ! command.empty? then - vars['status'] = 'running: busy' - vars['timeout'] = max_runtime.to_s - save(sessionfile,vars) - timeout(max_runtime) do - begin - command = command_string(dir,command,'process.log') - report("watchdog: #{command}") if @verbose - system(command) - rescue TimeoutError - vars['status'] = 'running: timeout' - rescue - trace - vars['status'] = 'running: aborted' - else - vars['status'] = 'running: finished' - vars['runtime'] = sprintf("%.02f",(Time.now - start_of_run)) - vars['endtime'] = Time.now.to_i.to_s - end - end - else - vars['status'] = 'running: aborted' # no command - end - else - vars['status'] = 'running: aborted' # not enough time - end - save(sessionfile,vars) - unlock(lck) - report("watchdog: ending thread #{sessionfile}") if @verbose - @threads.delete(sessionfile) - rescue - trace - end - end - else - report("watchdog: skipping - id (#{vars['id']}) / status (#{vars['status']})") if @verbose - end - if @onlyonerun then - @skips[sessionfile] = true - else - @skips.delete(sessionfile) - end - else - # not yet ok - end - else - # maybe a lock - end - rescue - trace - end - else - break - end - end - rescue - trace - end - end - - def wait - begin - # report(Time.now.to_s) if @verbose - loop do - @threads.delete_if do |k,v| - begin - v == nil || v.stop? - rescue - true - else - false - end - end - if @threads.length == @max_threads then - if @delay > @max_threads then - sleep(@delay) - else - sleep(@max_threads) - end - break if @@fast_wait_loop - else - sleep(@delay) - break - end - end - rescue - trace - end - end - - def check - begin - time = Time.now - if (time - @last_action) > @@check_factor*@max_age then - report("watchdog: cleanup") if @verbose - @stats = Hash.new - @last_action = time - kill - end - rescue - trace - end - end - - def cycle - loop do - begin - collect - launch - wait - check - rescue - trace - report("watchdog: some problem, restarting loop") - end - end - end - -end - -class Commands - - include CommandBase - - def watch - if watch = setup then - watch.cycle - else - report("provide valid work path") - end - end - def main - watch - end - - private - - def setup - if watch = Watch.new(logger) then - watch.root_path = @commandline.option('root') - watch.work_path = @commandline.option('work') - watch.cache_path = @commandline.option('cache') - watch.create = @commandline.option('create') - watch.verbose = @commandline.option('verbose') - begin - watch.max_threads = @commandline.option('threads').to_i - rescue - watch.max_threads = 5 - end - watch.setup - end - return watch - end - -end - -logger = Logger.new(banner.shift) -commandline = CommandLine.new - -commandline.registervalue('root', '') -commandline.registervalue('work', '') -commandline.registervalue('cache', '') -commandline.registervalue('threads', '5') - -commandline.registerflag('create') - -commandline.registeraction('watch', '[--work=path] [--root=path] [--create]') - -commandline.registerflag('verbose') -commandline.registeraction('help') -commandline.registeraction('version') - -commandline.expand - -Commands.new(commandline,logger,banner).send(commandline.action || 'main') |