You are here

function _dmemcache_set_pieces in Memcache API and Integration 7

Same name and namespace in other branches
  1. 6 dmemcache.inc \_dmemcache_set_pieces()

Split a large item into pieces and place them into memcache

Parameters

string $key: The string with which you will retrieve this item later.

mixed $value: The item to be stored.

int $exp: (optional) Expiration time in seconds. If it's 0, the item never expires (but memcached server doesn't guarantee this item to be stored all the time, it could be deleted from the cache to make place for other items).

string $bin: (optional) The name of the Drupal subsystem that is making this call. Examples could be 'cache', 'alias', 'taxonomy term' etc. It is possible to map different $bin values to different memcache servers.

object $mc: (optional) The memcache object. Normally this value is determined automatically based on the bin the object is being stored to.

Return value

bool

1 call to _dmemcache_set_pieces()
dmemcache_set in ./dmemcache.inc
Place an item into memcache.

File

./dmemcache.inc, line 125
A memcache API for Drupal.

Code

function _dmemcache_set_pieces($key, $value, $exp = 0, $bin = 'cache', $mc = NULL) {
  static $recursion = 0;
  if (!empty($value->multi_part_data) || !empty($value->multi_part_pieces)) {

    // Prevent an infinite loop.
    return FALSE;
  }

  // Recursion happens when __dmemcache_piece_cache outgrows the largest
  // memcache slice (1 MiB by default) -- prevent an infinite loop and later
  // generate a watchdog error.
  if ($recursion) {
    return FALSE;
  }
  $recursion++;
  $full_key = dmemcache_key($key);

  // Cache the name of this key so if it is deleted later we know to also
  // delete the cache pieces.
  if (!dmemcache_piece_cache_set($full_key, $exp)) {

    // We're caching a LOT of large items. Our piece_cache has exceeded the
    // maximum memcache object size (default of 1 MiB).
    $piece_cache =& drupal_static('dmemcache_piece_cache', array());
    register_shutdown_function('watchdog', 'memcache', 'Too many over-sized cache items (!count) has caused the dmemcache_piece_cache to exceed the maximum memcache object size (default of 1 MiB). Now relying on memcache auto-expiration to eventually clean up over-sized cache pieces upon deletion.', array(
      '!count' => count($piece_cache),
    ), WATCHDOG_ERROR);
  }
  if (variable_get('memcache_log_data_pieces', 2)) {
    timer_start('memcache_split_data');
  }

  // We need to split the item into pieces, so convert it into a string.
  if (is_string($value)) {
    $data = $value;
    $serialized = FALSE;
  }
  else {
    $serialize_function = dmemcache_serialize();
    $data = $serialize_function($value);
    $serialized = TRUE;
  }

  // Account for any metadata stored alongside the data.
  $max_len = variable_get('memcache_data_max_length', 1048576) - (512 + strlen($full_key));
  $pieces = str_split($data, $max_len);
  $piece_count = count($pieces);

  // Create a placeholder item containing data about the pieces.
  $cache = new stdClass();

  // $key gets run through dmemcache_key() later inside dmemcache_set().
  $cache->cid = $key;
  $cache->created = REQUEST_TIME;
  $cache->expire = $exp;
  $cache->data = new stdClass();
  $cache->data->serialized = $serialized;
  $cache->data->piece_count = $piece_count;
  $cache->multi_part_data = TRUE;
  $result = dmemcache_set($cache->cid, $cache, $exp, $bin, $mc);

  // Create a cache item for each piece of data.
  foreach ($pieces as $id => $piece) {
    $cache = new stdClass();
    $cache->cid = _dmemcache_key_piece($key, $id);
    $cache->created = REQUEST_TIME;
    $cache->expire = $exp;
    $cache->data = $piece;
    $cache->multi_part_piece = TRUE;
    $result &= dmemcache_set($cache->cid, $cache, $exp, $bin, $mc);
  }
  if (variable_get('memcache_log_data_pieces', 2) && $piece_count >= variable_get('memcache_log_data_pieces', 2)) {
    if (function_exists('format_size')) {
      $data_size = format_size(strlen($data));
    }
    else {
      $data_size = number_format(strlen($data)) . ' byte';
    }
    register_shutdown_function('watchdog', 'memcache', 'Spent !time ms splitting !bytes object into !pieces pieces, cid = !key', array(
      '!time' => timer_read('memcache_split_data'),
      '!bytes' => $data_size,
      '!pieces' => $piece_count,
      '!key' => dmemcache_key($key, $bin),
    ), WATCHDOG_WARNING);
  }
  $recursion--;

  // TRUE if all pieces were saved correctly.
  return $result;
}