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

r176:1bdb8b71a462 - - 1 file changed: 1 inserted, 1 deleted

@@ -48,424 +48,424
48 48 using: (1) grader
49 49 (2) grader environment [mode] [options]
50 50 (3) grader stop [all|pids-list]
51 51 (4) grader --help
52 52 (1) call grader with environment = 'exam', mode = 'queue'
53 53 (2) possible modes are: 'queue', 'test_request', 'prob', 'sub', 'contest', and 'autonew'
54 54 queue: repeatedly check the task queue and grade any available tasks
55 55
56 56 prob: re-grade every user latest submission of the specific problem.
57 57 the problem name must be specified by the next argument.
58 58
59 59 additional options:
60 60 --all-sub re-grade every submissions instead of just the latest submission of each user.
61 61
62 62 sub: re-grader the specified submission.
63 63 The submission ID to be re-graded must be specified by the next argument.
64 64
65 65 options:
66 66 --err-log log error to a file in the log dir
67 67
68 68 (3) create stop-file to stop running grader in queue mode
69 69 (4) You are here.
70 70 USAGE
71 71 end
72 72
73 73 def process_options_and_stop_file
74 74 # The list of options are:
75 75 # - stop [all|process ids]
76 76 # -
77 77
78 78 # Process 'help' option
79 79 if (ARGV.length==1) and (/help/.match(ARGV[0]))
80 80 display_manual
81 81 exit(0)
82 82 end
83 83
84 84 # Process 'stop' option.
85 85 if (ARGV.length >= 1) and (ARGV[0]=='stop')
86 86 if ARGV.length==1
87 87 puts "you should specify pid-list or 'all'"
88 88 display_manual
89 89 elsif (ARGV.length==2) and (ARGV[1]=='all')
90 90 stop_grader(:all)
91 91 puts "A global stop file ('stop.all') created."
92 92 puts "You should remove it manually later."
93 93 else
94 94 (1..ARGV.length-1).each do |i|
95 95 stop_grader(ARGV[i])
96 96 end
97 97 puts "stop file(s) created"
98 98 end
99 99 exit(0)
100 100 end
101 101
102 102 # Check stop file.
103 103 if check_stopfile
104 104 puts "Stop file exists. Terminated."
105 105 clear_stopfile
106 106 exit(0)
107 107 end
108 108
109 109 #default options
110 110 options = {
111 111 :mode => 'queue',
112 112 :environment => 'exam',
113 113 :dry_run => false,
114 114 }
115 115
116 116 # Process mode and environment option
117 117 if ARGV.length >= 1
118 118 options[:environment] = ARGV.shift
119 119 if ARGV.length >=1
120 120 options[:mode] = ARGV.shift
121 121 end
122 122 else
123 123 puts 'no argument specified, using default mode and environment.'
124 124 end
125 125
126 126 options[:dry_run] = (ARGV.delete('--dry') != nil)
127 127 if options[:dry_run] and (not ['prob','contest','autonew'].include? options[:mode])
128 128 puts "Dry run currently works only for 'prob' or 'contest' modes."
129 129 exit(0)
130 130 end
131 131
132 132 options[:report] = (ARGV.delete('--report') != nil)
133 133 if options[:report] and (not ['prob','contest','autonew'].include? options[:mode])
134 134 puts "Report currently works only for 'prob' or 'contest' modes."
135 135 exit(0)
136 136 end
137 137
138 138 options[:all_sub] = (ARGV.delete('--all-sub') != nil)
139 139
140 140 options[:err_log] = (ARGV.delete('--err-log') != nil)
141 141
142 142 return options
143 143 end
144 144
145 145 class ResultCollector
146 146 def initialize
147 147 @results = {}
148 148 @problems = {}
149 149 @users = {}
150 150 end
151 151
152 152 def after_save_hook(submission, grading_result)
153 153 end
154 154
155 155 def save(submission, grading_result)
156 156 user = submission.user
157 157 problem = submission.problem
158 158 if not @problems.has_key? problem.id
159 159 @problems[problem.id] = problem
160 160 end
161 161 if not @users.has_key? user.id
162 162 @users[user.id] = user
163 163 end
164 164 @results[[user.id, problem.id]] = grading_result
165 165
166 166 after_save_hook(submission, grading_result)
167 167 end
168 168
169 169 def print_report_by_user
170 170 puts "---------------------"
171 171 puts " REPORT"
172 172 puts "---------------------"
173 173
174 174 print "login,email"
175 175 @problems.each_value do |problem|
176 176 print ",#{problem.name}"
177 177 end
178 178 print "\n"
179 179
180 180 @users.each_value do |user|
181 181 print "#{user.login},#{user.email}"
182 182 @problems.each_value do |problem|
183 183 if @results.has_key? [user.id, problem.id]
184 184 print ",#{@results[[user.id,problem.id]][:points]}"
185 185 else
186 186 print ","
187 187 end
188 188 end
189 189 print "\n"
190 190 end
191 191 end
192 192 end
193 193
194 194 def grader_general_loop(engine, grader_proc, options)
195 195 runner = Grader::Runner.new(engine, grader_proc)
196 196 while true
197 197
198 198 if check_stopfile # created by calling grader stop
199 199 clear_stopfile
200 200 log "stopped (with stop file)"
201 201 break
202 202 end
203 203
204 204 task = yield(runner)
205 205
206 206 if task==nil
207 207 sleep(1)
208 208 end
209 209 end
210 210 end
211 211
212 212 def grader_queue_loop(grader_proc, options)
213 213 log "Grader: queue"
214 214 engine = Grader::Engine.new
215 215 grader_general_loop(engine, grader_proc, options) do |runner|
216 216 runner.grade_oldest_task
217 217 end
218 218 end
219 219
220 220 def grader_test_request_loop(grader_proc, options)
221 221 log "Grader: test_request"
222 222 engine = Grader::Engine.new(:room_maker => Grader::TestRequestRoomMaker.new,
223 223 :reporter => Grader::TestRequestReporter.new)
224 224 grader_general_loop(engine, grader_proc, options) do |runner|
225 225 runner.grade_oldest_test_request
226 226 end
227 227 end
228 228
229 229 def grader_autonew_loop(grader_proc, options)
230 230 log "Grader: autonew"
231 231
232 232 if options[:report]
233 233 result_collector = ResultCollector.new
234 234 else
235 235 result_collector = nil
236 236 end
237 237
238 238 if options[:dry_run]
239 239 puts "Running in dry mode"
240 240 end
241 241
242 242 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
243 243 :result_collector => result_collector)
244 244
245 245 engine = Grader::Engine.new(:reporter => prob_reporter)
246 246 runner = Grader::Runner.new(engine, grader_proc)
247 247
248 248 grader_proc.report_active if grader_proc!=nil
249 249
250 250 latest_submitted_at = nil
251 251 graded_submission_ids = {}
252 252
253 253 while true
254 254
255 255 if check_stopfile # created by calling grader stop
256 256 clear_stopfile
257 257 log "stopped (with stop file)"
258 258 break
259 259 end
260 260
261 261 if latest_submitted_at==nil
262 262 submissions = Submission.all
263 263 else
264 264 submissions = Submission.all(:conditions => ["submitted_at >= :latest",
265 265 {:latest => latest_submitted_at}])
266 266 end
267 267
268 268 graded_any = false
269 269
270 270 if submissions.length != 0
271 271 submissions.each do |submission|
272 272 if (submission.problem == nil) or (!submission.problem.available)
273 273 next
274 274 end
275 275 if ! graded_submission_ids[submission.id]
276 276 runner.grade_submission(submission)
277 277 graded_submission_ids[submission.id] = true
278 278 if (!latest_submitted_at or
279 279 latest_submitted_at < submission.submitted_at)
280 280 latest_submitted_at = submission.submitted_at
281 281 end
282 282 puts "graded: #{submission.id}"
283 283 puts "latest: #{latest_submitted_at}"
284 284 graded_any = true
285 285 end
286 286 end
287 287 end
288 288
289 289 if ! graded_any
290 290 sleep(1)
291 291 end
292 292 end
293 293 end
294 294
295 295 def grader_grade_problems(grader_proc, options)
296 296 if options[:report]
297 297 result_collector = ResultCollector.new
298 298 else
299 299 result_collector = nil
300 300 end
301 301
302 302 if options[:dry_run]
303 303 puts "Running in dry mode"
304 304 end
305 305
306 306 prob_reporter = Grader::SubmissionReporter.new(:dry_run => options[:dry_run],
307 307 :result_collector => result_collector)
308 308 engine = Grader::Engine.new(:reporter => prob_reporter)
309 309 runner = Grader::Runner.new(engine, grader_proc)
310 310
311 311 grader_proc.report_active if grader_proc!=nil
312 312
313 313 ARGV.each do |prob_name|
314 314 prob = Problem.find_by_name(prob_name)
315 315 if prob==nil
316 316 puts "cannot find problem: #{prob_name}"
317 317 else
318 318 runner.grade_problem(prob,options)
319 319 end
320 320 end
321 321
322 322 if options[:report]
323 323 result_collector.print_report_by_user
324 324 end
325 325 end
326 326
327 327 def grader_grade_contests(grader_proc, options)
328 328 # always use dry run when grading during contest
329 329 dry_run = options[:dry_run] = true
330 330
331 331 contest_name = ARGV.shift
332 332
333 333 contest = Contest.find_by_name(contest_name)
334 334 if contest==nil
335 335 puts "cannot find contest: #{contest_name}"
336 336 exit(0)
337 337 end
338 338
339 339 if options[:report]
340 340 result_collector = ResultCollector.new
341 341 else
342 342 result_collector = nil
343 343 end
344 344
345 345 if options[:dry_run]
346 346 puts "Running in dry mode"
347 347 end
348 348
349 349 prob_reporter = Grader::SubmissionReporter.new(:dry_run => dry_run,
350 350 :result_collector => result_collector)
351 351 engine = Grader::Engine.new(:reporter => prob_reporter)
352 352 runner = Grader::Runner.new(engine, grader_proc)
353 353
354 354 grader_proc.report_active if grader_proc!=nil
355 355
356 356 contest.problems.each do |problem|
357 357 puts "Grading: #{problem.name}"
358 358 runner.grade_problem(problem,
359 359 :user_conditions => lambda do |u|
360 360 u.contest_finished? and
361 361 u.contest_ids.include?(contest.id)
362 362 end)
363 363 end
364 364
365 365 if options[:report]
366 366 result_collector.print_report_by_user
367 367 end
368 368 end
369 369
370 370 def grader_grade_submissions(grader_proc, options)
371 371 engine = Grader::Engine.new
372 372 runner = Grader::Runner.new(engine, grader_proc)
373 373
374 374 grader_proc.report_active if grader_proc!=nil
375 375
376 376 ARGV.each do |sub_id|
377 377 puts "Grading #{sub_id}"
378 378 begin
379 379 submission = Submission.find(sub_id.to_i)
380 380 rescue ActiveRecord::RecordNotFound
381 381 puts "Submission #{sub_id} not found"
382 382 submission = nil
383 383 end
384 384
385 385 if submission!=nil
386 386 runner.grade_submission(submission)
387 387 end
388 388 end
389 389 end
390 390
391 391 #########################################
392 392 # main program
393 393 #########################################
394 394
395 395 options = process_options_and_stop_file
396 396 GRADER_ENV = options[:environment]
397 397 grader_mode = options[:mode]
398 398 dry_run = options[:dry_run]
399 399
400 400 puts "environment: #{GRADER_ENV}"
401 401 puts "grader mode: #{grader_mode}"
402 402 require File.join(File.dirname(__FILE__),'config/environment')
403 403
404 404 # add grader_mode to config
405 405 # this is needed because method log needs it. TODO: clean this up
406 406 class << config
407 407 attr_accessor :grader_mode
408 408 end
409 409 config.grader_mode = grader_mode
410 410
411 411 # reading rails environment
412 412 log 'Reading rails environment'
413 413
414 414 RAILS_ENV = config.rails_env
415 415 require RAILS_ROOT + '/config/environment'
416 416
417 417 # register grader process
418 418 if config.report_grader
419 419 grader_proc = GraderProcess.register(config.grader_hostname,
420 420 Process.pid,
421 421 grader_mode)
422 422 else
423 423 grader_proc = nil
424 424 end
425 425
426 426 #set loggin environment
427 427 ENV['GRADER_LOGGING'] = log_file_name
428 428 if options[:err_log]
429 429 err_file_name = log_file_name + '.err'
430 430 $stderr.reopen(err_file_name,"a")
431 431 log "STDERR log to file [#{err_file_name}]"
432 - warn "start logging for grader PID #{Process.id} on #{Time.now.in_time_zone}"
432 + warn "start logging for grader PID #{Process.pid} on #{Time.now.in_time_zone}"
433 433 end
434 434
435 435
436 436 # register exit handler to report inactive, and terminated
437 437 at_exit do
438 438 if grader_proc!=nil
439 439 grader_proc.report_inactive
440 440 grader_proc.terminate
441 441 end
442 442 end
443 443
444 444 #
445 445 # MAIN LOOP
446 446 #
447 447
448 448 case grader_mode
449 449 when "queue"
450 450 grader_queue_loop(grader_proc, options)
451 451
452 452 when "test_request"
453 453 grader_test_request_loop(grader_proc, options)
454 454
455 455 when "prob"
456 456 grader_grade_problems(grader_proc, options)
457 457
458 458 when "contest"
459 459 grader_grade_contests(grader_proc, options)
460 460
461 461 when "sub"
462 462 grader_grade_submissions(grader_proc, options)
463 463
464 464 when "autonew"
465 465 grader_autonew_loop(grader_proc, options)
466 466
467 467 else
468 468 display_manual
469 469 exit(0)
470 470 end
471 471
You need to be logged in to leave comments. Login now