/** * Turns a key array into a key string. This includes running the indexing functions used to manage the Redis * hierarchical storage. * * When requested the actual path, rather than a normalized value, is returned. * * @param array $key * @param bool $path * @return string */ protected function makeKeyString($key, $path = false) { $key = \Stash\Utilities::normalizeKeys($key); $keyString = 'cache:::'; $pathKey = ':pathdb::'; foreach ($key as $name) { //a. cache:::name //b. cache:::name0:::sub $keyString .= $name; //a. :pathdb::cache:::name //b. :pathdb::cache:::name0:::sub $pathKey = ':pathdb::' . $keyString; $pathKey = md5($pathKey); if (isset($this->keyCache[$pathKey])) { $index = $this->keyCache[$pathKey]; } else { $index = $this->redis->get($pathKey); $this->keyCache[$pathKey] = $index; } //a. cache:::name0::: //b. cache:::name0:::sub1::: $keyString .= '_' . $index . ':::'; } return $path ? $pathKey : md5($keyString); }
/** * Turns a key array into a key string. This includes running the indexing functions used to manage the memcached * hierarchical storage. * * When requested the actual path, rather than a normalized value, is returned. * * @param array $key * @param bool $path * @return string */ protected function makeKeyString($key, $path = false) { $key = \Stash\Utilities::normalizeKeys($key); $keyString = ':cache:::'; $pathKey = ':pathdb::'; $time = microtime(true); if ($time - $this->keyCacheTime >= $this->keyCacheTimeLimit) { $this->keyCacheTime = $time; $this->keyCache = array(); } foreach ($key as $name) { //a. cache:::name //b. cache:::name0:::sub $keyString .= $name; //a. :pathdb::cache:::name //b. :pathdb::cache:::name0:::sub $pathKey = ':pathdb::' . $keyString; $pathKey = md5($pathKey); if (isset($this->keyCache[$pathKey])) { $index = $this->keyCache[$pathKey]; } else { $index = $this->memcache->cas($pathKey, 0); $this->keyCache[$pathKey] = $index; } //a. cache:::name0::: //b. cache:::name0:::sub1::: $keyString .= '_' . $index . ':::'; } return $path ? $pathKey : md5($keyString); }
/** * This function takes in an array of strings (the key) and uses them to create a path to save the cache item to. * It starts with the cachePath (or a new 'cache' directory in the config temp directory) and then uses each element * of the array as a directory (after putting the element through md5(), which was the most efficient way to make * sure it was filesystem safe). The last element of the array gets a php extension attached to it. * * @param array $key Null arguments return the base directory. * @throws \Stash\Exception\LogicException * @return string */ protected function makePath($key = null) { if (!isset($this->cachePath)) { throw new LogicException('Unable to load system without a base path.'); } $basePath = $this->cachePath; if (!is_array($key) || count($key) == 0) { return $basePath; } // When I profiled this compared to the "implode" function, this was much faster. This is probably due to the // small size of the arrays and the overhead from function calls. This may seem like a ridiculous // micro-optimization, but I only did it after profiling the code with xdebug and noticing a legitimate // difference, most likely due to the number of times this function can get called in a scripts. // Please don't look at me like that. $memkey = ''; foreach ($key as $group) { $memkey .= str_replace('#', ':', $group) . '#'; } if (isset($this->memStore['keys'][$memkey])) { return $this->memStore['keys'][$memkey]; } else { $path = $basePath; $key = Utilities::normalizeKeys($key, $this->keyHashFunction); foreach ($key as $value) { if (strpos($value, '@') === 0) { $path .= substr($value, 1) . DIRECTORY_SEPARATOR; continue; } $sLen = strlen($value); $len = floor($sLen / $this->directorySplit); for ($i = 0; $i < $this->directorySplit; $i++) { $start = $len * $i; if ($i == $this->directorySplit) { $len = $sLen - $start; } $path .= substr($value, $start, $len) . DIRECTORY_SEPARATOR; } } $path = rtrim($path, DIRECTORY_SEPARATOR) . $this->getEncoder()->getExtension(); $this->memStore['keys'][$memkey] = $path; // in most cases the key will be used almost immediately or not at all, so it doesn't need to grow too large if (count($this->memStore['keys']) > $this->memStoreLimit) { foreach (array_rand($this->memStore['keys'], ceil($this->memStoreLimit / 2) + 1) as $empty) { unset($this->memStore['keys'][$empty]); } } return $path; } }
/** * This function takes an array of strings and turns it into the sqlKey. It does this by iterating through the * array, running the string through sqlite_escape_string() and then combining that string to the keystring with a * delimiter. * * @param array $key * @return string */ public static function makeSqlKey($key) { $key = Utilities::normalizeKeys($key, 'base64_encode'); $path = ''; foreach ($key as $rawPathPiece) { $path .= $rawPathPiece . ':::'; } return $path; }