Description:
add more logging
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r174:09d1e857c1e3 - - 3 files changed: 17 inserted, 3 deleted

@@ -36,53 +36,56
36 puts str
36 puts str
37 end
37 end
38 if config.logging
38 if config.logging
39 fp = File.open(log_file_name,"a")
39 fp = File.open(log_file_name,"a")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 fp.close
41 fp.close
42 end
42 end
43 end
43 end
44
44
45 def display_manual
45 def display_manual
46 puts <<USAGE
46 puts <<USAGE
47 Grader.
47 Grader.
48 using: (1) grader
48 using: (1) grader
49 (2) grader environment [mode] [options]
49 (2) grader environment [mode] [options]
50 (3) grader stop [all|pids-list]
50 (3) grader stop [all|pids-list]
51 (4) grader --help
51 (4) grader --help
52 (1) call grader with environment = 'exam', mode = 'queue'
52 (1) call grader with environment = 'exam', mode = 'queue'
53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
54 queue: repeatedly check the task queue and grade any available tasks
54 queue: repeatedly check the task queue and grade any available tasks
55
55
56 prob: re-grade every user latest submission of the specific problem.
56 prob: re-grade every user latest submission of the specific problem.
57 the problem name must be specified by the next argument.
57 the problem name must be specified by the next argument.
58
58
59 additional options:
59 additional options:
60 + --all-sub re-grade every submissions instead of just the latest submission of each user.
60
61
61 - --all-sub re-grade every submissions instead of just the latest submission of each user.
62 sub: re-grader the specified submission.
62 sub: re-grader the specified submission.
63 The submission ID to be re-graded must be specified by the next argument.
63 The submission ID to be re-graded must be specified by the next argument.
64
64
65 + options:
66 + --err-log log error to a file in the log dir
67 +
65 (3) create stop-file to stop running grader in queue mode
68 (3) create stop-file to stop running grader in queue mode
66 (4) You are here.
69 (4) You are here.
67 USAGE
70 USAGE
68 end
71 end
69
72
70 def process_options_and_stop_file
73 def process_options_and_stop_file
71 # The list of options are:
74 # The list of options are:
72 # - stop [all|process ids]
75 # - stop [all|process ids]
73 # -
76 # -
74
77
75 # Process 'help' option
78 # Process 'help' option
76 if (ARGV.length==1) and (/help/.match(ARGV[0]))
79 if (ARGV.length==1) and (/help/.match(ARGV[0]))
77 display_manual
80 display_manual
78 exit(0)
81 exit(0)
79 end
82 end
80
83
81 # Process 'stop' option.
84 # Process 'stop' option.
82 if (ARGV.length >= 1) and (ARGV[0]=='stop')
85 if (ARGV.length >= 1) and (ARGV[0]=='stop')
83 if ARGV.length==1
86 if ARGV.length==1
84 puts "you should specify pid-list or 'all'"
87 puts "you should specify pid-list or 'all'"
85 display_manual
88 display_manual
86 elsif (ARGV.length==2) and (ARGV[1]=='all')
89 elsif (ARGV.length==2) and (ARGV[1]=='all')
87 stop_grader(:all)
90 stop_grader(:all)
88 puts "A global stop file ('stop.all') created."
91 puts "A global stop file ('stop.all') created."
@@ -113,48 +116,50
113 # Process mode and environment option
116 # Process mode and environment option
114 if ARGV.length >= 1
117 if ARGV.length >= 1
115 options[:environment] = ARGV.shift
118 options[:environment] = ARGV.shift
116 if ARGV.length >=1
119 if ARGV.length >=1
117 options[:mode] = ARGV.shift
120 options[:mode] = ARGV.shift
118 end
121 end
119 else
122 else
120 puts 'no argument specified, using default mode and environment.'
123 puts 'no argument specified, using default mode and environment.'
121 end
124 end
122
125
123 options[:dry_run] = (ARGV.delete('--dry') != nil)
126 options[:dry_run] = (ARGV.delete('--dry') != nil)
124 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
127 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
125 puts "Dry run currently works only for 'prob' or 'contest' modes."
128 puts "Dry run currently works only for 'prob' or 'contest' modes."
126 exit(0)
129 exit(0)
127 end
130 end
128
131
129 options[:report] = (ARGV.delete('--report') != nil)
132 options[:report] = (ARGV.delete('--report') != nil)
130 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
133 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
131 puts "Report currently works only for 'prob' or 'contest' modes."
134 puts "Report currently works only for 'prob' or 'contest' modes."
132 exit(0)
135 exit(0)
133 end
136 end
134
137
135 options[:all_sub] = (ARGV.delete('--all-sub') != nil)
138 options[:all_sub] = (ARGV.delete('--all-sub') != nil)
136
139
140 + options[:err_log] = (ARGV.delete('--err-log') != nil)
141 +
137 return options
142 return options
138 end
143 end
139
144
140 class ResultCollector
145 class ResultCollector
141 def initialize
146 def initialize
142 @results = {}
147 @results = {}
143 @problems = {}
148 @problems = {}
144 @users = {}
149 @users = {}
145 end
150 end
146
151
147 def after_save_hook(submission, grading_result)
152 def after_save_hook(submission, grading_result)
148 end
153 end
149
154
150 def save(submission, grading_result)
155 def save(submission, grading_result)
151 user = submission.user
156 user = submission.user
152 problem = submission.problem
157 problem = submission.problem
153 if not @problems.has_key? problem.id
158 if not @problems.has_key? problem.id
154 @problems[problem.id] = problem
159 @problems[problem.id] = problem
155 end
160 end
156 if not @users.has_key? user.id
161 if not @users.has_key? user.id
157 @users[user.id] = user
162 @users[user.id] = user
158 end
163 end
159 @results[[user.id, problem.id]] = grading_result
164 @results[[user.id, problem.id]] = grading_result
160
165
@@ -399,48 +404,55
399 # add grader_mode to config
404 # add grader_mode to config
400 # this is needed because method log needs it. TODO: clean this up
405 # this is needed because method log needs it. TODO: clean this up
401 class << config
406 class << config
402 attr_accessor :grader_mode
407 attr_accessor :grader_mode
403 end
408 end
404 config.grader_mode = grader_mode
409 config.grader_mode = grader_mode
405
410
406 # reading rails environment
411 # reading rails environment
407 log 'Reading rails environment'
412 log 'Reading rails environment'
408
413
409 RAILS_ENV = config.rails_env
414 RAILS_ENV = config.rails_env
410 require RAILS_ROOT + '/config/environment'
415 require RAILS_ROOT + '/config/environment'
411
416
412 # register grader process
417 # register grader process
413 if config.report_grader
418 if config.report_grader
414 grader_proc = GraderProcess.register(config.grader_hostname,
419 grader_proc = GraderProcess.register(config.grader_hostname,
415 Process.pid,
420 Process.pid,
416 grader_mode)
421 grader_mode)
417 else
422 else
418 grader_proc = nil
423 grader_proc = nil
419 end
424 end
420
425
421 #set loggin environment
426 #set loggin environment
422 ENV['GRADER_LOGGING'] = log_file_name
427 ENV['GRADER_LOGGING'] = log_file_name
428 + if options[:err_log]
429 + err_file_name = log_file_name + '.err'
430 + $stderr.reopen(err_file_name,"a")
431 + log "STDERR log to file [#{err_file_name}]"
432 + warn "start logging for grader PID #{Process.id} on #{Time.now.in_time_zone}"
433 + end
434 +
423
435
424 # register exit handler to report inactive, and terminated
436 # register exit handler to report inactive, and terminated
425 at_exit do
437 at_exit do
426 if grader_proc!=nil
438 if grader_proc!=nil
427 grader_proc.report_inactive
439 grader_proc.report_inactive
428 grader_proc.terminate
440 grader_proc.terminate
429 end
441 end
430 end
442 end
431
443
432 #
444 #
433 # MAIN LOOP
445 # MAIN LOOP
434 #
446 #
435
447
436 case grader_mode
448 case grader_mode
437 when "queue"
449 when "queue"
438 grader_queue_loop(grader_proc, options)
450 grader_queue_loop(grader_proc, options)
439
451
440 when "test_request"
452 when "test_request"
441 grader_test_request_loop(grader_proc, options)
453 grader_test_request_loop(grader_proc, options)
442
454
443 when "prob"
455 when "prob"
444 grader_grade_problems(grader_proc, options)
456 grader_grade_problems(grader_proc, options)
445
457
446 when "contest"
458 when "contest"
@@ -97,50 +97,52
97 rescue RuntimeError => msg
97 rescue RuntimeError => msg
98 @reporter.report_error(submission, msg)
98 @reporter.report_error(submission, msg)
99 puts "ERROR: #{msg}"
99 puts "ERROR: #{msg}"
100
100
101 ensure
101 ensure
102 @room_maker.clean_up(submission)
102 @room_maker.clean_up(submission)
103 Dir.chdir(current_dir) # this is really important
103 Dir.chdir(current_dir) # this is really important
104 end
104 end
105 end
105 end
106
106
107 protected
107 protected
108
108
109 def talk(str)
109 def talk(str)
110 if @config.talkative
110 if @config.talkative
111 puts str
111 puts str
112 end
112 end
113 end
113 end
114
114
115 def call_judge(problem_home,language,grading_dir,fname)
115 def call_judge(problem_home,language,grading_dir,fname)
116 ENV['PROBLEM_HOME'] = problem_home
116 ENV['PROBLEM_HOME'] = problem_home
117 ENV['RUBYOPT'] = ''
117 ENV['RUBYOPT'] = ''
118
118
119 talk grading_dir
119 talk grading_dir
120 Dir.chdir grading_dir
120 Dir.chdir grading_dir
121 - cmd = "#{problem_home}/script/judge #{language} #{fname}"
121 + script_name = "#{problem_home}/script/judge"
122 + cmd = "#{script_name} #{language} #{fname}"
122 talk "CMD: #{cmd}"
123 talk "CMD: #{cmd}"
124 + warn "ERROR: file does not exists #{script_name}" unless File.exists? script_name
123 system(cmd)
125 system(cmd)
124 end
126 end
125
127
126 def get_std_script_dir
128 def get_std_script_dir
127 GRADER_ROOT + '/std-script'
129 GRADER_ROOT + '/std-script'
128 end
130 end
129
131
130 def copy_script(problem_home)
132 def copy_script(problem_home)
131 script_dir = "#{problem_home}/script"
133 script_dir = "#{problem_home}/script"
132 std_script_dir = get_std_script_dir
134 std_script_dir = get_std_script_dir
133
135
134 raise "engine: std-script directory not found" if !FileTest.exist?(std_script_dir)
136 raise "engine: std-script directory not found" if !FileTest.exist?(std_script_dir)
135
137
136 scripts = Dir[std_script_dir + '/*']
138 scripts = Dir[std_script_dir + '/*']
137
139
138 copied = []
140 copied = []
139
141
140 scripts.each do |s|
142 scripts.each do |s|
141 fname = File.basename(s)
143 fname = File.basename(s)
142 next if FileTest.directory?(s)
144 next if FileTest.directory?(s)
143 if !FileTest.exist?("#{script_dir}/#{fname}")
145 if !FileTest.exist?("#{script_dir}/#{fname}")
144 copied << fname
146 copied << fname
145 FileUtils.cp(s, "#{script_dir}", :preserve => true)
147 FileUtils.cp(s, "#{script_dir}", :preserve => true)
146 end
148 end
@@ -24,44 +24,44
24 return task
24 return task
25 end
25 end
26
26
27 def grade_problem(problem, options={})
27 def grade_problem(problem, options={})
28 User.find_each do |u|
28 User.find_each do |u|
29 puts "user: #{u.login}"
29 puts "user: #{u.login}"
30 if options[:user_conditions]!=nil
30 if options[:user_conditions]!=nil
31 con_proc = options[:user_conditions]
31 con_proc = options[:user_conditions]
32 next if not con_proc.call(u)
32 next if not con_proc.call(u)
33 end
33 end
34 if options[:all_sub]
34 if options[:all_sub]
35 Submission.where(user_id: u.id,problem_id: problem.id).find_each do |sub|
35 Submission.where(user_id: u.id,problem_id: problem.id).find_each do |sub|
36 @engine.grade(sub)
36 @engine.grade(sub)
37 end
37 end
38 else
38 else
39 last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
39 last_sub = Submission.find_last_by_user_and_problem(u.id,problem.id)
40 if last_sub!=nil
40 if last_sub!=nil
41 @engine.grade(last_sub)
41 @engine.grade(last_sub)
42 end
42 end
43 end
43 end
44 end
44 end
45 end
45 end
46
46
47 def grade_submission(submission)
47 def grade_submission(submission)
48 - puts "Submission: #{submission.id} by #{submission.user.full_name}"
48 + puts "Submission: #{submission.id} by #{submission.try(:user).try(:full_name)}"
49 @engine.grade(submission)
49 @engine.grade(submission)
50 end
50 end
51
51
52 def grade_oldest_test_request
52 def grade_oldest_test_request
53 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
53 test_request = TestRequest.get_inqueue_and_change_status(Task::STATUS_GRADING)
54 if test_request!=nil
54 if test_request!=nil
55 @grader_process.report_active(test_request) if @grader_process!=nil
55 @grader_process.report_active(test_request) if @grader_process!=nil
56
56
57 @engine.grade(test_request)
57 @engine.grade(test_request)
58 test_request.status_complete!
58 test_request.status_complete!
59 @grader_process.report_inactive(test_request) if @grader_process!=nil
59 @grader_process.report_inactive(test_request) if @grader_process!=nil
60 end
60 end
61 return test_request
61 return test_request
62 end
62 end
63
63
64 end
64 end
65
65
66 end
66 end
67
67
You need to be logged in to leave comments. Login now