View source
<?php
define('BACKGROUND_PROCESS_ASS_MAX_AGE', 30);
function background_process_ass_menu() {
$items = array();
$items['admin/config/system/background-process/ass'] = array(
'type' => MENU_LOCAL_TASK,
'title' => 'Apache Server Status',
'description' => 'Administer background process apache server status',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'background_process_ass_settings_form',
),
'access arguments' => array(
'administer background process',
),
'file' => 'background_process_ass.admin.inc',
'weight' => 3,
);
return $items;
}
function background_process_ass_init() {
return;
$cache = cache_get('background_process_ass_max_clients');
if (!$cache) {
$cache = (object) array(
'data' => array(),
);
$service_hosts = background_process_get_service_hosts();
foreach ($service_hosts as $name => $info) {
$ass = $name . '_ass';
if (!empty($service_hosts[$ass])) {
}
}
}
global $conf;
foreach ($cache->data as $service_host => $max_clients) {
if (!isset($conf[$service_host]['max_clients'])) {
$conf[$service_host]['max_clients'] = $max_clients;
}
}
}
function background_process_ass_cron() {
set_time_limit(30);
background_process_ass_auto_unlock();
}
function background_process_ass_cronapi() {
$items = array();
$items['background_process_ass_cron'] = array(
'description' => t('Unlock dead processes'),
'rules' => array(
'* * * * *',
),
'configure' => 'admin/config/system/background-process/ass',
);
return $items;
}
function background_process_ass_cron_schedule_alter(&$items) {
if (!isset($items['background_process_ass_cron'])) {
$hooks = ultimate_cron_get_hooks();
if (isset($hooks['background_process_ass_cron']['background_process'])) {
$process =& $hooks['background_process_ass_cron']['background_process'];
if ($process
->getStartTime() + 120 < time()) {
$process
->log(t('Self unlocking stale cleanup job'))
->unlock();
$process = NULL;
}
}
}
if (isset($items['background_process_ass_cron'])) {
$org_items = $items;
$items = array();
$items['background_process_ass_cron'] = $org_items['background_process_ass_cron'];
$items += $org_items;
}
}
function background_process_ass_service_group() {
$info = array();
$info['methods']['background_process_ass_service_group_idle'] = t('Idle workers');
return $info;
}
function background_process_ass_service_group_idle($service_group, $reload = FALSE) {
$result = NULL;
$max = 0;
$msg = "";
$workers =& drupal_static('background_process_ass_idle_workers', array());
foreach ($service_group['hosts'] as $idx => $host) {
$name = $host . '_ass';
if ($reload || !isset($workers[$name])) {
$workers[$name] = background_process_ass_get_server_status($name, TRUE, $reload);
}
if ($workers[$name] <= 0 && !$reload) {
return background_process_ass_service_group_idle($service_group, TRUE);
}
if ($max < $workers[$name]) {
$result = $host;
$max = $workers[$name];
}
}
if (isset($result)) {
$workers[$result . '_ass']--;
return $result;
}
else {
return background_process_service_group_random($service_group);
}
}
function background_process_ass_auto_unlock() {
$processes = BackgroundProcess::loadAll();
$service_hosts = background_process_get_service_hosts();
foreach ($processes as $process) {
if (!$process->service_host) {
continue;
}
if (!isset($service_hosts[$process->service_host . '_ass'])) {
continue;
}
if (!isset($service_hosts[$process->service_host])) {
continue;
}
list($url, $headers) = background_process_build_request('bgp-start/' . $process->pid, $process->service_host);
$process->http_host = $headers['Host'];
$url = parse_url($url);
$path = $url['path'] . (isset($url['query']) ? '?' . $url['query'] : '');
if (strlen("POST {$path}") > 64) {
continue;
}
if ($process
->getStatus() != BACKGROUND_PROCESS_STATUS_RUNNING) {
continue;
}
if ($process
->getStartTime() > time() - variable_get('background_process_ass_max_age', BACKGROUND_PROCESS_ASS_MAX_AGE)) {
continue;
}
$server_status = background_process_ass_get_server_status($process->service_host . '_ass');
if ($server_status) {
if (!background_process_ass_check_process($process, $server_status, $path)) {
_background_process_ass_unlock($process);
}
}
}
}
function background_process_ass_check_process($process, $server_status, $path) {
$active = TRUE;
if ($server_status && $server_status['status']['Current Timestamp'] > $process
->getStartTime()) {
if (!empty($server_status['connections'])) {
$active = FALSE;
foreach ($server_status['connections'] as $conn) {
if ($conn['M'] == 'R') {
watchdog('bg_process', 'Found reading state ...', array(), WATCHDOG_WARNING);
$active = TRUE;
break;
}
if ($conn['M'] == '.' || $conn['M'] == '_') {
continue;
}
if ($conn['VHost'] == $process->http_host && strpos($conn['Request'], 'POST ' . $path) === 0) {
$active = TRUE;
break;
}
}
}
}
return $active;
}
function _background_process_ass_unlock($process) {
if ($process
->getStatus() == BACKGROUND_PROCESS_STATUS_RUNNING) {
$msg = t('Died unexpectedly (auto unlock due to missing connection)');
if ($process
->log($msg)
->unlock()) {
watchdog('bg_process_ass', 'Unlocked @handle', array(
'@handle' => $process
->getHandle(),
), WATCHDOG_INFO);
}
}
}
function background_process_ass_get_server_status($name, $auto = FALSE, $reload = FALSE) {
if (!$name) {
return;
}
$service_hosts = variable_get('background_process_service_hosts', array());
if (empty($service_hosts[$name])) {
return;
}
$service_host = $service_hosts[$name];
$cache =& drupal_static('background_process_ass_server_status', array());
if (!$reload && isset($cache[$name][$auto])) {
return $cache[$name][$auto];
}
$server_status = array();
$options = array();
if ($auto) {
$options['query']['auto'] = 1;
}
list($url, $headers) = background_process_build_request('', $name, $options);
$timestamp = time();
$response = drupal_http_request($url, array(
'headers' => $headers,
));
if ($response->code != 200) {
watchdog('bg_process', 'Could not acquire server status from %url - error: %error', array(
'%url' => $url,
'%error' => $response->error,
), WATCHDOG_ERROR);
return NULL;
}
if ($auto) {
preg_match('/IdleWorkers:\\s+(\\d+)/', $response->data, $matches);
$server_status = $matches[1];
}
else {
$tables = _background_process_ass_parse_table($response->data);
$dls = _background_process_ass_parse_definition_list($response->data);
$server_status = array(
'response' => $response,
'connections' => $tables[0],
'status' => $dls[1],
);
preg_match('/.*?,\\s+(\\d+-.*?-\\d+\\s+\\d+:\\d+:\\d+)/', $server_status['status']['Restart Time'], $matches);
str_replace('Maj', 'May', $matches[1]);
str_replace('May', 'Oct', $matches[1]);
$server_status['status']['Restart Timestamp'] = strtotime($matches[1]);
$server_status['status']['Current Timestamp'] = $timestamp;
}
$cache[$name][$auto] = $server_status;
return $server_status;
}
function _background_process_ass_parse_table($html) {
preg_match_all("/<table.*?>.*?<\\/[\\s]*table>/s", $html, $table_htmls);
$tables = array();
foreach ($table_htmls[0] as $table_html) {
preg_match_all("/<th.*?>(.*?)<\\/[\\s]*th>/s", $table_html, $matches);
$row_headers = $matches[1];
preg_match_all("/<tr.*?>(.*?)<\\/[\\s]*tr>/s", $table_html, $matches);
$table = array();
foreach ($matches[1] as $row_html) {
$row_html = preg_replace("/\r|\n/", '', $row_html);
preg_match_all("/<td.*?>(.*?)<\\/[\\s]*td>/", $row_html, $td_matches);
$row = array();
for ($i = 0; $i < count($td_matches[1]); $i++) {
$td = strip_tags(html_entity_decode($td_matches[1][$i]));
$i2 = isset($row_headers[$i]) ? $row_headers[$i] : $i;
$row[$i2] = $td;
}
if (count($row) > 0) {
$table[] = $row;
}
}
$tables[] = $table;
}
return $tables;
}
function _background_process_ass_parse_definition_list($html) {
preg_match_all("/<dl.*?>.*?<\\/[\\s]*dl>/s", $html, $dl_htmls);
$dls = array();
foreach ($dl_htmls[0] as $dl_html) {
preg_match_all("/<dl.*?>(.*?)<\\/[\\s]*dl>/s", $dl_html, $matches);
$dl = array();
foreach ($matches[1] as $row_html) {
$row_html = preg_replace("/\r|\n/", '', $row_html);
preg_match_all("/<dt.*?>(.*?)<\\/[\\s]*dt>/", $row_html, $dt_matches);
$row = array();
for ($i = 0; $i < count($dt_matches[1]); $i++) {
$dt = strip_tags(html_entity_decode($dt_matches[1][$i]));
if (strpos($dt, ':') !== FALSE) {
list($key, $value) = explode(': ', $dt, 2);
$dl[$key] = $value;
}
}
}
$dls[] = $dl;
}
return $dls;
}