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,109 +1,109
1 require 'ftools'
1 require 'ftools'
2
2
3 # DirInit::Manager handles directory initialization and clean-up when
3 # DirInit::Manager handles directory initialization and clean-up when
4 # there are many concurrent processes that wants to modify the
4 # there are many concurrent processes that wants to modify the
5 # directory in the same way.
5 # directory in the same way.
6 #
6 #
7 # An example usage is when each process wants to copy some temporary
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
8 # files to the directory and delete these files after finishing its
9 # job. Problems may occur when the first process delete the files
9 # job. Problems may occur when the first process delete the files
10 # while the second process is still using the files.
10 # while the second process is still using the files.
11 #
11 #
12 # This library maintain a reference counter on the processes using the
12 # This library maintain a reference counter on the processes using the
13 # directory. It locks the dir to manage critical section when
13 # directory. It locks the dir to manage critical section when
14 # updating the reference counter.
14 # updating the reference counter.
15
15
16 module DirInit
16 module DirInit
17
17
18 class Manager
18 class Manager
19
19
20 def initialize(dir_name, usage_filename='.usage_counter')
20 def initialize(dir_name, usage_filename='.usage_counter')
21 @dir_name = dir_name
21 @dir_name = dir_name
22 @usage_filename = usage_filename
22 @usage_filename = usage_filename
23 end
23 end
24
24
25 # Check if someone has initialized the dir. If not, call block.
25 # Check if someone has initialized the dir. If not, call block.
26
26
27 def setup # :yields: block
27 def setup # :yields: block
28 - dir = File.new(@dir_name)
28 + dir = File.new(@dir_name + '/lockfile',"w+")
29 dir.flock(File::LOCK_EX)
29 dir.flock(File::LOCK_EX)
30 begin
30 begin
31 counter_filename = get_counter_filename
31 counter_filename = get_counter_filename
32 if File.exist? counter_filename
32 if File.exist? counter_filename
33 # someone is here
33 # someone is here
34 f = File.new(counter_filename,"r+")
34 f = File.new(counter_filename,"r+")
35 counter = f.read.to_i
35 counter = f.read.to_i
36 f.seek(0)
36 f.seek(0)
37 f.write("#{counter+1}\n")
37 f.write("#{counter+1}\n")
38 f.close
38 f.close
39 else
39 else
40 # i'm the first, create the counter file
40 # i'm the first, create the counter file
41 counter = 0
41 counter = 0
42 f = File.new(counter_filename,"w")
42 f = File.new(counter_filename,"w")
43 f.write("1\n")
43 f.write("1\n")
44 f.close
44 f.close
45 end
45 end
46
46
47 # if no one is here
47 # if no one is here
48 if counter == 0
48 if counter == 0
49 if block_given?
49 if block_given?
50 yield
50 yield
51 end
51 end
52 end
52 end
53
53
54 rescue
54 rescue
55 raise
55 raise
56
56
57 ensure
57 ensure
58 # make sure it unlock the directory
58 # make sure it unlock the directory
59 dir.flock(File::LOCK_UN)
59 dir.flock(File::LOCK_UN)
60 dir.close
60 dir.close
61 end
61 end
62 end
62 end
63
63
64 # Check if I am the last one using the dir. If true, call block.
64 # Check if I am the last one using the dir. If true, call block.
65
65
66 def teardown
66 def teardown
67 dir = File.new(@dir_name)
67 dir = File.new(@dir_name)
68 dir.flock(File::LOCK_EX)
68 dir.flock(File::LOCK_EX)
69 begin
69 begin
70 counter_filename = get_counter_filename
70 counter_filename = get_counter_filename
71 if File.exist? counter_filename
71 if File.exist? counter_filename
72 # someone is here
72 # someone is here
73 f = File.new(counter_filename,"r+")
73 f = File.new(counter_filename,"r+")
74 counter = f.read.to_i
74 counter = f.read.to_i
75 f.seek(0)
75 f.seek(0)
76 f.write("#{counter-1}\n")
76 f.write("#{counter-1}\n")
77 f.close
77 f.close
78
78
79 if counter == 1
79 if counter == 1
80 # i'm the last one
80 # i'm the last one
81
81
82 File.delete(counter_filename)
82 File.delete(counter_filename)
83 if block_given?
83 if block_given?
84 yield
84 yield
85 end
85 end
86 end
86 end
87 else
87 else
88 # This is BAD
88 # This is BAD
89 raise "Error: reference count missing"
89 raise "Error: reference count missing"
90 end
90 end
91
91
92 rescue
92 rescue
93 raise
93 raise
94
94
95 ensure
95 ensure
96 # make sure it unlock the directory
96 # make sure it unlock the directory
97 dir.flock(File::LOCK_UN)
97 dir.flock(File::LOCK_UN)
98 dir.close
98 dir.close
99 end
99 end
100 end
100 end
101
101
102 protected
102 protected
103
103
104 def get_counter_filename
104 def get_counter_filename
105 return File.join(@dir_name,@usage_filename)
105 return File.join(@dir_name,@usage_filename)
106 end
106 end
107
107
108 end
108 end
109 end
109 end
@@ -1,186 +1,187
1 require 'fileutils'
1 require 'fileutils'
2 require File.join(File.dirname(__FILE__),'dir_init')
2 require File.join(File.dirname(__FILE__),'dir_init')
3
3
4 module Grader
4 module Grader
5
5
6 #
6 #
7 # A grader engine grades a submission, against anything: a test
7 # A grader engine grades a submission, against anything: a test
8 # data, or a user submitted test data. It uses two helpers objects:
8 # data, or a user submitted test data. It uses two helpers objects:
9 # room_maker and reporter.
9 # room_maker and reporter.
10 #
10 #
11 class Engine
11 class Engine
12
12
13 attr_writer :room_maker
13 attr_writer :room_maker
14 attr_writer :reporter
14 attr_writer :reporter
15
15
16 def initialize(options={})
16 def initialize(options={})
17 # default options
17 # default options
18 if not options.include? :room_maker
18 if not options.include? :room_maker
19 options[:room_maker] = Grader::SubmissionRoomMaker.new
19 options[:room_maker] = Grader::SubmissionRoomMaker.new
20 end
20 end
21 if not options.include? :reporter
21 if not options.include? :reporter
22 options[:reporter] = Grader::SubmissionReporter.new
22 options[:reporter] = Grader::SubmissionReporter.new
23 end
23 end
24
24
25 @config = Grader::Configuration.get_instance
25 @config = Grader::Configuration.get_instance
26
26
27 @room_maker = options[:room_maker]
27 @room_maker = options[:room_maker]
28 @reporter = options[:reporter]
28 @reporter = options[:reporter]
29 end
29 end
30
30
31 # takes a submission, asks room_maker to produce grading directories,
31 # takes a submission, asks room_maker to produce grading directories,
32 # calls grader scripts, and asks reporter to save the result
32 # calls grader scripts, and asks reporter to save the result
33 def grade(submission)
33 def grade(submission)
34 current_dir = FileUtils.pwd
34 current_dir = FileUtils.pwd
35
35
36 user = submission.user
36 user = submission.user
37 problem = submission.problem
37 problem = submission.problem
38
38
39 # TODO: will have to create real exception for this
39 # TODO: will have to create real exception for this
40 if user==nil or problem == nil
40 if user==nil or problem == nil
41 @reporter.report_error(submission,"Grading error: problem with submission")
41 @reporter.report_error(submission,"Grading error: problem with submission")
42 #raise "engine: user or problem is nil"
42 #raise "engine: user or problem is nil"
43 end
43 end
44
44
45 # TODO: this is another hack so that output only task can be judged
45 # TODO: this is another hack so that output only task can be judged
46 if submission.language!=nil
46 if submission.language!=nil
47 language = submission.language.name
47 language = submission.language.name
48 lang_ext = submission.language.ext
48 lang_ext = submission.language.ext
49 else
49 else
50 language = 'c'
50 language = 'c'
51 lang_ext = 'c'
51 lang_ext = 'c'
52 end
52 end
53
53
54 # FIX THIS
54 # FIX THIS
55 talk 'some hack on language'
55 talk 'some hack on language'
56 if language == 'cpp'
56 if language == 'cpp'
57 language = 'c++'
57 language = 'c++'
58 end
58 end
59
59
60 # COMMENT: should it be only source.ext?
60 # COMMENT: should it be only source.ext?
61 if problem!=nil
61 if problem!=nil
62 source_name = "#{problem.name}.#{lang_ext}"
62 source_name = "#{problem.name}.#{lang_ext}"
63 else
63 else
64 source_name = "source.#{lang_ext}"
64 source_name = "source.#{lang_ext}"
65 end
65 end
66
66
67 begin
67 begin
68 grading_dir = @room_maker.produce_grading_room(submission)
68 grading_dir = @room_maker.produce_grading_room(submission)
69 @room_maker.save_source(submission,source_name)
69 @room_maker.save_source(submission,source_name)
70 problem_home = @room_maker.find_problem_home(submission)
70 problem_home = @room_maker.find_problem_home(submission)
71
71
72 # puts "GRADING DIR: #{grading_dir}"
72 # puts "GRADING DIR: #{grading_dir}"
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 raise "No test data."
76 raise "No test data."
77 end
77 end
78
78
79 dinit = DirInit::Manager.new(problem_home)
79 dinit = DirInit::Manager.new(problem_home)
80
80
81 dinit.setup do
81 dinit.setup do
82 copy_log = copy_script(problem_home)
82 copy_log = copy_script(problem_home)
83 save_copy_log(problem_home,copy_log)
83 save_copy_log(problem_home,copy_log)
84 end
84 end
85
85
86 call_judge(problem_home,language,grading_dir,source_name)
86 call_judge(problem_home,language,grading_dir,source_name)
87
87
88 @reporter.report(submission,"#{grading_dir}/test-result")
88 @reporter.report(submission,"#{grading_dir}/test-result")
89
89
90 dinit.teardown do
90 dinit.teardown do
91 copy_log = load_copy_log(problem_home)
91 copy_log = load_copy_log(problem_home)
92 clear_copy_log(problem_home)
92 clear_copy_log(problem_home)
93 clear_script(copy_log,problem_home)
93 clear_script(copy_log,problem_home)
94 end
94 end
95
95
96 rescue RuntimeError => msg
96 rescue RuntimeError => msg
97 @reporter.report_error(submission, msg)
97 @reporter.report_error(submission, msg)
98
98
99 ensure
99 ensure
100 @room_maker.clean_up(submission)
100 @room_maker.clean_up(submission)
101 Dir.chdir(current_dir) # this is really important
101 Dir.chdir(current_dir) # this is really important
102 end
102 end
103 end
103 end
104
104
105 protected
105 protected
106
106
107 def talk(str)
107 def talk(str)
108 if @config.talkative
108 if @config.talkative
109 puts str
109 puts str
110 end
110 end
111 end
111 end
112
112
113 def call_judge(problem_home,language,grading_dir,fname)
113 def call_judge(problem_home,language,grading_dir,fname)
114 ENV['PROBLEM_HOME'] = problem_home
114 ENV['PROBLEM_HOME'] = problem_home
115
115
116 talk grading_dir
116 talk grading_dir
117 Dir.chdir grading_dir
117 Dir.chdir grading_dir
118 cmd = "#{problem_home}/script/judge #{language} #{fname}"
118 cmd = "#{problem_home}/script/judge #{language} #{fname}"
119 talk "CMD: #{cmd}"
119 talk "CMD: #{cmd}"
120 system(cmd)
120 system(cmd)
121 end
121 end
122
122
123 def get_std_script_dir
123 def get_std_script_dir
124 GRADER_ROOT + '/std-script'
124 GRADER_ROOT + '/std-script'
125 end
125 end
126
126
127 def copy_script(problem_home)
127 def copy_script(problem_home)
128 script_dir = "#{problem_home}/script"
128 script_dir = "#{problem_home}/script"
129 std_script_dir = get_std_script_dir
129 std_script_dir = get_std_script_dir
130
130
131 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
131 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
132
132
133 scripts = Dir[std_script_dir + '/*']
133 scripts = Dir[std_script_dir + '/*']
134
134
135 copied = []
135 copied = []
136
136
137 scripts.each do |s|
137 scripts.each do |s|
138 fname = File.basename(s)
138 fname = File.basename(s)
139 + next if FileTest.directory?(s)
139 if !FileTest.exist?("#{script_dir}/#{fname}")
140 if !FileTest.exist?("#{script_dir}/#{fname}")
140 copied << fname
141 copied << fname
141 FileUtils.cp(s, "#{script_dir}")
142 FileUtils.cp(s, "#{script_dir}")
142 end
143 end
143 end
144 end
144
145
145 return copied
146 return copied
146 end
147 end
147
148
148 def copy_log_filename(problem_home)
149 def copy_log_filename(problem_home)
149 return File.join(problem_home, '.scripts_copied')
150 return File.join(problem_home, '.scripts_copied')
150 end
151 end
151
152
152 def save_copy_log(problem_home, log)
153 def save_copy_log(problem_home, log)
153 f = File.new(copy_log_filename(problem_home),"w")
154 f = File.new(copy_log_filename(problem_home),"w")
154 log.each do |fname|
155 log.each do |fname|
155 f.write("#{fname}\n")
156 f.write("#{fname}\n")
156 end
157 end
157 f.close
158 f.close
158 end
159 end
159
160
160 def load_copy_log(problem_home)
161 def load_copy_log(problem_home)
161 f = File.new(copy_log_filename(problem_home),"r")
162 f = File.new(copy_log_filename(problem_home),"r")
162 log = []
163 log = []
163 f.readlines.each do |line|
164 f.readlines.each do |line|
164 log << line.strip
165 log << line.strip
165 end
166 end
166 f.close
167 f.close
167 log
168 log
168 end
169 end
169
170
170 def clear_copy_log(problem_home)
171 def clear_copy_log(problem_home)
171 File.delete(copy_log_filename(problem_home))
172 File.delete(copy_log_filename(problem_home))
172 end
173 end
173
174
174 def clear_script(log,problem_home)
175 def clear_script(log,problem_home)
175 log.each do |s|
176 log.each do |s|
176 FileUtils.rm("#{problem_home}/script/#{s}")
177 FileUtils.rm("#{problem_home}/script/#{s}")
177 end
178 end
178 end
179 end
179
180
180 def mkdir_if_does_not_exist(dirname)
181 def mkdir_if_does_not_exist(dirname)
181 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
182 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
182 end
183 end
183
184
184 end
185 end
185
186
186 end
187 end
@@ -1,203 +1,203
1 #
1 #
2 # This part contains various test_request helpers for interfacing
2 # This part contains various test_request helpers for interfacing
3 # with Grader::Engine. There are TestRequestRoomMaker and
3 # with Grader::Engine. There are TestRequestRoomMaker and
4 # TestRequestReporter.
4 # TestRequestReporter.
5
5
6 module Grader
6 module Grader
7
7
8 def self.link_or_copy(src, des)
8 def self.link_or_copy(src, des)
9 begin
9 begin
10 FileUtils.ln_s(src, des)
10 FileUtils.ln_s(src, des)
11 - rescue
11 + rescue NotImplementedError
12 FileUtils.cp(src,des)
12 FileUtils.cp(src,des)
13 end
13 end
14 end
14 end
15
15
16 def self.call_and_log(error_message)
16 def self.call_and_log(error_message)
17 begin
17 begin
18 yield
18 yield
19 rescue
19 rescue
20 msg = "ERROR: #{error_message}"
20 msg = "ERROR: #{error_message}"
21 raise msg
21 raise msg
22 end
22 end
23 end
23 end
24
24
25 #
25 #
26 # A TestRequestRoomMaker is a helper object for Engine
26 # A TestRequestRoomMaker is a helper object for Engine
27 # - finds grading room: in user_result_dir/(user)/test_request/ ...
27 # - finds grading room: in user_result_dir/(user)/test_request/ ...
28 # - prepare problem configuration for grading --- basically it copy
28 # - prepare problem configuration for grading --- basically it copy
29 # all config files, and copy user's input into the testcase
29 # all config files, and copy user's input into the testcase
30 # directory. First, it finds the template from problem template
30 # directory. First, it finds the template from problem template
31 # directory; if it can't find a template, it'll use the template
31 # directory; if it can't find a template, it'll use the template
32 # from default template.
32 # from default template.
33 class TestRequestRoomMaker
33 class TestRequestRoomMaker
34 def initialize
34 def initialize
35 @config = Grader::Configuration.get_instance
35 @config = Grader::Configuration.get_instance
36 end
36 end
37
37
38 def produce_grading_room(test_request)
38 def produce_grading_room(test_request)
39 grading_room = grading_room_dir(test_request)
39 grading_room = grading_room_dir(test_request)
40 FileUtils.mkdir_p(grading_room)
40 FileUtils.mkdir_p(grading_room)
41
41
42 #
42 #
43 # Also copy additional submitted file to this directory as well.
43 # Also copy additional submitted file to this directory as well.
44 # The program would see this file only if it is copied
44 # The program would see this file only if it is copied
45 # to the sandbox directory later. The run script should do it.
45 # to the sandbox directory later. The run script should do it.
46 #
46 #
47 if FileTest.exists?("#{test_request.input_file_name}.files")
47 if FileTest.exists?("#{test_request.input_file_name}.files")
48 FileUtils.cp_r("#{test_request.input_file_name}.files/.",
48 FileUtils.cp_r("#{test_request.input_file_name}.files/.",
49 "#{grading_room}")
49 "#{grading_room}")
50 end
50 end
51
51
52 grading_room
52 grading_room
53 end
53 end
54
54
55 def find_problem_home(test_request)
55 def find_problem_home(test_request)
56 problem_name = test_request.problem_name
56 problem_name = test_request.problem_name
57
57
58 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
58 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
59
59
60 raise "Test Request: error template not found" if !File.exists?(template_dir)
60 raise "Test Request: error template not found" if !File.exists?(template_dir)
61
61
62 problem_home = problem_home_dir(test_request)
62 problem_home = problem_home_dir(test_request)
63 FileUtils.mkdir_p(problem_home)
63 FileUtils.mkdir_p(problem_home)
64
64
65 copy_problem_template(template_dir,problem_home)
65 copy_problem_template(template_dir,problem_home)
66 link_input_file(test_request,problem_home)
66 link_input_file(test_request,problem_home)
67
67
68 problem_home
68 problem_home
69 end
69 end
70
70
71 def save_source(test_request,source_name)
71 def save_source(test_request,source_name)
72 dir = self.produce_grading_room(test_request)
72 dir = self.produce_grading_room(test_request)
73 submission = test_request.submission
73 submission = test_request.submission
74 f = File.open("#{dir}/#{source_name}","w")
74 f = File.open("#{dir}/#{source_name}","w")
75 f.write(submission.source)
75 f.write(submission.source)
76 f.close
76 f.close
77 end
77 end
78
78
79 def clean_up(test_request)
79 def clean_up(test_request)
80 problem_home = problem_home_dir(test_request)
80 problem_home = problem_home_dir(test_request)
81 remove_data_files(problem_home)
81 remove_data_files(problem_home)
82 end
82 end
83
83
84 protected
84 protected
85 def grading_room_dir(test_request)
85 def grading_room_dir(test_request)
86 problem_name = test_request.problem_name
86 problem_name = test_request.problem_name
87 user = test_request.user
87 user = test_request.user
88 grading_room = "#{@config.user_result_dir}" +
88 grading_room = "#{@config.user_result_dir}" +
89 "/#{user.login}/test_request" +
89 "/#{user.login}/test_request" +
90 "/#{problem_name}/#{test_request.id}"
90 "/#{problem_name}/#{test_request.id}"
91 grading_room
91 grading_room
92 end
92 end
93
93
94 def problem_home_dir(test_request)
94 def problem_home_dir(test_request)
95 problem_name = test_request.problem_name
95 problem_name = test_request.problem_name
96 user = test_request.user
96 user = test_request.user
97 "#{@config.user_result_dir}" +
97 "#{@config.user_result_dir}" +
98 "/#{user.login}/test_request/#{problem_name}"
98 "/#{user.login}/test_request/#{problem_name}"
99 end
99 end
100
100
101 def copy_problem_template(template_dir,problem_home)
101 def copy_problem_template(template_dir,problem_home)
102 Grader::call_and_log("Test Request: cannot copy problem template") {
102 Grader::call_and_log("Test Request: cannot copy problem template") {
103 FileUtils.cp_r("#{template_dir}/.","#{problem_home}")
103 FileUtils.cp_r("#{template_dir}/.","#{problem_home}")
104 }
104 }
105 end
105 end
106
106
107 def link_input_file(test_request, problem_home)
107 def link_input_file(test_request, problem_home)
108 input_fname = "#{test_request.input_file_name}"
108 input_fname = "#{test_request.input_file_name}"
109 if !File.exists?(input_fname)
109 if !File.exists?(input_fname)
110 raise "Test Request: input file not found."
110 raise "Test Request: input file not found."
111 end
111 end
112
112
113 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
113 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
114 if File.exists?(input_fname_problem_home)
114 if File.exists?(input_fname_problem_home)
115 FileUtils.rm([input_fname_problem_home], :force => true)
115 FileUtils.rm([input_fname_problem_home], :force => true)
116 end
116 end
117
117
118 Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}")
118 Grader::link_or_copy("#{input_fname}", "#{input_fname_problem_home}")
119 end
119 end
120
120
121 def remove_data_files(problem_home)
121 def remove_data_files(problem_home)
122 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
122 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
123 Grader::call_and_log("Test Request: cannot remove data files") {
123 Grader::call_and_log("Test Request: cannot remove data files") {
124 FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*")
124 FileUtils.rm Dir.glob("#{problem_home}/test_cases/1/*")
125 }
125 }
126 end
126 end
127 end
127 end
128
128
129 end
129 end
130
130
131 class TestRequestReporter
131 class TestRequestReporter
132 def initialize
132 def initialize
133 @config = Grader::Configuration.get_instance
133 @config = Grader::Configuration.get_instance
134 end
134 end
135
135
136 def report(test_request,test_result_dir)
136 def report(test_request,test_result_dir)
137 save_result(test_request,read_result(test_result_dir))
137 save_result(test_request,read_result(test_result_dir))
138 end
138 end
139
139
140 def report_error(test_request, msg)
140 def report_error(test_request, msg)
141 save_result(test_request, {:running_stat => {
141 save_result(test_request, {:running_stat => {
142 :msg => "#{msg}",
142 :msg => "#{msg}",
143 :running_time => nil,
143 :running_time => nil,
144 :exit_status => "Some error occured. Program did not run",
144 :exit_status => "Some error occured. Program did not run",
145 :memory_usage => nil
145 :memory_usage => nil
146 }})
146 }})
147 end
147 end
148
148
149 protected
149 protected
150 def read_result(test_result_dir)
150 def read_result(test_result_dir)
151 # TODO:
151 # TODO:
152 cmp_msg_fname = "#{test_result_dir}/compiler_message"
152 cmp_msg_fname = "#{test_result_dir}/compiler_message"
153 cmp_file = File.open(cmp_msg_fname)
153 cmp_file = File.open(cmp_msg_fname)
154 cmp_msg = cmp_file.read
154 cmp_msg = cmp_file.read
155 cmp_file.close
155 cmp_file.close
156
156
157 result_file_name = "#{test_result_dir}/1/result"
157 result_file_name = "#{test_result_dir}/1/result"
158
158
159 if File.exists?(result_file_name)
159 if File.exists?(result_file_name)
160 output_file_name = "#{test_result_dir}/1/output.txt"
160 output_file_name = "#{test_result_dir}/1/output.txt"
161 results = File.open("#{test_result_dir}/1/result").readlines
161 results = File.open("#{test_result_dir}/1/result").readlines
162 stat = extract_running_stat(results)
162 stat = extract_running_stat(results)
163
163
164 return {
164 return {
165 :output_file_name => output_file_name,
165 :output_file_name => output_file_name,
166 :running_stat => stat,
166 :running_stat => stat,
167 :comment => "",
167 :comment => "",
168 :cmp_msg => cmp_msg}
168 :cmp_msg => cmp_msg}
169 else
169 else
170 return {
170 return {
171 :running_stat => nil,
171 :running_stat => nil,
172 :comment => "Compilation error",
172 :comment => "Compilation error",
173 :cmp_msg => cmp_msg}
173 :cmp_msg => cmp_msg}
174 end
174 end
175 end
175 end
176
176
177 def extract_running_stat(results)
177 def extract_running_stat(results)
178 running_stat_line = results[-1]
178 running_stat_line = results[-1]
179
179
180 # extract exit status line
180 # extract exit status line
181 run_stat = ""
181 run_stat = ""
182 if !(/[Cc]orrect/.match(results[0]))
182 if !(/[Cc]orrect/.match(results[0]))
183 run_stat = results[0].chomp
183 run_stat = results[0].chomp
184 else
184 else
185 run_stat = 'Program exited normally'
185 run_stat = 'Program exited normally'
186 end
186 end
187
187
188 # extract running time
188 # extract running time
189 if res = /r(.*)u(.*)s/.match(running_stat_line)
189 if res = /r(.*)u(.*)s/.match(running_stat_line)
190 seconds = (res[1].to_f + res[2].to_f)
190 seconds = (res[1].to_f + res[2].to_f)
191 time_stat = "Time used: #{seconds} sec."
191 time_stat = "Time used: #{seconds} sec."
192 else
192 else
193 seconds = nil
193 seconds = nil
194 time_stat = "Time used: n/a sec."
194 time_stat = "Time used: n/a sec."
195 end
195 end
196
196
197 # extract memory usage
197 # extract memory usage
198 if res = /s(.*)m/.match(running_stat_line)
198 if res = /s(.*)m/.match(running_stat_line)
199 memory_used = res[1].to_i
199 memory_used = res[1].to_i
200 else
200 else
201 memory_used = -1
201 memory_used = -1
202 end
202 end
203
203
You need to be logged in to leave comments. Login now