Description:
copy working trunk (r383, before major changes to combine judge and to support grader message queue) to trunk git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@396 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
merge default
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r188:0b607f9b89c1 - - 12 files changed: 14 inserted, 400 deleted

@@ -0,0 +1,10
1 + # Rails app directory
2 + RAILS_ROOT = "/home/jittat/web_grader"
3 +
4 + GRADER_ROOT = "/home/jittat/grader/scripts"
5 +
6 + # This load all required codes
7 + require File.join(File.dirname(__FILE__),'../lib/boot')
8 +
9 + # load the required environment file
10 + require File.dirname(__FILE__) + "/env_#{GRADER_ENV}.rb"
@@ -1,151 +1,140
1 1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 2 # please use the migrations feature of Active Record to incrementally modify your database, and
3 3 # then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11
12 - ActiveRecord::Schema.define(:version => 20090429014554) do
12 + ActiveRecord::Schema.define(:version => 20090426131044) do
13 13
14 14 create_table "announcements", :force => true do |t|
15 15 t.string "author"
16 16 t.text "body"
17 17 t.boolean "published"
18 18 t.datetime "created_at"
19 19 t.datetime "updated_at"
20 20 t.boolean "frontpage", :default => false
21 21 t.boolean "contest_only", :default => false
22 22 end
23 23
24 24 create_table "configurations", :force => true do |t|
25 25 t.string "key"
26 26 t.string "value_type"
27 27 t.string "value"
28 28 t.datetime "created_at"
29 29 t.datetime "updated_at"
30 30 end
31 31
32 32 create_table "countries", :force => true do |t|
33 33 t.string "name"
34 34 t.datetime "created_at"
35 35 t.datetime "updated_at"
36 36 end
37 37
38 38 create_table "descriptions", :force => true do |t|
39 39 t.text "body"
40 40 t.boolean "markdowned"
41 41 t.datetime "created_at"
42 42 t.datetime "updated_at"
43 43 end
44 44
45 - create_table "grader_messages", :force => true do |t|
46 - t.integer "grader_process_id"
47 - t.integer "command"
48 - t.string "options"
49 - t.integer "target_id"
50 - t.boolean "taken"
51 - t.integer "taken_grader_process_id"
52 - t.datetime "created_at"
53 - t.datetime "updated_at"
54 - end
55 -
56 45 create_table "grader_processes", :force => true do |t|
57 46 t.string "host", :limit => 20
58 47 t.integer "pid"
59 48 t.string "mode"
60 49 t.boolean "active"
61 50 t.datetime "created_at"
62 51 t.datetime "updated_at"
63 52 t.integer "task_id"
64 53 t.string "task_type"
65 54 t.boolean "terminated"
66 55 end
67 56
68 57 add_index "grader_processes", ["host", "pid"], :name => "index_grader_processes_on_ip_and_pid"
69 58
70 59 create_table "languages", :force => true do |t|
71 60 t.string "name", :limit => 10
72 61 t.string "pretty_name"
73 62 t.string "ext", :limit => 10
74 63 t.string "common_ext"
75 64 end
76 65
77 66 create_table "messages", :force => true do |t|
78 67 t.integer "sender_id"
79 68 t.integer "receiver_id"
80 69 t.integer "replying_message_id"
81 70 t.text "body"
82 71 t.boolean "replied"
83 72 t.datetime "created_at"
84 73 t.datetime "updated_at"
85 74 end
86 75
87 76 create_table "problems", :force => true do |t|
88 77 t.string "name", :limit => 30
89 78 t.string "full_name"
90 79 t.integer "full_score"
91 80 t.date "date_added"
92 81 t.boolean "available"
93 82 t.string "url"
94 83 t.integer "description_id"
95 84 t.boolean "test_allowed"
96 85 t.boolean "output_only"
97 86 end
98 87
99 88 create_table "rights", :force => true do |t|
100 89 t.string "name"
101 90 t.string "controller"
102 91 t.string "action"
103 92 end
104 93
105 94 create_table "rights_roles", :id => false, :force => true do |t|
106 95 t.integer "right_id"
107 96 t.integer "role_id"
108 97 end
109 98
110 99 add_index "rights_roles", ["role_id"], :name => "index_rights_roles_on_role_id"
111 100
112 101 create_table "roles", :force => true do |t|
113 102 t.string "name"
114 103 end
115 104
116 105 create_table "roles_users", :id => false, :force => true do |t|
117 106 t.integer "role_id"
118 107 t.integer "user_id"
119 108 end
120 109
121 110 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
122 111
123 112 create_table "sessions", :force => true do |t|
124 113 t.string "session_id"
125 114 t.text "data"
126 115 t.datetime "updated_at"
127 116 end
128 117
129 118 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
130 119 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
131 120
132 121 create_table "sites", :force => true do |t|
133 122 t.string "name"
134 123 t.boolean "started"
135 124 t.datetime "start_time"
136 125 t.datetime "created_at"
137 126 t.datetime "updated_at"
138 127 t.integer "country_id"
139 128 t.string "password"
140 129 end
141 130
142 131 create_table "submissions", :force => true do |t|
143 132 t.integer "user_id"
144 133 t.integer "problem_id"
145 134 t.integer "language_id"
146 135 t.text "source"
147 136 t.binary "binary"
148 137 t.datetime "submitted_at"
149 138 t.datetime "compiled_at"
150 139 t.text "compiler_message"
151 140 t.datetime "graded_at"
@@ -1,127 +1,127
1 1 #!/usr/bin/ruby
2 2
3 3 def stop_grader(id)
4 4 if id==:all
5 5 File.open(File.dirname(__FILE__) + "/stop.all",'w').close
6 6 else
7 7 File.open(File.dirname(__FILE__) + "/stop.#{id}",'w').close
8 8 end
9 9 end
10 10
11 11 def check_stopfile
12 12 FileTest.exist?(File.dirname(__FILE__) + "/stop.all") or
13 13 FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
14 14 end
15 15
16 16 def clear_stopfile
17 17 if FileTest.exist?(File.dirname(__FILE__) + "/stop.#{Process.pid}")
18 18 system("rm " + File.dirname(__FILE__) + "/stop.#{Process.pid}")
19 19 end
20 20 end
21 21
22 22 def config
23 23 Grader::Configuration.get_instance
24 24 end
25 25
26 26 def log_file_name
27 27 if !File.exists?(config.log_dir)
28 28 raise "Log directory does not exist: #{config.log_dir}"
29 29 end
30 30 config.log_dir +
31 - "/#{GRADER_ENV}.#{Process.pid}"
31 + "/#{GRADER_ENV}_#{config.grader_mode}.#{Process.pid}"
32 32 end
33 33
34 34 def log(str)
35 35 if config.talkative
36 36 puts str
37 37 end
38 38 if config.logging
39 39 fp = File.open(log_file_name,"a")
40 40 fp.puts("GRADER: #{Time.new.strftime("%H:%M")} #{str}")
41 41 fp.close
42 42 end
43 43 end
44 44
45 45 def display_manual
46 46 puts <<USAGE
47 47 Grader.
48 48 using: (1) grader
49 49 (2) grader environment [mode]
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', 'prob', 'test_request'
54 54 (3) create stop-file to stop running grader in queue mode
55 55 (4) You are here.
56 56 USAGE
57 57 end
58 58
59 59 #########################################
60 60 # main program
61 61 #########################################
62 62
63 63 # with --help
64 64 if (ARGV.length==1) and (/help/.match(ARGV[0]))
65 65 display_manual
66 66 exit(0)
67 67 end
68 68
69 69 # reading environment and options
70 70 if (ARGV.length >= 1) and (ARGV[0]=='stop')
71 71 if ARGV.length==1
72 72 puts "you should specify pid-list or 'all'"
73 73 display_manual
74 74 elsif (ARGV.length==2) and (ARGV[1]=='all')
75 75 stop_grader(:all)
76 76 puts "A global stop file ('stop.all') created."
77 77 puts "You should remove it manually later."
78 78 else
79 79 (1..ARGV.length-1).each do |i|
80 80 stop_grader(ARGV[i])
81 81 end
82 82 puts "stop file(s) created"
83 83 end
84 84 exit(0)
85 85 end
86 86
87 87 if check_stopfile
88 88 puts "Stop file exists. Terminated."
89 89 clear_stopfile
90 90 exit(0)
91 91 end
92 92
93 93 grader_mode = 'queue'
94 94 if ARGV.length >= 1
95 95 GRADER_ENV = ARGV[0]
96 96 if ARGV.length >=2
97 97 grader_mode = ARGV[1]
98 98 end
99 99 else
100 100 GRADER_ENV = 'exam'
101 101 end
102 102
103 103 puts "environment: #{GRADER_ENV}"
104 104 require File.join(File.dirname(__FILE__),'config/environment')
105 105
106 106 # add grader_mode to config
107 107 # this is needed because method log needs it. TODO: clean this up
108 108 class << config
109 109 attr_accessor :grader_mode
110 110 end
111 111 config.grader_mode = grader_mode
112 112
113 113 # reading rails environment
114 114 log 'Reading rails environment'
115 115
116 116 RAILS_ENV = config.rails_env
117 117 require RAILS_ROOT + '/config/environment'
118 118
119 119 # register grader process
120 120 if config.report_grader
121 121 grader_proc = GraderProcess.register(config.grader_hostname,
122 122 Process.pid,
123 123 grader_mode)
124 124 else
125 125 grader_proc = nil
126 126 end
127 127
@@ -9,167 +9,167
9 9 # data, or a user submitted test data. It uses two helpers objects:
10 10 # room_maker and reporter.
11 11 #
12 12 class Engine
13 13
14 14 attr_writer :room_maker
15 15 attr_writer :reporter
16 16
17 17 def initialize(room_maker=nil, reporter=nil)
18 18 @config = Grader::Configuration.get_instance
19 19
20 20 @room_maker = room_maker || Grader::SubmissionRoomMaker.new
21 21 @reporter = reporter || Grader::SubmissionReporter.new
22 22 end
23 23
24 24 # takes a submission, asks room_maker to produce grading directories,
25 25 # calls grader scripts, and asks reporter to save the result
26 26 def grade(submission)
27 27 current_dir = `pwd`.chomp
28 28
29 29 user = submission.user
30 30 problem = submission.problem
31 31
32 32 # TODO: will have to create real exception for this
33 33 if user==nil or problem == nil
34 34 @reporter.report_error(submission,"Grading error: problem with submission")
35 35 #raise "engine: user or problem is nil"
36 36 end
37 37
38 38 # TODO: this is another hack so that output only task can be judged
39 39 if submission.language!=nil
40 40 language = submission.language.name
41 41 lang_ext = submission.language.ext
42 42 else
43 43 language = 'c'
44 44 lang_ext = 'c'
45 45 end
46 46
47 47 # FIX THIS
48 48 talk 'some hack on language'
49 49 if language == 'cpp'
50 50 language = 'c++'
51 51 end
52 52
53 53 # COMMENT: should it be only source.ext?
54 54 if problem!=nil
55 55 source_name = "#{problem.name}.#{lang_ext}"
56 56 else
57 57 source_name = "source.#{lang_ext}"
58 58 end
59 59
60 60 begin
61 61 grading_dir = @room_maker.produce_grading_room(submission)
62 62 @room_maker.save_source(submission,source_name)
63 63 problem_home = @room_maker.find_problem_home(submission)
64 64
65 65 # puts "GRADING DIR: #{grading_dir}"
66 66 # puts "PROBLEM DIR: #{problem_home}"
67 67
68 68 dinit = DirInit::Manager.new(problem_home)
69 69
70 70 dinit.setup do
71 71 copy_log = copy_script(problem_home)
72 72 save_copy_log(problem_home,copy_log)
73 73 end
74 74
75 75 call_judge(problem_home,language,grading_dir,source_name)
76 76
77 77 @reporter.report(submission,"#{grading_dir}/test-result")
78 78
79 79 dinit.teardown do
80 80 copy_log = load_copy_log(problem_home)
81 81 clear_copy_log(problem_home)
82 82 clear_script(copy_log,problem_home)
83 83 end
84 84
85 85 rescue RuntimeError => msg
86 86 @reporter.report_error(submission,"Grading error: #{msg}")
87 87
88 88 ensure
89 89 @room_maker.clean_up(submission)
90 90 Dir.chdir(current_dir) # this is really important
91 91 end
92 92 end
93 93
94 94 protected
95 95
96 96 def talk(str)
97 97 if @config.talkative
98 98 puts str
99 99 end
100 100 end
101 101
102 102 def call_judge(problem_home,language,grading_dir,fname)
103 103 ENV['PROBLEM_HOME'] = problem_home
104 104
105 - talk "Grading in #{grading_dir}"
105 + talk grading_dir
106 106 Dir.chdir grading_dir
107 107 cmd = "#{problem_home}/script/judge #{language} #{fname}"
108 108 talk "CMD: #{cmd}"
109 109 system(cmd)
110 110 end
111 111
112 112 def get_std_script_dir
113 113 GRADER_ROOT + '/std-script'
114 114 end
115 115
116 116 def copy_script(problem_home)
117 117 script_dir = "#{problem_home}/script"
118 118 std_script_dir = get_std_script_dir
119 119
120 120 raise "std-script directory not found" if !FileTest.exist?(std_script_dir)
121 121
122 122 scripts = Dir[std_script_dir + '/*']
123 123
124 124 copied = []
125 125
126 126 scripts.each do |s|
127 127 fname = File.basename(s)
128 128 if !FileTest.exist?("#{script_dir}/#{fname}")
129 129 copied << fname
130 130 system("cp #{s} #{script_dir}")
131 131 end
132 132 end
133 133
134 134 return copied
135 135 end
136 136
137 137 def copy_log_filename(problem_home)
138 138 return File.join(problem_home, '.scripts_copied')
139 139 end
140 140
141 141 def save_copy_log(problem_home, log)
142 142 f = File.new(copy_log_filename(problem_home),"w")
143 143 log.each do |fname|
144 144 f.write("#{fname}\n")
145 145 end
146 146 f.close
147 147 end
148 148
149 149 def load_copy_log(problem_home)
150 150 f = File.new(copy_log_filename(problem_home),"r")
151 151 log = []
152 152 f.readlines.each do |line|
153 153 log << line.strip
154 154 end
155 155 f.close
156 156 log
157 157 end
158 158
159 159 def clear_copy_log(problem_home)
160 160 File.delete(copy_log_filename(problem_home))
161 161 end
162 162
163 163 def clear_script(log,problem_home)
164 164 log.each do |s|
165 165 system("rm #{problem_home}/script/#{s}")
166 166 end
167 167 end
168 168
169 169 def mkdir_if_does_not_exist(dirname)
170 170 Dir.mkdir(dirname) if !FileTest.exist?(dirname)
171 171 end
172 172
173 173 end
174 174
175 175 end
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
deleted file
You need to be logged in to leave comments. Login now