To use memcache functions that are not implemented in Cacherouter (e.g. "add") I had to reimplement Cacherouter's __init function, because it's private and I can't call it directly outside. It seems to be only way of accessing cacherouter's memcache object, if I don't subclass Cacherouter's classes (I don't want to).
Please correct me if I'm wrong. I'm not good at OOP.

Comments

crea’s picture

I.e. I have this:

/**
 * Replacement for CacheRouter private __init function.
 */
function cacherouter_init(&$cache, $bin) {
  global $conf;

  if (isset($conf['cacherouter'][$bin]['engine']) && !isset($cache->map[$bin])) {
    $type = strtolower($conf['cacherouter'][$bin]['engine']);
  }
  else {
    $type = isset($conf['cacherouter']['default']['engine']) ? $conf['cacherouter']['default']['engine'] : 'db';
  }

  $cache->type[$bin] = $type;

  if (!class_exists($type . 'Cache')) {
    if (!require(drupal_get_path('module', 'cacherouter') .'/engines/' . $type . '.php')) {
      return FALSE;
    }
  }
  $cache_engine = $type . 'Cache';

  $options = array();
  if (isset($conf['cacherouter'][$bin])) {
    $options = $conf['cacherouter'][$bin];
  }

  $default_options = array();
  if (isset($conf['cacherouter']['default'])) {
    $default_options = $conf['cacherouter']['default'];
  }

  $cache->map[$bin] = new $cache_engine($bin, $options, $default_options);
}

/**
 * Prepare memcache object.
 */
function _prepare_memcache($table) {
  // Check Memcache API.
  if (function_exists('dmemcache_object')) {
    $memcache = dmemcache_object($table);
    if (!$memcache) {
      return FALSE; // Memcache API error.
    }
  }
  // Check CacheRouter.
  elseif (class_exists('memcacheCache')) {
    global $cache;
    if (!isset($cache)) {
      $cache = new CacheRouter();
    }
    if (!isset($cache->map[$table])) {
      cacherouter_init($cache, $table);
    }
    if (isset($cache->map[$table]->memcache) && is_object($cache->map[$table]->memcache)) {
      // Use CacheRouter Memcache.
      $memcache = $cache->map[$table]->memcache;
    }
    else {
      return FALSE; // CacheRouter Memcache error.
    }
  }
  else {
    return FALSE; // No memcached support at all.
  }
  
  return $memcache;
}

Note how Memcache API has dmemcache_object() function that makes it very simple, and for Cacherouter there's lot of code needed, with code duplication. I would prefer to use single function just as in Memcache API.

This will be even bigger issue for Memcached engine because PECL Memcached module has even more advanced functions ("cas" etc).

andypost’s picture

Do you really need direct access to engine object?

crea’s picture

Ofcourse I don't need engine object access. I'm only using it to initialize and access Memcache object. That's lot of repeating code needed to reuse Memcache object of CacheRouter.

andypost’s picture

Memcache object is a part of $GLOBALS['cache']->map array and one per bin - take a look inside Cacherouter.php

Name "cache" is bad for global object and engine class name and should be changed at #564460: Class conflict, namespace collisions

crea’s picture

Did you read my code above ? Yes, I use global cache variable, but that's not guaranteed to work, cause cache can be uninitialized. So to initialize it I repeat CacheRouter's code in my cacherouter_init() function. Please try to read carefully. Thanks.