[ARVADOS] created: 1.1.4-351-g7e6ac5a
Git user
git at public.curoverse.com
Tue Jun 5 11:13:11 EDT 2018
at 7e6ac5a4967614cbe59ed5c0ec41c8be4d4cff4d (commit)
commit 7e6ac5a4967614cbe59ed5c0ec41c8be4d4cff4d
Author: Tom Clegg <tclegg at veritasgenetics.com>
Date: Tue Jun 5 10:56:22 2018 -0400
13164: Remove locking. Clean up after races in background instead.
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg at veritasgenetics.com>
diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb
index 1dbdb57..7ec9845 100644
--- a/services/api/app/models/container.rb
+++ b/services/api/app/models/container.rb
@@ -5,6 +5,7 @@
require 'log_reuse_info'
require 'whitelist_update'
require 'safe_json'
+require 'update_priority'
class Container < ArvadosModel
include ArvadosModelUpdates
@@ -37,6 +38,7 @@ class Container < ArvadosModel
before_save :scrub_secret_mounts
after_save :handle_completed
after_save :propagate_priority
+ after_commit { UpdatePriority.run_update_thread }
has_many :container_requests, :foreign_key => :container_uuid, :class_name => 'ContainerRequest', :primary_key => :uuid
belongs_to :auth, :class_name => 'ApiClientAuthorization', :foreign_key => :auth_uuid, :primary_key => :uuid
@@ -126,7 +128,6 @@ class Container < ArvadosModel
# Update the priority of child container requests to match new
# priority of the parent container (ignoring requests with no
# container assigned, because their priority doesn't matter).
- ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
ContainerRequest.
where(requesting_container_uuid: self.uuid,
state: ContainerRequest::Committed).
@@ -316,10 +317,6 @@ class Container < ArvadosModel
# (because state might have changed while acquiring the lock).
check_lock_fail
transaction do
- # Locking involves assigning auth_uuid, which involves looking
- # up container requests, so we must lock both tables in the
- # proper order to avoid deadlock.
- ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
reload
check_lock_fail
update_attributes!(state: Locked)
@@ -542,7 +539,6 @@ class Container < ArvadosModel
if self.state_changed? and self.final?
act_as_system_user do
- ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
if self.state == Cancelled
retryable_requests = ContainerRequest.where("container_uuid = ? and priority > 0 and state = 'Committed' and container_count < container_count_max", uuid)
else
diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb
index ac4415b..b4d1a41 100644
--- a/services/api/app/models/container_request.rb
+++ b/services/api/app/models/container_request.rb
@@ -286,7 +286,6 @@ class ContainerRequest < ArvadosModel
def update_priority
return unless state_changed? || priority_changed? || container_uuid_changed?
act_as_system_user do
- ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
Container.
where('uuid in (?)', [self.container_uuid_was, self.container_uuid].compact).
map(&:update_priority!)
@@ -299,7 +298,6 @@ class ContainerRequest < ArvadosModel
def set_requesting_container_uuid
return if !current_api_client_authorization
- ActiveRecord::Base.connection.execute('LOCK container_requests, containers IN EXCLUSIVE MODE')
if (c = Container.where('auth_uuid=?', current_api_client_authorization.uuid).select([:uuid, :priority]).first)
self.requesting_container_uuid = c.uuid
self.priority = c.priority>0 ? 1 : 0
diff --git a/services/api/lib/update_priority.rb b/services/api/lib/update_priority.rb
new file mode 100644
index 0000000..724d2b2
--- /dev/null
+++ b/services/api/lib/update_priority.rb
@@ -0,0 +1,38 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+module UpdatePriority
+ # Clean up after races: if container priority>0 but there are no
+ # committed container requests for it, reset priority to 0.
+ def self.update_priority
+ if !File.owned?(Rails.root.join('tmp'))
+ Rails.logger.warn("UpdatePriority: not owner of #{Rails.root}/tmp, skipping")
+ return
+ end
+ lockfile = Rails.root.join('tmp', 'update_priority.lock')
+ File.open(lockfile, File::RDWR|File::CREAT, 0600) do |f|
+ return unless f.flock(File::LOCK_NB|File::LOCK_EX)
+ ActiveRecord::Base.connection.execute("UPDATE containers AS c SET priority=0 WHERE state='Queued' AND priority>0 AND uuid NOT IN (SELECT container_uuid FROM container_requests WHERE priority>0);")
+ end
+ end
+
+ def self.run_update_thread
+ need = false
+ Rails.cache.fetch('UpdatePriority', expires_in: 5.seconds) do
+ need = true
+ end
+ return if !need
+
+ Thread.new do
+ Thread.current.abort_on_exception = false
+ begin
+ update_priority
+ rescue => e
+ Rails.logger.error "#{e.class}: #{e}\n#{e.backtrace.join("\n\t")}"
+ ensure
+ ActiveRecord::Base.connection.close
+ end
+ end
+ end
+end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list