Commit 371b6e30 authored by mikeytown2's avatar mikeytown2

Issue #1903844 by mikeytown2: Use Just In Time locking.

parent 968eb425
......@@ -174,8 +174,8 @@ function httprl_menu() {
* This hook should be ran about once a day to once an hour.
*/
function httprl_cron() {
// Let expiration times vary by 30 seconds or so.
$fuzz_factor = 30;
// Let expiration times vary by 1 hour.
$fuzz_factor = 3600;
// Remove expired locks from the semaphore database table.
if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) {
......@@ -1213,6 +1213,11 @@ function httprl_send_request($results = NULL) {
// Reset timer.
$restart_timers = TRUE;
// Get lock if needed.
if (!empty($result->options['lock_name'])) {
httprl_acquire_lock($result);
}
// If connection can not be established bail out here.
if (!$result->fp) {
// Do post processing on the stream.
......@@ -1947,7 +1952,7 @@ function httprl_queue_background_callback(&$args, &$result = NULL) {
}
// Get the maximum amount of time this could take.
$times = array(HTTPRL_TIMEOUT, HTTPRL_GLOBAL_TIMEOUT);
$times = array(httprl_variable_get('httprl_timeout', HTTPRL_TIMEOUT), httprl_variable_get('httprl_global_timeout', HTTPRL_GLOBAL_TIMEOUT));
if (isset($callback_options['options']['timeout'])) {
$times[] = $callback_options['options']['timeout'];
}
......@@ -1955,42 +1960,21 @@ function httprl_queue_background_callback(&$args, &$result = NULL) {
$times[] = $callback_options['options']['global_timeout'];
}
// Acquire lock for this run.
$locked = FALSE;
// Create lock name for this run.
$available = FALSE;
$lock_counter = 0;
while (!$locked && $lock_counter < 20) {
$id = 'httprl_' . hash('sha512', mt_rand() . time());
// Set lock to maximum amount of time.
$locked = lock_acquire($id, max($times));
while (!$available && $lock_counter < 20) {
$name = 'httprl_' . hash('sha512', mt_rand() . microtime(TRUE));
$available = lock_may_be_available($name);
$lock_counter++;
}
// Make sure lock exists after this process is dead.
if (empty($mode)) {
// Remove from the global locks variable.
global $locks;
unset($locks[$id]);
// Remove the lock_id reference in the database.
if (httprl_variable_get('lock_inc', './includes/lock.inc') === './includes/lock.inc') {
if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) {
db_update('semaphore')
->fields(array('value' => 'httprl'))
->condition('name', $id)
->condition('value', _lock_id())
->execute();
}
else {
db_query("UPDATE {semaphore} SET value = '%s' WHERE name = '%s' AND value = '%s'", 'httprl', $id, _lock_id());
}
}
}
$callback_options['options']['lock_name'] = $name;
// Create data array and options for request.
$options = array(
'data' => array(
'master_key' => hash('sha512', httprl_drupal_get_private_key()),
'temp_key' => $id,
'temp_key' => $name,
'mode' => $mode,
'php_timeout' => max($times),
'function' => $callback_options['function'],
......@@ -2013,6 +1997,63 @@ function httprl_queue_background_callback(&$args, &$result = NULL) {
return httprl_request($url, $options);
}
/**
* Get a lock so background calls work.
*
* @param $result
* An object from httprl_send_request.
*/
function httprl_acquire_lock(&$result) {
if (empty($result->options['lock_name'])) {
return FALSE;
}
// Get the maximum amount of time this could take.
$times = array(httprl_variable_get('httprl_timeout', HTTPRL_TIMEOUT), httprl_variable_get('httprl_global_timeout', HTTPRL_GLOBAL_TIMEOUT));
if (isset($result->options['timeout'])) {
$times[] = $result->options['timeout'];
}
if (isset($result->options['global_timeout'])) {
$times[] = $result->options['global_timeout'];
}
// Acquire lock for this run.
$locked = FALSE;
$lock_counter = 0;
$name = $result->options['lock_name'];
while (!$locked && $lock_counter < 3) {
// Set lock to maximum amount of time.
$locked = lock_acquire($name, max($times));
$lock_counter++;
}
if (!$locked) {
return FALSE;
}
// Make sure lock exists after this process is dead.
if (!empty($result->options['blocking'])) {
// Remove from the global locks variable.
global $locks;
unset($locks[$name]);
// Remove the lock_id reference in the database.
if (httprl_variable_get('lock_inc', './includes/lock.inc') === './includes/lock.inc') {
if (defined('VERSION') && substr(VERSION, 0, 1) >= 7) {
db_update('semaphore')
->fields(array('value' => 'httprl'))
->condition('name', $name)
->condition('value', _lock_id())
->execute();
}
else {
db_query("UPDATE {semaphore} SET value = '%s' WHERE name = '%s' AND value = '%s'", 'httprl', $name, _lock_id());
}
}
}
return TRUE;
}
/**
* Will decode chunked transfer-encoding and gzip/deflate content-encoding.
*
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment