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

r175:29d3adfcaa1c - - 3 files changed: 17 inserted, 3 deleted

@@ -12,173 +12,178
12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 end
14 end
15
15
16 def clear_stopfile
16 def clear_stopfile
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 File.delete(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 File.delete(File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 end
19 end
20 end
20 end
21
21
22 def config
22 def config
23 Grader::Configuration.get_instance
23 Grader::Configuration.get_instance
24 end
24 end
25
25
26 def log_file_name
26 def log_file_name
27 if !File.exists?(config.log_dir)
27 if !File.exists?(config.log_dir)
28 raise "Log directory does not exist: #{config.log_dir}"
28 raise "Log directory does not exist: #{config.log_dir}"
29 end
29 end
30 config.log_dir +
30 config.log_dir +
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
31 "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 end
32 end
33
33
34 def log(str)
34 def log(str)
35 if config.talkative
35 if config.talkative
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."
89 puts "You should remove it manually later."
92 puts "You should remove it manually later."
90 else
93 else
91 (1..ARGV.length-1).each do |i|
94 (1..ARGV.length-1).each do |i|
92 stop_grader(ARGV[i])
95 stop_grader(ARGV[i])
93 end
96 end
94 puts "stop file(s) created"
97 puts "stop file(s) created"
95 end
98 end
96 exit(0)
99 exit(0)
97 end
100 end
98
101
99 # Check stop file.
102 # Check stop file.
100 if check_stopfile
103 if check_stopfile
101 puts "Stop file exists. Terminated."
104 puts "Stop file exists. Terminated."
102 clear_stopfile
105 clear_stopfile
103 exit(0)
106 exit(0)
104 end
107 end
105
108
106 #default options
109 #default options
107 options = {
110 options = {
108 :mode => 'queue',
111 :mode => 'queue',
109 :environment => 'exam',
112 :environment => 'exam',
110 :dry_run => false,
113 :dry_run => false,
111 }
114 }
112
115
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
161 after_save_hook(submission, grading_result)
166 after_save_hook(submission, grading_result)
162 end
167 end
163
168
164 def print_report_by_user
169 def print_report_by_user
165 puts "---------------------"
170 puts "---------------------"
166 puts " REPORT"
171 puts " REPORT"
167 puts "---------------------"
172 puts "---------------------"
168
173
169 print "login,email"
174 print "login,email"
170 @problems.each_value do |problem|
175 @problems.each_value do |problem|
171 print ",#{problem.name}"
176 print ",#{problem.name}"
172 end
177 end
173 print "\n"
178 print "\n"
174
179
175 @users.each_value do |user|
180 @users.each_value do |user|
176 print "#{user.login},#{user.email}"
181 print "#{user.login},#{user.email}"
177 @problems.each_value do |problem|
182 @problems.each_value do |problem|
178 if @results.has_key? [user.id, problem.id]
183 if @results.has_key? [user.id, problem.id]
179 print ",#{@results[[user.id,problem.id]][:points]}"
184 print ",#{@results[[user.id,problem.id]][:points]}"
180 else
185 else
181 print ","
186 print ","
182 end
187 end
183 end
188 end
184 print "\n"
189 print "\n"
@@ -375,85 +380,92
375 rescue ActiveRecord::RecordNotFound
380 rescue ActiveRecord::RecordNotFound
376 puts "Submission #{sub_id} not found"
381 puts "Submission #{sub_id} not found"
377 submission = nil
382 submission = nil
378 end
383 end
379
384
380 if submission!=nil
385 if submission!=nil
381 runner.grade_submission(submission)
386 runner.grade_submission(submission)
382 end
387 end
383 end
388 end
384 end
389 end
385
390
386 #########################################
391 #########################################
387 # main program
392 # main program
388 #########################################
393 #########################################
389
394
390 options = process_options_and_stop_file
395 options = process_options_and_stop_file
391 GRADER_ENV = options[:environment]
396 GRADER_ENV = options[:environment]
392 grader_mode = options[:mode]
397 grader_mode = options[:mode]
393 dry_run = options[:dry_run]
398 dry_run = options[:dry_run]
394
399
395 puts "environment: #{GRADER_ENV}"
400 puts "environment: #{GRADER_ENV}"
396 puts "grader mode: #{grader_mode}"
401 puts "grader mode: #{grader_mode}"
397 require File.join(File.dirname(__FILE__),'config/environment')
402 require File.join(File.dirname(__FILE__),'config/environment')
398
403
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"
447 grader_grade_contests(grader_proc, options)
459 grader_grade_contests(grader_proc, options)
448
460
449 when "sub"
461 when "sub"
450 grader_grade_submissions(grader_proc, options)
462 grader_grade_submissions(grader_proc, options)
451
463
452 when "autonew"
464 when "autonew"
453 grader_autonew_loop(grader_proc, options)
465 grader_autonew_loop(grader_proc, options)
454
466
455 else
467 else
456 display_manual
468 display_manual
457 exit(0)
469 exit(0)
458 end
470 end
459
471
@@ -73,98 +73,100
73 # puts "PROBLEM DIR: #{problem_home}"
73 # puts "PROBLEM DIR: #{problem_home}"
74
74
75 if !FileTest.exist?(problem_home)
75 if !FileTest.exist?(problem_home)
76 puts "PROBLEM DIR: #{problem_home}"
76 puts "PROBLEM DIR: #{problem_home}"
77 raise "engine: No test data."
77 raise "engine: No test data."
78 end
78 end
79
79
80 dinit = DirInit::Manager.new(problem_home)
80 dinit = DirInit::Manager.new(problem_home)
81
81
82 dinit.setup do
82 dinit.setup do
83 copy_log = copy_script(problem_home)
83 copy_log = copy_script(problem_home)
84 save_copy_log(problem_home,copy_log)
84 save_copy_log(problem_home,copy_log)
85 end
85 end
86
86
87 call_judge(problem_home,language,grading_dir,source_name)
87 call_judge(problem_home,language,grading_dir,source_name)
88
88
89 @reporter.report(submission,"#{grading_dir}/test-result")
89 @reporter.report(submission,"#{grading_dir}/test-result")
90
90
91 dinit.teardown do
91 dinit.teardown do
92 copy_log = load_copy_log(problem_home)
92 copy_log = load_copy_log(problem_home)
93 clear_copy_log(problem_home)
93 clear_copy_log(problem_home)
94 clear_script(copy_log,problem_home)
94 clear_script(copy_log,problem_home)
95 end
95 end
96
96
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
147 end
149 end
148
150
149 return copied
151 return copied
150 end
152 end
151
153
152 def copy_log_filename(problem_home)
154 def copy_log_filename(problem_home)
153 return File.join(problem_home, '.scripts_copied')
155 return File.join(problem_home, '.scripts_copied')
154 end
156 end
155
157
156 def save_copy_log(problem_home, log)
158 def save_copy_log(problem_home, log)
157 f = File.new(copy_log_filename(problem_home),"w")
159 f = File.new(copy_log_filename(problem_home),"w")
158 log.each do |fname|
160 log.each do |fname|
159 f.write("#{fname}\n")
161 f.write("#{fname}\n")
160 end
162 end
161 f.close
163 f.close
162 end
164 end
163
165
164 def load_copy_log(problem_home)
166 def load_copy_log(problem_home)
165 f = File.new(copy_log_filename(problem_home),"r")
167 f = File.new(copy_log_filename(problem_home),"r")
166 log = []
168 log = []
167 f.readlines.each do |line|
169 f.readlines.each do |line|
168 log << line.strip
170 log << line.strip
169 end
171 end
170 f.close
172 f.close
@@ -1,67 +1,67
1 #
1 #
2 # A runner drives the engine into various tasks.
2 # A runner drives the engine into various tasks.
3 #
3 #
4
4
5 module Grader
5 module Grader
6
6
7 class Runner
7 class Runner
8
8
9 def initialize(engine, grader_process=nil)
9 def initialize(engine, grader_process=nil)
10 @engine = engine
10 @engine = engine
11 @grader_process = grader_process
11 @grader_process = grader_process
12 end
12 end
13
13
14 def grade_oldest_task
14 def grade_oldest_task
15 task = Task.get_inqueue_and_change_status(Task::STATUS_GRADING)
15 task = Task.get_inqueue_and_change_status(Task::STATUS_GRADING)
16 if task!=nil
16 if task!=nil
17 @grader_process.report_active(task) if @grader_process!=nil
17 @grader_process.report_active(task) if @grader_process!=nil
18
18
19 submission = Submission.find(task.submission_id)
19 submission = Submission.find(task.submission_id)
20 @engine.grade(submission)
20 @engine.grade(submission)
21 task.status_complete!
21 task.status_complete!
22 @grader_process.report_inactive(task) if @grader_process!=nil
22 @grader_process.report_inactive(task) if @grader_process!=nil
23 end
23 end
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