Description:
changed grader-batch to handle only batch tasks. git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@392 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r186:c74af5659ae2 - - 4 files changed: 288 inserted, 153 deleted

@@ -0,0 +1,217
1 + #!/usr/bin/ruby
2 +
3 + def stop_grader(id)
4 + if id==:all
5 + File.open(File.dirname(__FILE__) + "/stop.all",'w').close
6 + else
7 + File.open(File.dirname(__FILE__) + "/stop.#{id}",'w').close
8 + end
9 + end
10 +
11 + def check_stopfile
12 + FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 + FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 + end
15 +
16 + def clear_stopfile
17 + if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 + system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 + end
20 + end
21 +
22 + def config
23 + Grader::Configuration.get_instance
24 + end
25 +
26 + def log_file_name
27 + if !File.exists?(config.log_dir)
28 + raise "Log directory does not exist: #{config.log_dir}"
29 + end
30 + config.log_dir +
31 + "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 + end
33 +
34 + def log(str)
35 + if config.talkative
36 + puts str
37 + end
38 + if config.logging
39 + fp = File.open(log_file_name,"a")
40 + fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 + fp.close
42 + end
43 + end
44 +
45 + def display_manual
46 + puts <<USAGE
47 + Grader.
48 + using: (1) grader
49 + (2) grader environment [mode]
50 + (3) grader stop [all|pids-list]
51 + (4) grader --help
52 + (1) call grader with environment = 'exam', mode = 'queue'
53 + (2) possible modes are: 'queue', 'prob', 'test_request'
54 + (3) create stop-file to stop running grader in queue mode
55 + (4) You are here.
56 + USAGE
57 + end
58 +
59 + #########################################
60 + # main program
61 + #########################################
62 +
63 + # with --help
64 + if (ARGV.length==1) and (/help/.match(ARGV[0]))
65 + display_manual
66 + exit(0)
67 + end
68 +
69 + # reading environment and options
70 + if (ARGV.length >= 1) and (ARGV[0]=='stop')
71 + if ARGV.length==1
72 + puts "you should specify pid-list or 'all'"
73 + display_manual
74 + elsif (ARGV.length==2) and (ARGV[1]=='all')
75 + stop_grader(:all)
76 + puts "A global stop file ('stop.all') created."
77 + puts "You should remove it manually later."
78 + else
79 + (1..ARGV.length-1).each do |i|
80 + stop_grader(ARGV[i])
81 + end
82 + puts "stop file(s) created"
83 + end
84 + exit(0)
85 + end
86 +
87 + if check_stopfile
88 + puts "Stop file exists. Terminated."
89 + clear_stopfile
90 + exit(0)
91 + end
92 +
93 + grader_mode = 'queue'
94 + if ARGV.length >= 1
95 + GRADER_ENV = ARGV[0]
96 + if ARGV.length >=2
97 + grader_mode = ARGV[1]
98 + end
99 + else
100 + GRADER_ENV = 'exam'
101 + end
102 +
103 + puts "environment: #{GRADER_ENV}"
104 + require File.join(File.dirname(__FILE__),'config/environment')
105 +
106 + # add grader_mode to config
107 + # this is needed because method log needs it. TODO: clean this up
108 + class << config
109 + attr_accessor :grader_mode
110 + end
111 + config.grader_mode = grader_mode
112 +
113 + # reading rails environment
114 + log 'Reading rails environment'
115 +
116 + RAILS_ENV = config.rails_env
117 + require RAILS_ROOT + '/config/environment'
118 +
119 + # register grader process
120 + if config.report_grader
121 + grader_proc = GraderProcess.register(config.grader_hostname,
122 + Process.pid,
123 + grader_mode)
124 + else
125 + grader_proc = nil
126 + end
127 +
128 + #set loggin environment
129 + ENV['GRADER_LOGGING'] = log_file_name
130 +
131 + # register exit handler to report inactive, and terminated
132 + at_exit do
133 + if grader_proc!=nil
134 + grader_proc.report_inactive
135 + grader_proc.terminate
136 + end
137 + end
138 +
139 + #
140 + # MAIN LOOP
141 + #
142 +
143 + case grader_mode
144 + when "queue", "test_request"
145 + log "Grader: #{grader_mode}"
146 + if grader_mode=="queue"
147 + engine = Grader::Engine.new
148 + else
149 + engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
150 + Grader::TestRequestReporter.new)
151 + end
152 +
153 + runner = Grader::Runner.new(engine, grader_proc)
154 + while true
155 +
156 + if check_stopfile # created by calling grader stop
157 + clear_stopfile
158 + log "stopped (with stop file)"
159 + break
160 + end
161 +
162 + if grader_mode=="queue"
163 + task = runner.grade_oldest_task
164 + else
165 + task = runner.grade_oldest_test_request
166 + end
167 + if task==nil
168 + sleep(1)
169 + end
170 + end
171 +
172 + when "prob"
173 + engine = Grader::Engine.new
174 + runner = Grader::Runner.new(engine, grader_proc)
175 +
176 + grader_proc.report_active if grader_proc!=nil
177 +
178 + ARGV.shift
179 + ARGV.shift
180 +
181 + ARGV.each do |prob_name|
182 + prob = Problem.find_by_name(prob_name)
183 + if prob==nil
184 + puts "cannot find problem: #{prob_name}"
185 + else
186 + runner.grade_problem(prob)
187 + end
188 + end
189 +
190 + when "sub"
191 + engine = Grader::Engine.new
192 + runner = Grader::Runner.new(engine, grader_proc)
193 +
194 + grader_proc.report_active if grader_proc!=nil
195 +
196 + ARGV.shift
197 + ARGV.shift
198 +
199 + ARGV.each do |sub_id|
200 + puts "Grading #{sub_id}"
201 + begin
202 + submission = Submission.find(sub_id.to_i)
203 + rescue ActiveRecord::RecordNotFound
204 + puts "Record not found"
205 + submission = nil
206 + end
207 +
208 + if submission!=nil
209 + runner.grade_submission(submission)
210 + end
211 + end
212 +
213 + else
214 + display_manual
215 + exit(0)
216 + end
217 +
@@ -1,9 +1,9
1 # Rails app directory
1 # Rails app directory
2 - RAILS_ROOT = File.join(File.dirname(__FILE__),"../../..")
2 + RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__),"../../.."))
3 - GRADER_ROOT = File.join(File.dirname(__FILE__),"..")
3 + GRADER_ROOT = File.expand_path(File.join(File.dirname(__FILE__),".."))
4
4
5 # This load all required codes
5 # This load all required codes
6 require File.join(File.dirname(__FILE__),'../lib/boot')
6 require File.join(File.dirname(__FILE__),'../lib/boot')
7
7
8 # load the required environment file
8 # load the required environment file
9 require File.dirname(__FILE__) + "/env_#{GRADER_ENV}.rb"
9 require File.dirname(__FILE__) + "/env_#{GRADER_ENV}.rb"
@@ -1,217 +1,135
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 - def stop_grader(id)
3 + require 'optparse'
4 - if id==:all
5 - File.open(File.dirname(__FILE__) + "/stop.all",'w').close
6 - else
7 - File.open(File.dirname(__FILE__) + "/stop.#{id}",'w').close
8 - end
9 - end
10 -
11 - def check_stopfile
12 - FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 - FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 - end
15 -
16 - def clear_stopfile
17 - if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 - system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 - end
20 - end
21
4
22 def config
5 def config
23 Grader::Configuration.get_instance
6 Grader::Configuration.get_instance
24 end
7 end
25
8
26 def log_file_name
9 def log_file_name
27 if !File.exists?(config.log_dir)
10 if !File.exists?(config.log_dir)
28 raise "Log directory does not exist: #{config.log_dir}"
11 raise "Log directory does not exist: #{config.log_dir}"
29 end
12 end
30 config.log_dir +
13 config.log_dir +
31 - "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
14 + "/#{GRADER_ENV}.#{Process.pid}"
32 end
15 end
33
16
34 def log(str)
17 def log(str)
35 if config.talkative
18 if config.talkative
36 puts str
19 puts str
37 end
20 end
38 if config.logging
21 if config.logging
39 fp = File.open(log_file_name,"a")
22 fp = File.open(log_file_name,"a")
40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
23 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 fp.close
24 fp.close
42 end
25 end
43 end
26 end
44
27
45 - def display_manual
28 + def parse_arguments(args)
46 - puts <<USAGE
29 + options = {
47 - Grader.
30 + :environment => 'grading',
48 - using: (1) grader
31 + :problems => [],
49 - (2) grader environment [mode]
32 + :submissions => []
50 - (3) grader stop [all|pids-list]
33 + }
51 - (4) grader --help
34 + opts = OptionParser.new do |opts|
52 - (1) call grader with environment = 'exam', mode = 'queue'
35 + opts.banner = <<BANNER
53 - (2) possible modes are: 'queue', 'prob', 'test_request'
36 + grader-batch - the grader for batch grading..
54 - (3) create stop-file to stop running grader in queue mode
37 + Usage: grader-batch [options]
55 - (4) You are here.
38 + BANNER
56 - USAGE
39 +
40 + opts.on("-e", "--env", "Set environment: grading (*), exam, etc.") do |env|
41 + options[:environment] = env
42 + end
43 +
44 + opts.on("--prob p1,p2,p3", Array, "Grade problems p1, p2, and p3.") do |prob_list|
45 + options[:problems] += prob_list
46 + end
47 +
48 + opts.on("--sub s1,s2,s3", Array, "Grade submissions specified by ids") do |submission_list|
49 + options[:submissions] += submission_list
50 + end
51 +
52 + # help
53 + opts.on_tail("-h", "--help", "Show this message") do
54 + puts opts
55 + exit
56 + end
57 + end
58 +
59 + opts.parse!
60 + return options
57 end
61 end
58
62
63 +
59 #########################################
64 #########################################
60 # main program
65 # main program
61 #########################################
66 #########################################
62
67
63 - # with --help
68 + options = parse_arguments(ARGV)
64 - if (ARGV.length==1) and (/help/.match(ARGV[0]))
65 - display_manual
66 - exit(0)
67 - end
68
69
69 # reading environment and options
70 # reading environment and options
70 - if (ARGV.length >= 1) and (ARGV[0]=='stop')
71 + GRADER_ENV = options[:environment]
71 - if ARGV.length==1
72 - puts "you should specify pid-list or 'all'"
73 - display_manual
74 - elsif (ARGV.length==2) and (ARGV[1]=='all')
75 - stop_grader(:all)
76 - puts "A global stop file ('stop.all') created."
77 - puts "You should remove it manually later."
78 - else
79 - (1..ARGV.length-1).each do |i|
80 - stop_grader(ARGV[i])
81 - end
82 - puts "stop file(s) created"
83 - end
84 - exit(0)
85 - end
86 -
87 - if check_stopfile
88 - puts "Stop file exists. Terminated."
89 - clear_stopfile
90 - exit(0)
91 - end
92 -
93 - grader_mode = 'queue'
94 - if ARGV.length >= 1
95 - GRADER_ENV = ARGV[0]
96 - if ARGV.length >=2
97 - grader_mode = ARGV[1]
98 - end
99 - else
100 - GRADER_ENV = 'exam'
101 - end
102 -
103 puts "environment: #{GRADER_ENV}"
72 puts "environment: #{GRADER_ENV}"
104 require File.join(File.dirname(__FILE__),'config/environment')
73 require File.join(File.dirname(__FILE__),'config/environment')
105
74
106 - # add grader_mode to config
107 - # this is needed because method log needs it. TODO: clean this up
108 - class << config
109 - attr_accessor :grader_mode
110 - end
111 - config.grader_mode = grader_mode
112 -
113 # reading rails environment
75 # reading rails environment
114 log 'Reading rails environment'
76 log 'Reading rails environment'
115
77
116 RAILS_ENV = config.rails_env
78 RAILS_ENV = config.rails_env
117 require RAILS_ROOT + '/config/environment'
79 require RAILS_ROOT + '/config/environment'
118
80
119 # register grader process
81 # register grader process
120 if config.report_grader
82 if config.report_grader
121 grader_proc = GraderProcess.register(config.grader_hostname,
83 grader_proc = GraderProcess.register(config.grader_hostname,
122 Process.pid,
84 Process.pid,
123 - grader_mode)
85 + GRADER_ENV)
124 else
86 else
125 grader_proc = nil
87 grader_proc = nil
126 end
88 end
127
89
128 #set loggin environment
90 #set loggin environment
129 ENV['GRADER_LOGGING'] = log_file_name
91 ENV['GRADER_LOGGING'] = log_file_name
130
92
131 # register exit handler to report inactive, and terminated
93 # register exit handler to report inactive, and terminated
132 at_exit do
94 at_exit do
133 if grader_proc!=nil
95 if grader_proc!=nil
134 grader_proc.report_inactive
96 grader_proc.report_inactive
135 grader_proc.terminate
97 grader_proc.terminate
136 end
98 end
137 end
99 end
138
100
139 - #
101 + # grading
140 - # MAIN LOOP
102 +
141 - #
103 + engine = Grader::Engine.new
104 + runner = Grader::Runner.new(engine, grader_proc)
142
105
143 - case grader_mode
106 + # grade problems
144 - when "queue", "test_request"
107 + options[:problems].each do |prob_name|
145 - log "Grader: #{grader_mode}"
108 + grader_proc.report_active if grader_proc!=nil
146 - if grader_mode=="queue"
109 + prob = Problem.find_by_name(prob_name)
147 - engine = Grader::Engine.new
110 + if prob==nil
111 + puts "cannot find problem: #{prob_name}"
148 else
112 else
149 - engine = Grader::Engine.new(Grader::TestRequestRoomMaker.new,
113 + runner.grade_problem(prob)
150 - Grader::TestRequestReporter.new)
114 + end
115 + grader_proc.report_inactive if grader_proc!=nil
116 + end
117 +
118 + # grade submissions
119 + options[:submissions].each do |sub_id|
120 + grader_proc.report_active if grader_proc!=nil
121 + puts "Grading #{sub_id}"
122 + begin
123 + submission = Submission.find(sub_id.to_i)
124 + rescue ActiveRecord::RecordNotFound
125 + puts "Record not found"
126 + submission = nil
151 end
127 end
152
128
153 - runner = Grader::Runner.new(engine, grader_proc)
129 + if submission!=nil
154 - while true
130 + runner.grade_submission(submission)
155 -
156 - if check_stopfile # created by calling grader stop
157 - clear_stopfile
158 - log "stopped (with stop file)"
159 - break
160 - end
161 -
162 - if grader_mode=="queue"
163 - task = runner.grade_oldest_task
164 - else
165 - task = runner.grade_oldest_test_request
166 - end
167 - if task==nil
168 - sleep(1)
169 - end
170 end
131 end
171 -
132 + grader_proc.report_inactive if grader_proc!=nil
172 - when "prob"
173 - engine = Grader::Engine.new
174 - runner = Grader::Runner.new(engine, grader_proc)
175 -
176 - grader_proc.report_active if grader_proc!=nil
177 -
178 - ARGV.shift
179 - ARGV.shift
180 -
181 - ARGV.each do |prob_name|
182 - prob = Problem.find_by_name(prob_name)
183 - if prob==nil
184 - puts "cannot find problem: #{prob_name}"
185 - else
186 - runner.grade_problem(prob)
187 - end
188 - end
189 -
190 - when "sub"
191 - engine = Grader::Engine.new
192 - runner = Grader::Runner.new(engine, grader_proc)
193 -
194 - grader_proc.report_active if grader_proc!=nil
195 -
196 - ARGV.shift
197 - ARGV.shift
198 -
199 - ARGV.each do |sub_id|
200 - puts "Grading #{sub_id}"
201 - begin
202 - submission = Submission.find(sub_id.to_i)
203 - rescue ActiveRecord::RecordNotFound
204 - puts "Record not found"
205 - submission = nil
206 - end
207 -
208 - if submission!=nil
209 - runner.grade_submission(submission)
210 - end
211 - end
212 -
213 - else
214 - display_manual
215 - exit(0)
216 end
133 end
217
134
135 + puts "Done."
@@ -50,80 +50,80
50 language = 'c++'
50 language = 'c++'
51 end
51 end
52
52
53 # COMMENT: should it be only source.ext?
53 # COMMENT: should it be only source.ext?
54 if problem!=nil
54 if problem!=nil
55 source_name = "#{problem.name}.#{lang_ext}"
55 source_name = "#{problem.name}.#{lang_ext}"
56 else
56 else
57 source_name = "source.#{lang_ext}"
57 source_name = "source.#{lang_ext}"
58 end
58 end
59
59
60 begin
60 begin
61 grading_dir = @room_maker.produce_grading_room(submission)
61 grading_dir = @room_maker.produce_grading_room(submission)
62 @room_maker.save_source(submission,source_name)
62 @room_maker.save_source(submission,source_name)
63 problem_home = @room_maker.find_problem_home(submission)
63 problem_home = @room_maker.find_problem_home(submission)
64
64
65 # puts "GRADING DIR: #{grading_dir}"
65 # puts "GRADING DIR: #{grading_dir}"
66 # puts "PROBLEM DIR: #{problem_home}"
66 # puts "PROBLEM DIR: #{problem_home}"
67
67
68 dinit = DirInit::Manager.new(problem_home)
68 dinit = DirInit::Manager.new(problem_home)
69
69
70 dinit.setup do
70 dinit.setup do
71 copy_log = copy_script(problem_home)
71 copy_log = copy_script(problem_home)
72 save_copy_log(problem_home,copy_log)
72 save_copy_log(problem_home,copy_log)
73 end
73 end
74 -
74 +
75 call_judge(problem_home,language,grading_dir,source_name)
75 call_judge(problem_home,language,grading_dir,source_name)
76
76
77 @reporter.report(submission,"#{grading_dir}/test-result")
77 @reporter.report(submission,"#{grading_dir}/test-result")
78
78
79 dinit.teardown do
79 dinit.teardown do
80 copy_log = load_copy_log(problem_home)
80 copy_log = load_copy_log(problem_home)
81 clear_copy_log(problem_home)
81 clear_copy_log(problem_home)
82 clear_script(copy_log,problem_home)
82 clear_script(copy_log,problem_home)
83 end
83 end
84
84
85 rescue RuntimeError => msg
85 rescue RuntimeError => msg
86 @reporter.report_error(submission,"Grading error: #{msg}")
86 @reporter.report_error(submission,"Grading error: #{msg}")
87
87
88 ensure
88 ensure
89 @room_maker.clean_up(submission)
89 @room_maker.clean_up(submission)
90 Dir.chdir(current_dir) # this is really important
90 Dir.chdir(current_dir) # this is really important
91 end
91 end
92 end
92 end
93
93
94 protected
94 protected
95
95
96 def talk(str)
96 def talk(str)
97 if @config.talkative
97 if @config.talkative
98 puts str
98 puts str
99 end
99 end
100 end
100 end
101
101
102 def call_judge(problem_home,language,grading_dir,fname)
102 def call_judge(problem_home,language,grading_dir,fname)
103 ENV['PROBLEM_HOME'] = problem_home
103 ENV['PROBLEM_HOME'] = problem_home
104
104
105 - talk grading_dir
105 + talk "Grading in #{grading_dir}"
106 Dir.chdir grading_dir
106 Dir.chdir grading_dir
107 cmd = "#{problem_home}/script/judge #{language} #{fname}"
107 cmd = "#{problem_home}/script/judge #{language} #{fname}"
108 talk "CMD: #{cmd}"
108 talk "CMD: #{cmd}"
109 system(cmd)
109 system(cmd)
110 end
110 end
111
111
112 def get_std_script_dir
112 def get_std_script_dir
113 GRADER_ROOT + '/std-script'
113 GRADER_ROOT + '/std-script'
114 end
114 end
115
115
116 def copy_script(problem_home)
116 def copy_script(problem_home)
117 script_dir = "#{problem_home}/script"
117 script_dir = "#{problem_home}/script"
118 std_script_dir = get_std_script_dir
118 std_script_dir = get_std_script_dir
119
119
120 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
120 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
121
121
122 scripts = Dir[std_script_dir + '/*']
122 scripts = Dir[std_script_dir + '/*']
123
123
124 copied = []
124 copied = []
125
125
126 scripts.each do |s|
126 scripts.each do |s|
127 fname = File.basename(s)
127 fname = File.basename(s)
128 if !FileTest.exist?("#{script_dir}/#{fname}")
128 if !FileTest.exist?("#{script_dir}/#{fname}")
129 copied << fname
129 copied << fname
You need to be logged in to leave comments. Login now