View source
<?php
DEFINE('RADIOACTIVITY_MEMCACHE_OK', 1);
DEFINE('RADIOACTIVITY_MEMCACHE_NO_BIN', 2);
DEFINE('RADIOACTIVITY_MEMCACHE_NO_MODULE', 3);
function radioactivity_get_radioactivity_info($reset_cache = FALSE) {
static $info;
if ($reset_cache || !isset($info)) {
$info = array(
'targets' => array(),
'sources' => array(),
);
foreach (module_implements('radioactivity_info') as $name) {
$function = $name . '_radioactivity_info';
$result = $function();
if (isset($result) && is_array($result)) {
$info = array_merge_recursive($info, $result);
}
}
}
return $info;
}
function _radioactivity_get_decay_profiles() {
$decay_profiles = variable_get("radioactivity_profiles", array());
return $decay_profiles;
}
function _radioactivity_possibly_remap_id($oid, $oclass) {
static $map = array();
if (!isset($map[$oclass][$oid])) {
$info = radioactivity_get_radioactivity_info();
$function = isset($info['targets'][$oclass]['id_mapper']) ? $info['targets'][$oclass]['id_mapper'] : FALSE;
if ($function) {
$new_oid = $function($oid, $oclass);
}
else {
$new_oid = $oid;
}
$map[$oclass][$oid] = $new_oid;
}
return $map[$oclass][$oid];
}
function _radioactivity_resolve_classname($oid, $oclass) {
static $map = array();
if (!isset($map[$oclass][$oid])) {
$info = radioactivity_get_radioactivity_info();
$function = $info['targets'][$oclass]['subclass_resolver'];
if ($function) {
$subclass = $function($oid, $oclass);
if ($subclass) {
$classname = $oclass . ':' . $subclass;
}
else {
$classname = $oclass;
}
}
else {
$classname = $oclass;
}
$map[$oclass][$oid] = $classname;
}
return $map[$oclass][$oid];
}
function radioactivity_get_energies_for_source($oid, $oclass, $source) {
$ret = array();
foreach (_radioactivity_get_decay_profiles() as $dpid => $decay_profile) {
$classname = $oclass;
if (isset($decay_profile['energy'][$oclass]['subclasses']) && is_array($decay_profile['energy'][$oclass]['subclasses'])) {
foreach ($decay_profile['energy'][$oclass]['subclasses'] as $subsources) {
if (isset($subsources[$source])) {
$classname = _radioactivity_resolve_classname($oid, $oclass);
break;
}
}
}
$energy = $decay_profile['energy'];
$value = 0;
$classparts = explode(':', $classname);
foreach ($classparts as $part) {
if (!isset($energy[$part]) || !is_array($energy[$part])) {
break;
}
$energy = $energy[$part];
$value_cand = isset($energy[$source]) ? $energy[$source] : FALSE;
if (strlen($value_cand) > 0) {
$value = (double) $value_cand;
}
$energy = isset($energy['subclasses']) ? $energy['subclasses'] : FALSE;
}
$ret[$dpid] = $value;
}
return $ret;
}
function _radioactivity_add_energy_mysql($oid, $oclass, $dpid, $amount, $timestamp) {
db_query("INSERT INTO {radioactivity} (id, class, decay_profile, energy, last_emission_timestamp) " . "VALUES (%d, '%s', %d, %f, %d) ON DUPLICATE KEY UPDATE energy=energy+%f", $oid, $oclass, $dpid, $amount, $timestamp, $amount);
}
function _radioactivity_add_energy_std($oid, $oclass, $dpid, $amount, $timestamp) {
db_query("UPDATE {radioactivity} SET energy=energy+%f " . "WHERE id=%d AND class='%s' AND decay_profile=%d", $amount, $oid, $oclass, $dpid);
if (db_affected_rows() == 0) {
db_lock_table("radioactivity");
$result = db_query("UPDATE {radioactivity} SET energy=energy+%f " . "WHERE id=%d AND class='%s' AND decay_profile=%d", $amount, $oid, $oclass, $dpid);
if (db_affected_rows() == 0) {
db_query("INSERT INTO {radioactivity} (id, class, decay_profile, energy, last_emission_timestamp) " . "VALUES (%d, '%s', %d, %f, %d)", $oid, $oclass, $dpid, $amount, $timestamp);
}
db_unlock_tables();
}
}
function radioactivity_add_energy($oid, $oclass, $source, $allow_delayed_processing = FALSE) {
if ($allow_delayed_processing && radioactivity_get_memcached_enable()) {
if (radioactivity_write_memcache_entry(array(
'type' => 'add-energy',
'oid' => $oid,
'oclass' => $oclass,
'source' => $source,
))) {
return TRUE;
}
}
return _radioactivity_add_energy_internal($oid, $oclass, $source);
}
function _radioactivity_add_energy_internal($oid, $oclass, $source, $multiplier = 1) {
$db_type = $GLOBALS['db_type'];
$timestamp = time();
$energies = radioactivity_get_energies_for_source($oid, $oclass, $source);
foreach ($energies as $dpid => $amount) {
if ($amount == 0) {
continue;
}
$amount *= $multiplier;
$oid = _radioactivity_possibly_remap_id($oid, $oclass);
switch ($db_type) {
case 'mysql':
case 'mysqli':
_radioactivity_add_energy_mysql($oid, $oclass, $dpid, $amount, $timestamp);
break;
case 'pgsql':
_radioactivity_add_energy_std($oid, $oclass, $dpid, $amount, $timestamp);
break;
default:
watchdog('radioactivity', t('Unsupported database: @db_type', array(
'@db_type' => $db_type,
)), WATCHDOG_ERROR);
return FALSE;
}
}
return TRUE;
}
function radioactivity_get_memcached_enable() {
if (radioactivity_determine_memcached_availability() != RADIOACTIVITY_MEMCACHE_OK) {
return 0;
}
return (int) variable_get('radioactivity_memcached_enable', 0);
}
function radioactivity_get_memcached_expiration() {
return (int) variable_get('radioactivity_memcached_expiration', 600);
}
function radioactivity_determine_memcached_availability() {
static $availability;
if (!isset($availability)) {
if (!function_exists('dmemcache_object')) {
$availability = RADIOACTIVITY_MEMCACHE_NO_MODULE;
}
elseif (!dmemcache_object('radioactivity')) {
$availability = RADIOACTIVITY_MEMCACHE_NO_BIN;
}
else {
$availability = RADIOACTIVITY_MEMCACHE_OK;
}
}
return $availability;
}
function radioactivity_write_memcache_entry($entry) {
$mc = dmemcache_object('radioactivity');
$id_key = dmemcache_key('entry_id_seq', 'radioactivity');
$id = $mc
->increment($id_key);
if (!$id) {
$id = 0;
$mc
->add($id_key, $id);
}
$entry_key = dmemcache_key('entry-' . $id, 'radioactivity');
return dmemcache_set('entry-' . $id, $entry, radioactivity_get_memcached_expiration(), 'radioactivity');
}