Description:
MERGED changeset 380:381 from http://theory.cpe.ku.ac.th/grader/web/trunk/judge/scripts git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@382 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

r71:76c4d891d4d5 - - 3 files changed: 146 inserted, 0 deleted

@@ -0,0 +1,107
1 + require 'ftools'
2 +
3 + # DirInit::Manager handles directory initialization and clean-up when
4 + # there are many concurrent processes that wants to modify the
5 + # directory in the same way.
6 + #
7 + # An example usage is when each process wants to copy some temporary
8 + # files to the directory and delete these files after finishing its
9 + # job. Problems may occur when the first process delete the files
10 + # while the second process is still using the files.
11 + #
12 + # This library maintain a reference counter on the processes using the
13 + # directory. It locks the dir to manage critical section when
14 + # updating the reference counter.
15 +
16 + module DirInit
17 +
18 + class Manager
19 +
20 + def initialize(dir_name, usage_filename='.usage_counter')
21 + @dir_name = dir_name
22 + @usage_filename = usage_filename
23 + end
24 +
25 + # Check if someone has initialized the dir. If not, call block.
26 +
27 + def setup # :yields: block
28 + dir = File.new(@dir_name)
29 + dir.flock(File::LOCK_EX)
30 + begin
31 + counter_filename = get_counter_filename
32 + if File.exist? counter_filename
33 + # someone is here
34 + f = File.new(counter_filename,"r+")
35 + counter = f.read.to_i
36 + f.seek(0)
37 + f.write("#{counter+1}\n")
38 + f.close
39 + else
40 + # i'm the first, create the counter file
41 + counter = 0
42 + f = File.new(counter_filename,"w")
43 + f.write("1\n")
44 + f.close
45 + end
46 +
47 + # if no one is here
48 + if counter == 0
49 + if block_given?
50 + yield
51 + end
52 + end
53 +
54 + rescue
55 + raise
56 +
57 + ensure
58 + # make sure it unlock the directory
59 + dir.flock(File::LOCK_UN)
60 + end
61 + end
62 +
63 + # Check if I am the last one using the dir. If true, call block.
64 +
65 + def teardown
66 + dir = File.new(@dir_name)
67 + dir.flock(File::LOCK_EX)
68 + begin
69 + counter_filename = get_counter_filename
70 + if File.exist? counter_filename
71 + # someone is here
72 + f = File.new(counter_filename,"r+")
73 + counter = f.read.to_i
74 + f.seek(0)
75 + f.write("#{counter-1}\n")
76 + f.close
77 +
78 + if counter == 1
79 + # i'm the last one
80 +
81 + File.delete(counter_filename)
82 + if block_given?
83 + yield
84 + end
85 + end
86 + else
87 + # This is BAD
88 + raise "Error: reference count missing"
89 + end
90 +
91 + rescue
92 + raise
93 +
94 + ensure
95 + # make sure it unlock the directory
96 + dir.flock(File::LOCK_UN)
97 + end
98 + end
99 +
100 + protected
101 +
102 + def get_counter_filename
103 + return File.join(@dir_name,@usage_filename)
104 + end
105 +
106 + end
107 + end
@@ -0,0 +1,2
1 + box
2 +
@@ -1,7 +1,9
1 1 require 'fileutils'
2 + require 'ftools'
3 + require 'lib/dir_init'
2 4
3 5 module Grader
4 6
5 7 #
6 8 # A grader engine grades a submission, against anything: a test
7 9 # data, or a user submitted test data. It uses two helpers objects:
@@ -60,19 +62,28
60 62 @room_maker.save_source(submission,source_name)
61 63 problem_home = @room_maker.find_problem_home(submission)
62 64
63 65 # puts "GRADING DIR: #{grading_dir}"
64 66 # puts "PROBLEM DIR: #{problem_home}"
65 67
68 + dinit = DirInit::Manager.new(problem_home)
69 +
70 + dinit.setup do
66 71 copy_log = copy_script(problem_home)
72 + save_copy_log(problem_home,copy_log)
73 + end
67 74
68 75 call_judge(problem_home,language,grading_dir,source_name)
69 76
70 77 @reporter.report(submission,"#{grading_dir}/test-result")
71 78
79 + dinit.teardown do
80 + copy_log = load_copy_log(problem_home)
81 + clear_copy_log(problem_home)
72 82 clear_script(copy_log,problem_home)
83 + end
73 84
74 85 rescue RuntimeError => msg
75 86 @reporter.report_error(submission,"Grading error: #{msg}")
76 87
77 88 ensure
78 89 @room_maker.clean_up(submission)
@@ -120,12 +131,38
120 131 end
121 132 end
122 133
123 134 return copied
124 135 end
125 136
137 + def copy_log_filename(problem_home)
138 + return File.join(problem_home, '.scripts_copied')
139 + end
140 +
141 + def save_copy_log(problem_home, log)
142 + f = File.new(copy_log_filename(problem_home),"w")
143 + log.each do |fname|
144 + f.write("#{fname}\n")
145 + end
146 + f.close
147 + end
148 +
149 + def load_copy_log(problem_home)
150 + f = File.new(copy_log_filename(problem_home),"r")
151 + log = []
152 + f.readlines.each do |line|
153 + log << line.strip
154 + end
155 + f.close
156 + log
157 + end
158 +
159 + def clear_copy_log(problem_home)
160 + File.delete(copy_log_filename(problem_home))
161 + end
162 +
126 163 def clear_script(log,problem_home)
127 164 log.each do |s|
128 165 system("rm #{problem_home}/script/#{s}")
129 166 end
130 167 end
131 168
You need to be logged in to leave comments. Login now