note 86856 deleted from function.shmop-open by danbrown
| From: | danbrown@php.net | Date: | Thu, 06 Nov 2008 21:43:01 +0000 |
| Subject: | note 86856 deleted from function.shmop-open by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-146252@lists.php.net to get a copy of this message | ||
Note Submitter: inzhekov at yahoo dot com
----
<?
# Copyright (C) 2008 Ivan Zhekov - inzhekov at yahoo dot com
#
# You can redistribute this code and/or modify it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, either version 2 of the License, or (at your option)
# any later version.
#
# See the GNU General Public License for more details.
# <http://www.gnu.org/licenses/>
class Cache {
const CACHE_IDENT = 'PHP_SHARED_MEMORY_CACHE_IDENT';
const CACHE_IDENT_SIZE = 29;
function __construct($id, $chunk_size = 1024, $compress = true) {
$this->chunk_size = $chunk_size;
$this->compress = $compress;
// 2 bytes of information to store data length (needed to support compression)
// 65536 (16 bits) is the hash size
$this->memory_size = ($this->chunk_size + 2) * 65536 + self::CACHE_IDENT_SIZE;
// Allocate shared memory
$this->data_id = shmop_open($id, "c", 0644, $this->memory_size);
$ident = shmop_read($this->data_id, 0, self::CACHE_IDENT_SIZE);
// If CACHE_IDENT not found, clear the newly allocated memory block
if ($ident != self::CACHE_IDENT) {
// Create an empty block
$null_data = "";
for ($i = 0; $i < $this->chunk_size; $i++) {
$null_data .= ord(0);
}
// If cache is not active, fill cache memory with zero bytes
for ($i = 0; $i < 65536; $i++) {
shmop_write($this->data_id, $null_data, self::CACHE_IDENT_SIZE + ($i * ($this->chunk_size
+ 2)));
}
// Mark the block is initialized
shmop_write($this->data_id, self::CACHE_IDENT, 0);
}
}
function writeMem($key, $value) {
// Calculate hash
$hash = $this->calcMD5Hash($key);
// If block already used, read it to append data
$data = readMem($key);
// Add new data
$data[$key] = $value;
// Serialize it and compress it, if needed
if ($this->compress) {
$data_block = gzdeflate(serialize($data));
} else {
$data_block = serialize($data);
}
// Calculate size bytes and append it to data block
$size = strlen($data_block);
$size_block = chr($size % 256) . chr(floor($size / 256));
$data_block = $size_block . $data_block;
// Throw error if there is not enough space in the hash chunk
if (strlen($data_block) > $this->chunk_size) {
throw new Exception("Hash chunk overflown. Cache cannot allocate " .
strlen($data_block) . " bytes of data storage.");
}
// Write it into the shared memory
shmop_write($this->data_id, $data_block, $hash);
}
function readMem($key = null) {
$hash = $this->calcMD5Hash($key);
// Get data block size
$size_block = shmop_read($this->data_id, $hash, 2);
$size = ord($size_block[0]) + ord($size_block[1]) * 256;
if ($size) {
// Read data
$data_block = shmop_read($this->data_id, ($hash + 2), $size);
// Deserialize data block
if ($this->compress) {
$data = unserialize(gzinflate($data_block));
} else {
$data = unserialize($data_block);
}
} else {
$data = array();
}
return $data[$key];
}
function __destruct() {
shmop_close($this->data_id);
}
function calcMD5Hash($string)
{
$hash = md5($string);
return hexdec($hash[0] . $hash[1] . $hash[2] . $hash[3]) * ($this->chunk_size + 2) +
self::CACHE_IDENT_SIZE;
}
}
?>