/**
  * Gets multiple values from memcached in one request.
  *
  * See the buildKeys method definition to understand the $keys/$groups parameters.
  *
  * @link http://www.php.net/manual/en/memcached.getmulti.php
  *
  * @param   array           $keys       Array of keys to retrieve.
  * @param   string|array    $groups     If string, used for all keys. If arrays, corresponds with the $keys array.
  * @param   string          $server_key The key identifying the server to store the value on.
  * @param   null|array      $cas_tokens The variable to store the CAS tokens for the found items.
  * @param   int             $flags      The flags for the get operation.
  * @return  bool|array                  Returns the array of found items or FALSE on failure.
  */
 public function getMulti($keys, $groups = 'default', $server_key = '', &$cas_tokens = NULL, $flags = NULL)
 {
     $derived_keys = $this->buildKeys($keys, $groups);
     /**
      * If either $cas_tokens, or $flags is set, must hit Memcached and bypass runtime cache. Note that
      * this will purposely ignore no_mc_groups values as they cannot handle CAS tokens or the special
      * flags; however, if the groups of groups contains a no_mc_group, this is bypassed.
      */
     if (func_num_args() > 3 && !$this->contains_no_mc_group($groups)) {
         if (!empty($server_key)) {
             $values = $this->mc->getMultiByKey($server_key, $derived_keys, $cas_tokens, $flags);
         } else {
             $values = $this->mc->getMulti($derived_keys, $cas_tokens, $flags);
         }
     } else {
         $values = array();
         $need_to_get = array();
         // Pull out values from runtime cache, or mark for retrieval
         foreach ($derived_keys as $key) {
             if (isset($this->cache[$key])) {
                 $values[$key] = $this->cache[$key];
             } else {
                 $need_to_get[$key] = $key;
             }
         }
         // Get those keys not found in the runtime cache
         if (!empty($need_to_get)) {
             if (!empty($server_key)) {
                 $result = $this->mc->getMultiByKey($server_key, array_keys($need_to_get));
             } else {
                 $result = $this->mc->getMulti(array_keys($need_to_get));
             }
         }
         // Merge with values found in runtime cache
         if (isset($result) && Memcached::RES_SUCCESS === $this->getResultCode()) {
             $values = array_merge($values, $result);
         }
         // If order should be preserved, reorder now
         if (!empty($need_to_get) && $flags === Memcached::GET_PRESERVE_ORDER) {
             $ordered_values = array();
             foreach ($derived_keys as $key) {
                 if (isset($values[$key])) {
                     $ordered_values[$key] = $values[$key];
                 }
             }
             $values = $ordered_values;
             unset($ordered_values);
         }
     }
     // Add the values to the runtime cache
     $this->cache = array_merge($this->cache, $values);
     return $values;
 }
Ejemplo n.º 2
0
 /**
  *
  *
  * @param string $key
  * @param array $options
  * @return array|bool|mixed
  */
 public function get($key, $options = array())
 {
     if (!$this->online()) {
         return Gdn_Cache::CACHEOP_FAILURE;
     }
     $startTime = microtime(true);
     $finalOptions = array_merge($this->StoreDefaults, $options);
     $useLocal = (bool) $finalOptions[Gdn_Cache::FEATURE_LOCAL];
     $localData = array();
     $realKeys = array();
     if (is_array($key)) {
         $multi = true;
         foreach ($key as $multiKey) {
             $realKey = $this->makeKey($multiKey, $finalOptions);
             // Skip this key if we already have it
             if ($useLocal) {
                 $local = $this->localGet($realKey);
                 if ($local !== Gdn_Cache::CACHEOP_FAILURE) {
                     $localData[$realKey] = $local;
                     continue;
                 }
             }
             $realKeys[] = $realKey;
         }
     } else {
         $multi = false;
         $realKey = $this->makeKey($key, $finalOptions);
         // Completely short circuit if we already have everything
         if ($useLocal) {
             $local = $this->localGet($realKey);
             if ($local !== false) {
                 return $local;
             }
         }
         $realKeys = array($realKey);
     }
     $data = array();
     $hitCache = false;
     $numKeys = sizeof($realKeys);
     if ($numKeys) {
         $hitCache = true;
         if ($numKeys > 1) {
             $data = $this->memcache->getMulti($realKeys);
             $ok = $this->lastAction();
         } else {
             $data = $this->memcache->get($realKey);
             // Check if things went ok
             $ok = $this->lastAction($realKey);
             $data = array($realKey => $data);
         }
         if (!$ok) {
             return Gdn_Cache::CACHEOP_FAILURE;
         }
         $storeData = array();
         foreach ($data as $localKey => &$localValue) {
             // Is this a sharded key manifest?
             if (is_object($localValue) && $localValue instanceof MemcachedShard) {
                 $manifest = $localValue;
                 // MultiGet sub-keys
                 $shardKeys = array();
                 foreach ($manifest->keys as $serverKey => $keys) {
                     $serverKeys = $this->memcache->getMultiByKey($serverKey, $keys);
                     $shardKeys = array_merge($shardKeys, $serverKeys);
                 }
                 ksort($shardKeys, SORT_NATURAL);
                 // Check subkeys for validity
                 $shardData = implode('', array_values($shardKeys));
                 unset($shardKeys);
                 $dataHash = md5($shardData);
                 if ($dataHash != $manifest->hash) {
                     continue;
                 }
                 $localValue = unserialize($shardData);
             }
             if ($localValue !== false) {
                 $storeData[$localKey] = $localValue;
             }
         }
         $data = $storeData;
         unset($storeData);
         // Cache in process memory
         if ($useLocal && sizeof($data)) {
             $this->localSet($data);
         }
     }
     // Merge in local data
     $data = array_merge($data, $localData);
     // Track debug stats
     $elapsedTime = microtime(true) - $startTime;
     if (Gdn_Cache::$trace) {
         Gdn_Cache::$trackTime += $elapsedTime;
         Gdn_Cache::$trackGets++;
         $keyTime = sizeof($realKeys) ? $elapsedTime / sizeof($realKeys) : $elapsedTime;
         foreach ($realKeys as $realKey) {
             TouchValue($realKey, Gdn_Cache::$trackGet, array('hits' => 0, 'time' => 0, 'keysize' => null, 'transfer' => 0, 'wasted' => 0));
             $keyData = val($realKey, $data, false);
             Gdn_Cache::$trackGet[$realKey]['hits']++;
             Gdn_Cache::$trackGet[$realKey]['time'] += $keyTime;
             if ($keyData !== false) {
                 $keyData = serialize($keyData);
                 $keySize = strlen($keyData);
                 if (is_null(Gdn_Cache::$trackGet[$realKey]['keysize'])) {
                     Gdn_Cache::$trackGet[$realKey]['keysize'] = $keySize;
                 } else {
                     Gdn_Cache::$trackGet[$realKey]['wasted'] += $keySize;
                 }
                 Gdn_Cache::$trackGet[$realKey]['transfer'] += Gdn_Cache::$trackGet[$realKey]['keysize'];
             }
         }
     }
     // Miss: return the fallback
     if ($data === false) {
         return $this->fallback($key, $options);
     }
     // Hit: Single key. Return the value
     if (!$multi) {
         $val = sizeof($data) ? array_pop($data) : false;
         return $val;
     }
     // Hit: Multi key. Return stripped array.
     $dataStripped = array();
     foreach ($data as $index => $value) {
         $dataStripped[$this->stripKey($index, $finalOptions)] = $value;
     }
     $data = $dataStripped;
     unset($dataStripped);
     return $data;
 }
Ejemplo n.º 3
0
    return true;
}
$data = array('foo' => 'foo-data', 'bar' => 'bar-data', 'baz' => 'baz-data', 'lol' => 'lol-data', 'kek' => 'kek-data');
$keys = array_keys($data);
$null = null;
$m->setMulti($data, 3600);
/* Check that all keys were stored */
var_dump(has_all_keys($keys, $m->getMulti($keys)));
/* Check that all keys get deleted */
$deleted = $m->deleteMulti($keys);
var_dump(has_all_keys($keys, $deleted, true));
/* Try to get the deleted keys, should give empty array */
var_dump($m->getMulti($keys));
/* ---- same tests for byKey variants ---- */
$m->setMultiByKey("hi", $data, 3600);
var_dump(has_all_keys($keys, $m->getMultiByKey('hi', $keys)));
/* Check that all keys get deleted */
$deleted = $m->deleteMultiByKey('hi', $keys);
var_dump(has_all_keys($keys, $deleted, true));
/* Try to get the deleted keys, should give empty array */
var_dump($m->getMultiByKey('hi', $keys));
/* Test deleting non-existent keys */
$keys = array();
$keys[] = "nothere";
$keys[] = "nothere2";
$retval = $m->deleteMulti($keys);
foreach ($retval as $key => $value) {
    if ($value === Memcached::RES_NOTFOUND) {
        echo "{$key} NOT FOUND\n";
    }
}
 /**
  * @inheritdoc
  */
 public function getMultiByKey($server_key, array $keys, &$cas_tokens = array(), $flags = null)
 {
     $keys = $this->prefixArrayOfKeys($keys);
     return parent::getMultiByKey($server_key, $keys, $cas_tokens, $flags);
 }