"""Implementation of SQLAlchemy backend."""
+import functools
import sys
import threading
+import time
import uuid
import warnings
return wrapper
+def _retry_on_deadlock(f):
+ """Decorator to retry a DB API call if Deadlock was received."""
+ @functools.wraps(f)
+ def wrapped(*args, **kwargs):
+ while True:
+ try:
+ return f(*args, **kwargs)
+ except db_exc.DBDeadlock:
+ LOG.warn(_("Deadlock detected when running "
+ "'%(func_name)s': Retrying..."),
+ dict(func_name=f.__name__))
+ # Retry!
+ time.sleep(0.5)
+ continue
+ functools.update_wrapper(wrapped, f)
+ return wrapped
+
+
def model_query(context, *args, **kwargs):
"""Query helper that accounts for context's `read_deleted` field.
@require_context
+@_retry_on_deadlock
def quota_reserve(context, resources, quotas, deltas, expire,
until_refresh, max_age, project_id=None):
elevated = context.elevated()
@require_context
+@_retry_on_deadlock
def reservation_commit(context, reservations, project_id=None):
session = get_session()
with session.begin():
@require_context
+@_retry_on_deadlock
def reservation_rollback(context, reservations, project_id=None):
session = get_session()
with session.begin():
@require_admin_context
+@_retry_on_deadlock
def quota_destroy_all_by_project(context, project_id):
session = get_session()
with session.begin():
@require_admin_context
+@_retry_on_deadlock
def reservation_expire(context):
session = get_session()
with session.begin():
@require_admin_context
+@_retry_on_deadlock
def volume_allocate_iscsi_target(context, volume_id, host):
session = get_session()
with session.begin():
@require_admin_context
+@_retry_on_deadlock
def volume_destroy(context, volume_id):
session = get_session()
now = timeutils.utcnow()
@require_context
@require_volume_exists
+@_retry_on_deadlock
def volume_metadata_delete(context, volume_id, key):
_volume_user_metadata_get_query(context, volume_id).\
filter_by(key=key).\
@require_context
@require_volume_exists
+@_retry_on_deadlock
def volume_metadata_update(context, volume_id, metadata, delete):
return _volume_user_metadata_update(context, volume_id, metadata, delete)
@require_admin_context
@require_volume_exists
+@_retry_on_deadlock
def volume_admin_metadata_delete(context, volume_id, key):
_volume_admin_metadata_get_query(context, volume_id).\
filter_by(key=key).\
@require_admin_context
@require_volume_exists
+@_retry_on_deadlock
def volume_admin_metadata_update(context, volume_id, metadata, delete):
return _volume_admin_metadata_update(context, volume_id, metadata, delete)
@require_admin_context
+@_retry_on_deadlock
def snapshot_destroy(context, snapshot_id):
session = get_session()
with session.begin():
@require_context
@require_snapshot_exists
+@_retry_on_deadlock
def snapshot_metadata_delete(context, snapshot_id, key):
_snapshot_metadata_get_query(context, snapshot_id).\
filter_by(key=key).\
@require_context
@require_snapshot_exists
+@_retry_on_deadlock
def snapshot_metadata_update(context, snapshot_id, metadata, delete):
session = get_session()
with session.begin():
@require_admin_context
+@_retry_on_deadlock
def volume_type_destroy(context, id):
session = get_session()
with session.begin():
@require_context
+@_retry_on_deadlock
def transfer_destroy(context, transfer_id):
session = get_session()
with session.begin():