/** * Read from cache. * @param string key * @return mixed|NULL */ public function read($key) { $key = $this->prefix . $key; $meta = $this->memcache->get($key); if (!$meta) { return NULL; } // meta structure: // array( // data => stored data // delta => relative (sliding) expiration // callbacks => array of callbacks (function, args) // ) // verify dependencies if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) { $this->memcache->delete($key); return NULL; } if (!empty($meta[self::META_DELTA])) { $this->memcache->replace($key, $meta, 0, $meta[self::META_DELTA] + time()); } return $meta[self::META_DATA]; }
/** * Verifies dependencies. * @param array * @return bool */ private function verify($meta) { do { if (!empty($meta[self::META_DELTA])) { // meta[file] was added by readMeta() if (filemtime($meta[self::FILE]) + $meta[self::META_DELTA] < time()) { break; } touch($meta[self::FILE]); } elseif (!empty($meta[self::META_EXPIRE]) && $meta[self::META_EXPIRE] < time()) { break; } if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) { break; } if (!empty($meta[self::META_ITEMS])) { foreach ($meta[self::META_ITEMS] as $depFile => $time) { $m = $this->readMeta($depFile, LOCK_SH); if ($m[self::META_TIME] !== $time) { break 2; } if ($m && !$this->verify($m)) { break 2; } } } return TRUE; } while (FALSE); $this->delete($meta[self::FILE], $meta[self::HANDLE]); // meta[handle] & meta[file] was added by readMeta() return FALSE; }