You are here

function _apdqc_lock_may_be_available in Asynchronous Prefetch Database Query Cache 7

Same name in this branch
  1. 7 apdqc.lock.apc.inc \_apdqc_lock_may_be_available()
  2. 7 apdqc.lock.db.inc \_apdqc_lock_may_be_available()
  3. 7 apdqc.lock.memcache_storage.inc \_apdqc_lock_may_be_available()
  4. 7 apdqc.lock.memcache.inc \_apdqc_lock_may_be_available()
  5. 7 apdqc.lock.redis.inc \_apdqc_lock_may_be_available()

Check if lock acquired by a different process may be available.

If an existing lock has expired, it is removed.

Parameters

string $name: The name of the lock.

Return value

bool TRUE if there is no lock or it was removed, FALSE otherwise.

Related topics

1 call to _apdqc_lock_may_be_available()
apdqc.lock.inc in ./apdqc.lock.inc
A database-mediated implementation of a locking mechanism.
1 string reference to '_apdqc_lock_may_be_available'
apdqc.lock.inc in ./apdqc.lock.inc
A database-mediated implementation of a locking mechanism.

File

./apdqc.lock.db.inc, line 213
A database-mediated implementation of a locking mechanism.

Code

function _apdqc_lock_may_be_available($name) {

  // Build query.
  $query = \Database::getConnection()
    ->prefixTables("\n    SELECT expire, value FROM {" . db_escape_table('semaphore') . "}\n    WHERE name = '" . apdqc_escape_string($name) . "'\n  ");

  // Run query.
  $result = apdqc_query(array(
    'semaphore',
  ), array(
    $name,
  ), $query, array(
    'fetch_all' => TRUE,
  ));
  if (empty($result)) {
    return TRUE;
  }

  // Core DB fallback.
  if (is_string($result) && $result === 'NO DB') {
    $lock = db_query('SELECT expire, value FROM {semaphore} WHERE name = :name', array(
      ':name' => $name,
    ))
      ->fetchAssoc();
    if (!$lock) {
      return TRUE;
    }
  }
  else {
    $lock = $result[0];
  }
  $expire = (double) $lock['expire'];
  $now = microtime(TRUE);
  if ($now > $expire) {

    // We check two conditions to prevent a race condition where another
    // request acquired the lock and set a new expire time. We add a small
    // number to $expire to avoid errors with float to string conversion.
    // Build query.
    $query = \Database::getConnection()
      ->prefixTables("\n      DELETE FROM {" . db_escape_table('semaphore') . "}\n      WHERE name = '" . apdqc_escape_string($name) . "'\n      AND value = '" . apdqc_escape_string($lock['value']) . "'\n      AND expire = " . (double) $expire . "\n    ");

    // Run Query.
    $results = apdqc_query(array(
      'semaphore',
    ), array(
      $name,
    ), $query, array(
      'get_affected_rows' => TRUE,
    ));
    if (!is_string($results) || $results !== 'NO DB') {
      if ($results == 1) {
        return TRUE;
      }
      else {
        return FALSE;
      }
    }
    else {
      return (bool) db_delete('semaphore')
        ->condition('name', $name)
        ->condition('value', $lock['value'])
        ->condition('expire', 0.0001 + $expire, '<=')
        ->execute();
    }
  }
  return FALSE;
}