diff cache/memcache/ad_cache_memcache.inc @ 0:d8a3998dac8e ad

ajout module ad
author pierre
date Fri, 20 Feb 2009 14:04:09 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cache/memcache/ad_cache_memcache.inc	Fri Feb 20 14:04:09 2009 +0000
@@ -0,0 +1,401 @@
+<?php
+// $Id: ad_cache_memcache.inc,v 1.1.2.6.2.6 2009/02/16 23:12:28 jeremy Exp $
+
+/**
+ * @file
+ * Memcache include.
+ *
+ * Copyright (c) 2005-2009.
+ *   Jeremy Andrews <jeremy@tag1consulting.com>.
+ */
+
+/**
+ * TODO: Debug Raw and IFrame display methods, neither currently seem to work
+ *       with this cache type.
+ */
+
+/**
+ * Called by adserve.inc, display an ad from memcache.
+ */
+function ad_cache_memcache() {
+  _debug_echo('Memcache: entering ad_cache_memcache().');
+
+  // TODO: Move the meat of this function into adserve.php, simplifying what
+  // cache plugins have to do and removing duplicated logic.
+  $init_cache = array();
+  $init_func = ad_cache_memcache_hook($init_cache, 'include_file_init', 'include_func_init');
+
+  $hostid = adserve_variable('hostid') ? adserve_variable('hostid') : 'none';
+  if ($hostid == 'none' || ad_memcache_get("ad-hostid-$hostid")) {
+    if (function_exists($init_func)) {
+      $init = $init_func($init_cache, $hostid);
+    }
+    if (!empty($init)) {
+      if (adserve_variable('debug')) {
+        echo "Memcache: initialized externally:<pre>\n";
+        print_r($init);
+        echo '</pre>';
+      }
+      $type = $init['type'];
+      $id = $init['id'];
+      $group = $init['group'];
+      $aids = explode(',', $id);
+      adserve_variable('quantity', $init['quantity']);
+    }
+    else {
+      if ($id = adserve_variable('nids')) {
+        $type = 'node';
+      }
+      else if ($id = adserve_variable('tids')) {
+        $type = 'taxonomy';
+      }
+      else {
+        $type = 'default';
+        $id = 0;
+      }
+      $aids = ad_cache_memcache_get_ids($type, $id);
+      $group = $id;
+    }
+    adserve_variable('group', $group);
+
+    if (adserve_variable('debug')) {
+      echo 'Memcache: selecting from the following ad id(s): ';
+      if (empty($aids)) {
+        echo 'none.<br />';
+      }
+      else {
+        echo implode(', ', $aids) .'.<br />';
+      }
+    }
+
+    $ids = adserve_variable("$type-ids");
+    if ($ids == NULL) {
+      $ids = array();
+    }
+
+    $output = '';
+    $selected = adserve_select_ad($aids, adserve_variable('quantity'), $ids);
+    adserve_variable("$type-ids", array_merge($selected, $ids));
+    foreach ($selected as $aid) {
+      if ($aid = (int)$aid) {
+        $ad = ad_cache_memcache_get_ad($aid);
+
+        if (!empty($output)) {
+          $display_count++;
+          $output .= "<div class=\"space\" id=\"$id-$displayed_count\"></div>";
+        }
+
+        $output .= $ad->display;
+      }
+      else {
+        $ad = array();
+      }
+
+      _debug_echo("Displaying AID: $aid.");
+      $action = $aid ? 'view' : 'count';
+      ad_cache_memcache_increment($action, $aid, $group, $hostid, $ad);
+    }
+    if (empty($output)) {
+      adserve_variable('error', TRUE);
+      $output = 'No active ads were found in the '. (empty($nids) ? 'tids' : 'nids') ." '$id'.";
+      _debug_echo("Memcache: {$output}");
+    }
+  }
+  else {
+    _debug_echo("Memcache: invalid hostid: '$hostid'.");
+    $output = 'You do not have permission to display ads.';
+  }
+
+  return $output;
+}
+
+function ad_cache_memcache_hook(&$cache, $hook, $func) {
+
+  if (empty($cache)) {
+    _debug_echo('Memcache: retrieving hook info from cache.');
+    $cache = ad_memcache_get('ad-cache-hook');
+  }
+  $include_func = NULL;
+  if (is_array($cache) && !empty($cache)) {
+    $include_file = adserve_variable('root_dir') .'/'. $cache[$hook];
+    if (file_exists($include_file) && is_file($include_file)) {
+      _debug_echo("Memcache: including external file: '$include_file'.");
+      include_once($include_file);
+    }
+    else if (is_file($include_file)) {
+      _debug_echo("Memcache: unable to find external file: '$include_file'.");
+    }
+    else {
+      _debug_echo('Memcache: no include file defined in cache.');
+    }
+    $include_func = $cache[$func];
+    if ($include_func) {
+      _debug_echo("Memcache: returning requested func($func): '$include_func'.");
+    }
+  }
+  return ($include_func);
+}
+
+function ad_cache_memcache_get_ids($op = 'default', $id = 0) {
+  switch ($op) {
+
+    case 'node': {
+      $ids = explode(',', $id);
+      break;
+    }
+
+    case 'taxonomy': {
+      $ids = ad_memcache_get("ad-taxonomy-cache-$id");
+      if (!$ids || empty($ids)) {
+        $taxonomy = ad_memcache_get('ad-taxonomy');
+        $cache = array();
+        $ids = explode(',', $id);
+        foreach ($ids as $tid) {
+          if (is_array($taxonomy[$tid])) {
+            $cache += $taxonomy[$tid];
+          }
+        }
+        // Rebuild keys from 0, cache for quick re-use on next ad display.
+        $ids = array_values($cache);
+        ad_memcache_set("ad-taxonomy-cache-$id", $ids);
+      }
+      break;
+    }
+
+    default: {
+      $taxonomy = ad_memcache_get('ad-taxonomy');
+      $ids = $taxonomy[0];
+      break;
+    }
+
+  }
+
+  return $ids;
+}
+
+function ad_cache_memcache_get_ad($aid) {
+  static $load = FALSE;
+
+  $ad = ad_memcache_get("ad-aid-$aid");
+
+  if (!$load && !is_object($ad)) {
+    $load = TRUE;
+    adserve_bootstrap();
+    $ad_memcache_build = variable_get('ad_memcache_build', '');
+    if ((time() - $ad_memcache_build) >= 60) {
+      ad_cache_memcache_build();
+    }
+  }
+
+  return $ad;
+}
+
+/**
+ * Increment impressions counter in memcache.
+ */
+function ad_cache_memcache_increment($action, $aid, $group = '', $hostid = '', $ad = array()) {
+  static $timestamp = NULL;
+
+  _debug_echo("Memcache: increment action($action) aid($aid) group($group) hostid($hostid).");
+
+  if ($aid && !is_object($ad)) {
+    _debug_echo("Invalid ad id: $aid.");
+    return (0);
+  }
+
+  if (!isset($timestamp)) {
+    $timestamp = date('YmdH');
+  }
+  $counters = ad_memcache_get("ad-counters-$aid");
+
+  $update = TRUE;
+  if (!is_array($counters) || !isset($counters["$action:$group:$hostid:$timestamp"])) {
+    _debug_echo("Memcache: adding map: action($action) aid($aid) group($group) hostid($hostid) timestamp($timestamp)");
+    ad_memcache_increment_map($action, $aid, $group, $hostid, $timestamp);
+  }
+
+  $rc = ad_memcache_increment("ad-$action-$aid-$group-$hostid-$timestamp");
+  _debug_echo("Memcache: incrementing ad-$action-$aid-$group-$hostid-$timestamp ($rc)");
+}
+
+/**
+ * The maximum time any process can hold a given lock, in seconds.
+ */
+define('AD_MEMCACHE_LOCK_LIMIT', 2);
+
+/**
+ * Store a value in memcache.
+ */
+function ad_memcache_set($key, $value, $timeout = 86400) {
+  $memcache = ad_memcache_init();
+
+  return $memcache->set($key, $value, MEMCACHE_COMPRESSED, $timeout);
+}
+
+/**
+ * Store a value in memcache.
+ */
+function ad_memcache_add($key, $value, $timeout = 86400) {
+  $memcache = ad_memcache_init();
+
+  return $memcache->add($key, $value, MEMCACHE_COMPRESSED, $timeout);
+}
+
+/**
+ * Get a value from memcache.
+ */
+function ad_memcache_get($key) {
+  $memcache = ad_memcache_init();
+
+  return $memcache->get($key);
+}
+
+/**
+ * Delete a value from memcache.
+ */
+function ad_memcache_delete($key) {
+  $memcache = ad_memcache_init();
+
+  return $memcache->delete($key);
+}
+
+/**
+ * Get a lock in memcache.
+ */
+function ad_memcache_lock($key, $wait = TRUE) {
+  $loop = 0;
+  $lock = FALSE;
+  while ($lock == FALSE) {
+    $lock = ad_memcache_add("LOCK-$key-LOCK", TRUE, AD_MEMCACHE_LOCK_LIMIT);
+    if (!$lock && $wait) {
+      if ($loop++ > 50) {
+        // Hard limit of 5 seconds, after which we fail to grab a lock.
+        return FALSE;
+      }
+      // Wait 1/10th of a second and try again.
+      usleep(100000);
+    }
+    else if (!$lock && !$wait) {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+/**
+ * Release a lock in memcache.
+ */
+function ad_memcache_unlock($key) {
+  ad_memcache_delete("LOCK-$key-LOCK");
+}
+
+/**
+ * Increment a numerical value in memcache.
+ */
+function ad_memcache_increment($key, $value = 1) {
+  $memcache = ad_memcache_init();
+
+  $rc = $memcache->increment($key, $value);
+  if ($rc === FALSE) {
+    // We tried incrementing a counter that hasn't yet been initialized.
+    $rc = $memcache->set($key, $value);
+    if ($rc === FALSE) {
+      // Another process already initialized the counter, increment it.
+      $rc = $memcache->increment($key);
+    }
+  }
+  return $rc;
+}
+
+/**
+ * Decrement a numerical value in memcache.
+ */
+function ad_memcache_decrement($key, $value = 1) {
+  $memcache = ad_memcache_init();
+
+  $rc = $memcache->decrement($key, $value);
+  if ($rc === FALSE) {
+    // We tried incrementing a counter that hasn't yet been initialized.
+    $rc = $memcache->set($key, $value);
+    if ($rc === FALSE) {
+      // Another process already initialized the counter, increment it.
+      $rc = $memcache->decrement($key);
+    }
+  }
+  return $rc;
+}
+
+/**
+ * Update mapping which allows us to quickly find stats in memcache when
+ * feeding them into the database.
+ */
+function ad_memcache_increment_map($action, $aid, $group, $hostid, $timestamp) {
+  $key = "ad-counters-$aid";
+  if (ad_memcache_lock($key)) {
+    $counters = ad_memcache_get($key);
+    if (!is_array($counters) || !isset($counters["$action:$group:$hostid:$timestamp"])) {
+      $counters["$action:$group:$hostid:$timestamp"] = "$action:$group:$hostid:$timestamp";
+      ad_memcache_set($key, $counters);
+    }
+    ad_memcache_unlock($key);
+  }
+}
+
+/**
+ * Decrement a numerical value in memcache.
+ * TODO: Use the same configuration style as Drupal's memcache module,
+ * supporting multiple memcache servers, etc.
+ */
+function ad_memcache_init() {
+  static $memcache = NULL;
+
+  if (!$memcache) {
+    $memcache = new Memcache;
+    $memcache->addServer('localhost', 11211);
+  }
+  return $memcache;
+}
+
+/**
+ * Allow external ad selection logic.
+ */
+function ad_cache_memcache_adserve_select($ads, $invalid) {
+  $cache = array();
+  if ($select_func = ad_cache_memcache_hook($cache, 'include_file_select', 'include_func_select')) {
+    _debug_echo("Memcache: adserve_select: invoking '$select_func()'");
+    if (function_exists($select_func)) {
+      if (is_array($cache) && !empty($cache)) {
+        return $select_func($ads, $invalid, $cache);
+      }
+      else {
+        _debug_echo("Memcache: unexpected error: cache empty.");
+      }
+    }
+    else {
+      _debug_echo("Memcache: adserve_select: '$include_func_select()' not found");
+    }
+  }
+  else {
+    _debug_echo("Memcache: adserve_select: no select function defined");
+  }
+}
+
+/**
+ * Allow external exit text.
+ */
+function ad_cache_memcache_adserve_exit_text() {
+  $cache = array();
+  if ($exit_text_func = ad_cache_memcache_hook($cache, 'include_file_exit_text', 'include_func_exit_text')) {
+    _debug_echo("Memcache: adserve_exit_text: invoking '$exit_text_func()'");
+    if (function_exists($exit_text_func)) {
+      return $exit_text_func();
+    }
+    else {
+      _debug_echo("Memcache: adserve_exit_text: '$exit_text_func()' not found");
+    }
+  }
+  else {
+    _debug_echo("Memcache: adserve_exit_text: no exit_text function defined");
+  }
+}
+