PHP shmop id справка и размер на масива

Опитвам се да опростя извикванията на функциите за кеширане, като напиша функции за обработка на масивите и автоматично именуване. Това трябва да работи в повечето случаи, когато данните се актуализират рядко. Ето какво имам досега:

function save_cache($data, $name) {
    // get id for name of cache
    $id=shmop_open(get_cache_id($name), "c", 0644, get_array_size($data));

    // return int for data size or boolean false for fail
    if ($id) return shmop_write($id, serialize($data), 0);
    else return false;
}

function get_cache($name) {
    $id=shmop_open(get_cache_id($name), "a", 0644, shmop_size(get_cache_id($name)));
    if ($id) $data=unserialize(shmop_read($id, 0, shmop_size($id)));
    else return false;          // failed to load data

    if ($data) return $data;    // array retrieved
    else return false;          // failed to load data
}

function get_cache_id($name) {
    // build list to return a number for a string id
    // maintain this as new caches are created
    $id=array(  'test'  => 1,
                'test2' => 2
                );

    return $id[$name];
}

function get_array_size($a){
    $size = 0;
    while(list($k, $v) = each($a))$size += is_array($v) ? get_array_size($v) : strlen($v);
    return $size;
}

Проблемът е първият ред във функцията get_cache($name). Тъй като това трябва да бъде динамично, ще трябва да намеря размера на заявения масив въз основа на низа $name и да го препратя с моя списък с id в get_cache_id($name). Проблемът е да използвам shmop_open, имам нужда от размера от shmop_size, но за да използвам shmop_size, първо трябва да shmop_open.... И накрая, моят регистър за грешки на apache, ред 13 е присвояването на променливата $id в get_cache($name).

[Сряда, 6 март, 15:57:57 2013 г.] [грешка] [клиент 127.0.0.1] PHP предупреждение: shmop_size(): няма сегмент от споделена памет с идентификатор [1] в /home/mark/htdocs/phplib/cache. php на линия 13 [сряда, 6 март, 15:57:57 2013] [грешка] [клиент 127.0.0.1] PHP бележка: unserialize(): Грешка при отместване 7765 от 7769 байта в /home/mark/htdocs/phplib/cache. php на ред 14

Редактиране: работен код и реализация - В допълнение към отговора по-долу, функцията get_array_size на този скрипт е грешна и трябва да бъде напълно пропусната. Вместо това във функцията save_cache използвайте strlen(serialize($data)), за да определите размера на кеша за съхранение. Освен това ще трябва да изтриете съхранения преди това кеш на този идентификатор. Крайният скрипт трябва да изглежда така:

function save_cache($data, $name, $timeout) {
    // delete cache
    $id=shmop_open(get_cache_id($name), "a", 0, 0);
    shmop_delete($id);
    shmop_close($id);

    // get id for name of cache
    $id=shmop_open(get_cache_id($name), "c", 0644, strlen(serialize($data)));

    // return int for data size or boolean false for fail
    if ($id) {
        set_timeout($name, $timeout);
        return shmop_write($id, serialize($data), 0);
    }
    else return false;
}

function get_cache($name) {
    if (!check_timeout($name)) {
        $id=shmop_open(get_cache_id($name), "a", 0, 0);

        if ($id) $data=unserialize(shmop_read($id, 0, shmop_size($id)));
        else return false;          // failed to load data

        if ($data) {                // array retrieved
            shmop_close();
            return $data;
        }
        else return false;          // failed to load data
    }
    else return false;              // data was expired
}

function get_cache_id($name) {
    $id=array(  'test1' => 1
                'test2' => 2
                );

    return $id[$name];
}

function set_timeout($name, $int) {
    $timeout=new DateTime(date('Y-m-d H:i:s'));
    date_add($timeout, date_interval_create_from_date_string("$int seconds"));
    $timeout=date_format($timeout, 'YmdHis');

    $id=shmop_open(100, "a", 0, 0);
    if ($id) $tl=unserialize(shmop_read($id, 0, shmop_size($id)));
    else $tl=array();
    shmop_delete($id);
    shmop_close($id);

    $tl[$name]=$timeout;
    $id=shmop_open(100, "c", 0644, strlen(serialize($tl)));
    shmop_write($id, serialize($tl), 0);
}

function check_timeout($name) {
    $now=new DateTime(date('Y-m-d H:i:s'));
    $now=date_format($now, 'YmdHis');

    $id=shmop_open(100, "a", 0, 0);
    if ($id) $tl=unserialize(shmop_read($id, 0, shmop_size($id)));
    else return true;
    shmop_close($id);

    $timeout=$tl[$name];
    return (intval($now)>intval($timeout));
}

Примерно извикване на тази функция за използване при търсене с автоматично довършване на AJAX:

header('Content-type: application/json; charset=utf-8');
include '../phplib/conn.php';
include '../phplib/cache.php';

$searchTerm=$_GET['srch'];
$test=array();
$test=get_cache('test');
if (!$test) {
    $odbc=odbc_connection(); // defined in conn.php
    $sql="SELECT * FROM mysearchtable";
    $result=odbc_exec($odbc, $sql) or
        die("<pre>".date('[Y-m-d][H:i:s]').
        " Error: [".odbc_error()."] ".odbc_errormsg()."\n\n $sql");

    $i=0;
    while ($row=odbc_fetch_array($result)) {
        foreach ($row as $key => $value) $row[$key]=trim($value);
        $test[$i]=$row;
        $i++;
    }

    save_cache($test, 'test1', 600); // 10 minutes timeout
    odbc_close($odbc);
}

$result=array();
foreach ($test as $key) {
    if (strpos($key['item'])===0) { // starts the string
    // if (strpos($key['item'])!==false) { // in the string anywhere
        $result[]=array('item' => $key['item'], 'label' => $key['label']);
    }
}

echo json_encode($result);

person MaKR    schedule 06.03.2013    source източник


Отговори (1)


Вижте бележката в инструкциите за функцията: shmop_open

shmop_open 3-ти и 4-ти параметър трябва да бъдат 0 при отваряне на вече съществуващ сегмент. Ако получавате кеш, сегментът вече трябва да е създаден, следователно не е необходимо да получавате размера на сегмента в get_cache.

person Quentin Skousen    schedule 06.03.2013