Description:
locks dir based on temp file, does not copy dir when copying scripts, added proper rescue for ln_s
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r103:933325ce824a - - 4 files changed: 4 inserted, 3 deleted

@@ -1,76 +1,76
1 1 require 'ftools'
2 2
3 3 # DirInit::Manager handles directory initialization and clean-up when
4 4 # there are many concurrent processes that wants to modify the
5 5 # directory in the same way.
6 6 #
7 7 # An example usage is when each process wants to copy some temporary
8 8 # files to the directory and delete these files after finishing its
9 9 # job. Problems may occur when the first process delete the files
10 10 # while the second process is still using the files.
11 11 #
12 12 # This library maintain a reference counter on the processes using the
13 13 # directory. It locks the dir to manage critical section when
14 14 # updating the reference counter.
15 15
16 16 module DirInit
17 17
18 18 class Manager
19 19
20 20 def initialize(dir_name, usage_filename='.usage_counter')
21 21 @dir_name = dir_name
22 22 @usage_filename = usage_filename
23 23 end
24 24
25 25 # Check if someone has initialized the dir. If not, call block.
26 26
27 27 def setup # :yields: block
28 - dir = File.new(@dir_name)
28 + dir = File.new(@dir_name + '/lockfile',"w+")
29 29 dir.flock(File::LOCK_EX)
30 30 begin
31 31 counter_filename = get_counter_filename
32 32 if File.exist? counter_filename
33 33 # someone is here
34 34 f = File.new(counter_filename,"r+")
35 35 counter = f.read.to_i
36 36 f.seek(0)
37 37 f.write("#{counter+1}\n")
38 38 f.close
39 39 else
40 40 # i'm the first, create the counter file
41 41 counter = 0
42 42 f = File.new(counter_filename,"w")
43 43 f.write("1\n")
44 44 f.close
45 45 end
46 46
47 47 # if no one is here
48 48 if counter == 0
49 49 if block_given?
50 50 yield
51 51 end
52 52 end
53 53
54 54 rescue
55 55 raise
56 56
57 57 ensure
58 58 # make sure it unlock the directory
59 59 dir.flock(File::LOCK_UN)
60 60 dir.close
61 61 end
62 62 end
63 63
64 64 # Check if I am the last one using the dir. If true, call block.
65 65
66 66 def teardown
67 67 dir = File.new(@dir_name)
68 68 dir.flock(File::LOCK_EX)
69 69 begin
70 70 counter_filename = get_counter_filename
71 71 if File.exist? counter_filename
72 72 # someone is here
73 73 f = File.new(counter_filename,"r+")
74 74 counter = f.read.to_i
75 75 f.seek(0)
76 76 f.write("#{counter-1}\n")
@@ -91,96 +91,97
91 91 copy_log = load_copy_log(problem_home)
92 92 clear_copy_log(problem_home)
93 93 clear_script(copy_log,problem_home)
94 94 end
95 95
96 96 rescue RuntimeError => msg
97 97 @reporter.report_error(submission, msg)
98 98
99 99 ensure
100 100 @room_maker.clean_up(submission)
101 101 Dir.chdir(current_dir) # this is really important
102 102 end
103 103 end
104 104
105 105 protected
106 106
107 107 def talk(str)
108 108 if @config.talkative
109 109 puts str
110 110 end
111 111 end
112 112
113 113 def call_judge(problem_home,language,grading_dir,fname)
114 114 ENV['PROBLEM_HOME'] = problem_home
115 115
116 116 talk grading_dir
117 117 Dir.chdir grading_dir
118 118 cmd = "#{problem_home}/script/judge #{language} #{fname}"
119 119 talk "CMD: #{cmd}"
120 120 system(cmd)
121 121 end
122 122
123 123 def get_std_script_dir
124 124 GRADER_ROOT + '/std-script'
125 125 end
126 126
127 127 def copy_script(problem_home)
128 128 script_dir = "#{problem_home}/script"
129 129 std_script_dir = get_std_script_dir
130 130
131 131 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
132 132
133 133 scripts = Dir[std_script_dir + '/*']
134 134
135 135 copied = []
136 136
137 137 scripts.each do |s|
138 138 fname = File.basename(s)
139 + next if FileTest.directory?(s)
139 140 if !FileTest.exist?("#{script_dir}/#{fname}")
140 141 copied << fname
141 142 FileUtils.cp(s, "#{script_dir}")
142 143 end
143 144 end
144 145
145 146 return copied
146 147 end
147 148
148 149 def copy_log_filename(problem_home)
149 150 return File.join(problem_home, '.scripts_copied')
150 151 end
151 152
152 153 def save_copy_log(problem_home, log)
153 154 f = File.new(copy_log_filename(problem_home),"w")
154 155 log.each do |fname|
155 156 f.write("#{fname}\n")
156 157 end
157 158 f.close
158 159 end
159 160
160 161 def load_copy_log(problem_home)
161 162 f = File.new(copy_log_filename(problem_home),"r")
162 163 log = []
163 164 f.readlines.each do |line|
164 165 log << line.strip
165 166 end
166 167 f.close
167 168 log
168 169 end
169 170
170 171 def clear_copy_log(problem_home)
171 172 File.delete(copy_log_filename(problem_home))
172 173 end
173 174
174 175 def clear_script(log,problem_home)
175 176 log.each do |s|
176 177 FileUtils.rm("#{problem_home}/script/#{s}")
177 178 end
178 179 end
179 180
180 181 def mkdir_if_does_not_exist(dirname)
181 182 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
182 183 end
183 184
184 185 end
185 186
186 187 end
@@ -1,59 +1,59
1 1 #
2 2 # This part contains various test_request helpers for interfacing
3 3 # with Grader::Engine. There are TestRequestRoomMaker and
4 4 # TestRequestReporter.
5 5
6 6 module Grader
7 7
8 8 def self.link_or_copy(src, des)
9 9 begin
10 10 FileUtils.ln_s(src, des)
11 - rescue
11 + rescue NotImplementedError
12 12 FileUtils.cp(src,des)
13 13 end
14 14 end
15 15
16 16 def self.call_and_log(error_message)
17 17 begin
18 18 yield
19 19 rescue
20 20 msg = "ERROR: #{error_message}"
21 21 raise msg
22 22 end
23 23 end
24 24
25 25 #
26 26 # A TestRequestRoomMaker is a helper object for Engine
27 27 # - finds grading room: in user_result_dir/(user)/test_request/ ...
28 28 # - prepare problem configuration for grading --- basically it copy
29 29 # all config files, and copy user's input into the testcase
30 30 # directory. First, it finds the template from problem template
31 31 # directory; if it can't find a template, it'll use the template
32 32 # from default template.
33 33 class TestRequestRoomMaker
34 34 def initialize
35 35 @config = Grader::Configuration.get_instance
36 36 end
37 37
38 38 def produce_grading_room(test_request)
39 39 grading_room = grading_room_dir(test_request)
40 40 FileUtils.mkdir_p(grading_room)
41 41
42 42 #
43 43 # Also copy additional submitted file to this directory as well.
44 44 # The program would see this file only if it is copied
45 45 # to the sandbox directory later. The run script should do it.
46 46 #
47 47 if FileTest.exists?("#{test_request.input_file_name}.files")
48 48 FileUtils.cp_r("#{test_request.input_file_name}.files/.",
49 49 "#{grading_room}")
50 50 end
51 51
52 52 grading_room
53 53 end
54 54
55 55 def find_problem_home(test_request)
56 56 problem_name = test_request.problem_name
57 57
58 58 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
59 59
You need to be logged in to leave comments. Login now