key($key)); // Update static cache parent::set($key, $cache); return $cache; } /** * set() * Add item into cache. * * @param string $key * The key to set. * @param string $value * The data to store in the cache. * @param string $expire * The time to expire in seconds. * @param string $headers * The page headers. * @return bool * Returns TRUE on success or FALSE on failure */ function set($key, $value, $expire = CACHE_PERMENANT, $headers = NULL) { if ($expire == CACHE_TEMPORARY) { $expire = 180; } // Create new cache object. $cache = new stdClass; $cache->cid = $key; $cache->created = time(); $cache->expire = $expire; $cache->headers = $headers; if (is_array($value) || is_object($value)) { $cache->serialized = TRUE; $cache->data = serialize($value); } else { $cache->serialized = FALSE; $cache->data = $value; } if (!empty($key) && !empty($value)) { $this->lock(); // Get lookup table to be able to keep track of bins $lookup = xcache_get('lookup_' . $this->name); // If the lookup table is empty, initialize table if (empty($lookup)) { $lookup = array(); } // Get full key for storage and set it to 1 so we can keep track of the bin $full_key = $this->key($key); $lookup[$full_key] = 1; // Attempt to store full key and value if (!xcache_set($full_key, $cache, $expire)) { unset($lookup[$full_key]); $return = FALSE; } else { $return = TRUE; } } // Resave the lookup table (even on failure) xcache_set('lookup_' . $this->name, $lookup); // Remove lock. $this->unlock(); return $return; } /** * delete() * Remove item from cache. * * @param string $key * The key to set. * @return mixed object|bool * Returns either the cache object or FALSE on failure */ function delete($key) { // Remove from static array cache. parent::delete($key); if (substr($key, -1, 1) == '*') { $key = substr($key, 0, strlen($key) - 1); $lookup = xcache_get('lookup_' . $this->name); foreach ($lookup as $k => $v) { if (substr($k, 0, strlen($key) - 1)) { xcache_unset($k); unset($lookup[$k]); } } $this->lock(); xcache_set('lookup_' . $this->name, $lookup); $this->unlock(); } else { if (!empty($key) && !empty($value)) { if (!xcache_unset($this->key($key))) { $return = FALSE; } else { $return = TRUE; } } } } /** * flush() * Flush the entire cache. * * @param none * @return mixed bool * Returns TRUE */ function flush() { $this->lock(); // Get lookup table to be able to keep track of bins $lookup = xcache_get('lookup_' . $this->name); // If the lookup table is empty, remove lock and return if (empty($lookup)) { $this->unlock(); return TRUE; } // Cycle through keys and remove each entry from the cache foreach ($lookup as $k => $v) { if (xcache_unset($k)) { unset($lookup[$k]); } } // Resave the lookup table (even on failure) xcache_set('lookup_' . $this->name, $lookup); // Remove lock $this->unlock(); return TRUE; } /** * lock() * lock the cache from other writes. * * @param none * @return string * Returns TRUE on success, FALSE on failure */ function lock() { // Lock once by trying to add lock file, if we can't get the lock, we will loop // for 3 seconds attempting to get lock. If we still can't get it at that point, // then we give up and return FALSE. if (xcache_isset('lock_' . $this->name) === TRUE) { $time = time(); while (xcache_isset('lock_' . $this->name) === TRUE) { if (time() - $time >= 3) { return FALSE; } } } xcache_set('lock_' . $this->name, TRUE); return TRUE; } /** * unlock() * lock the cache from other writes. * * @param none * @return bool * Returns TRUE on success, FALSE on failure */ function unlock() { return xcache_unset('lock_' . $this->name); } }