public function save($key, $value, $ttl = 259200, $tags = NULL)
{
if (empty($key) || $value === NULL) {
$this->ReportError('empty key and null value are not allowed', __LINE__);
return false;
}
$key = (string) $key;
$auto_unlocker = NULL;
if (!$this->mutex->get_access_write($auto_unlocker)) {
return false;
}
$map = $this->mem_object->read('map');
$data_serialized = 0;
if (!is_scalar($value)) {
$value = serialize($value);
$data_serialized = 1;
}
$size = strlen($value);
if (empty($map)) {
$start = 0;
} else {
if (!array_key_exists($key, $map)) {
$start = $this->find_free_space($map, $size);
if ($start === false) {
$this->ReportError('Can not find enough space in memory', __LINE__);
return false;
}
} else {
if ($size <= $map[$key][self::map_key_fin] - $map[$key][self::map_key_start]) {
$start = $map[$key][self::map_key_start];
} else {
$this->del($key);
$this->del_old();
$map = $this->mem_object->read('map');
$start = $this->find_free_space($map, $size);
if ($start === false) {
$this->ReportError('Can not find enough space in memory', __LINE__);
return false;
}
}
}
}
$r = $this->write_data($value, $start);
if ($r === false) {
return false;
}
$set_ttl = 0;
$ttl = intval($ttl);
if ($ttl > self::max_ttl) {
$ttl = self::max_ttl;
}
if ($ttl > 0) {
$set_ttl = time() + $ttl;
}
$map[$key] = array(self::map_key_start => $start, self::map_key_fin => $start + $size);
if ($set_ttl > 0) {
$map[$key][self::map_key_ttl] = $set_ttl;
}
if ($data_serialized) {
$map[$key][self::map_key_serialized] = $data_serialized;
}
$r = $this->mem_object->save('map', $map);
if ($r === false) {
$this->ReportError('map was not saved', __LINE__);
return false;
}
if (!empty($tags)) {
if (!is_array($tags)) {
$tags = array($tags);
}
$tags_was_changed = false;
$mem_tags = $this->mem_object->read('tags');
foreach ($tags as $tag) {
if (empty($mem_tags[$tag]) || !in_array($key, $mem_tags[$tag])) {
$mem_tags[$tag][] = $key;
$tags_was_changed = true;
}
}
if ($tags_was_changed) {
$this->mem_object->save('tags', $mem_tags);
}
}
return true;
}