diff --git a/app/models/grader_message.rb b/app/models/grader_message.rb new file mode 100644 --- /dev/null +++ b/app/models/grader_message.rb @@ -0,0 +1,85 @@ +class GraderMessage < ActiveRecord::Base + + GRADE_SUBMISSION = 1 + GRADE_TEST_REQUEST = 2 + STOP = 3 + + def self.create_message(recipient, command, options=nil, target_id=nil) + recipient_id = recipient + if recipient == :all + recipient_id = -1 + elsif recipient == :any + recipient_id = 0 + end + + GraderMessage.create(:grader_process_id => recipient_id, + :command => command, + :options => options, + :target_id => target_id, + :taken => false) + end + + def self.create_grade_submission(mode,submission) + GraderMessage.create_message(:any, + GraderMessage::GRADE_SUBMISSION, + mode, + submission.id) + end + + def self.create_grade_test_request(mode,test_request) + GraderMessage.create_message(:any, + GraderMessage::GRADE_TEST_REQUEST, + mode, + test_request.id) + end + + def self.create_stop(grader_process_id) + GraderMessage.create_message(grader_process_id, + GraderMessage::STOP) + end + + def self.get_message_for(recipient_id, accepting_commands=:all) + command_conditions = + GraderMessage.build_command_conditions(accepting_commands) + recp_conditions= "((`grader_process_id` = #{recipient_id.to_i})" + + " OR (`grader_process_id` = 0) OR (`grader_process_id` = -1))" + + message = nil # need this to bind message in do-block for transaction + begin + GraderMessage.transaction do + message = GraderMessage.find(:first, + :order => "created_at", + :conditions => + "(`taken`=0)" + + "AND (#{recp_conditions})" + + " AND (#{command_conditions})", + :lock => true) + if message!=nil + message.taken = true + message.save! + end + end + + rescue + message = nil + + end + + message + end + + protected + + def self.build_command_conditions(accepting_commands) + if accepting_commands==:all + return '(1=1)' + else + conds = [] + accepting_commands.each do |command| + conds << "(`command` = #{command.to_i})" + end + return "(" + conds.join(" OR ") + ")" + end + end + +end diff --git a/db/migrate/20090429014554_create_grader_messages.rb b/db/migrate/20090429014554_create_grader_messages.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20090429014554_create_grader_messages.rb @@ -0,0 +1,16 @@ +class CreateGraderMessages < ActiveRecord::Migration + def self.up + create_table :grader_messages do |t| + t.integer :grader_process_id + t.integer :command + t.string :options + t.integer :target_id + t.boolean :taken + t.timestamps + end + end + + def self.down + drop_table :grader_messages + end +end diff --git a/db/schema.rb b/db/schema.rb --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20090426131044) do +ActiveRecord::Schema.define(:version => 20090429014554) do create_table "announcements", :force => true do |t| t.string "author" @@ -42,6 +42,16 @@ t.datetime "updated_at" end + create_table "grader_messages", :force => true do |t| + t.integer "grader_process_id" + t.integer "command" + t.string "options" + t.integer "target_id" + t.boolean "taken" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "grader_processes", :force => true do |t| t.string "host", :limit => 20 t.integer "pid" diff --git a/test/fixtures/grader_messages.yml b/test/fixtures/grader_messages.yml new file mode 100644 --- /dev/null +++ b/test/fixtures/grader_messages.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +# one: +# column: value +# +# two: +# column: value diff --git a/test/unit/grader_message_test.rb b/test/unit/grader_message_test.rb new file mode 100644 --- /dev/null +++ b/test/unit/grader_message_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class GraderMessageTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end