dtdfl62844 2013-03-06 22:10
浏览 33
已采纳

PHP shmop id引用和数组大小

I'm attempting to simplify calls to cache functions by writing functions to handle the arrays and naming automatically. This should work in most cases where the data is updated infrequently. Here's what I got so far:

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;
}

The problem is the first line in the get_cache($name) function. Since this is to be dynamic I would need to find the size of the array requested based on the string $name and referencing it with my id list in get_cache_id($name). The problem is to use shmop_open I need the size from shmop_size, but to use shmop_size I first need to shmop_open.... Lastly my apache error log, line 13 is the assignment of the $id variable in get_cache($name).

[Wed Mar 06 15:57:57 2013] [error] [client 127.0.0.1] PHP Warning: shmop_size(): no shared memory segment with an id of [1] in /home/mark/htdocs/phplib/cache.php on line 13 [Wed Mar 06 15:57:57 2013] [error] [client 127.0.0.1] PHP Notice: unserialize(): Error at offset 7765 of 7769 bytes in /home/mark/htdocs/phplib/cache.php on line 14

Edit: working code & implementation - In addition to the answer below, this script's get_array_size function is wrong and should be completely omitted. Instead, in the save_cache function use strlen(serialize($data)) to determine size of cache to store. In addition you'll need to delete the previously stored cache of that ID. The final script should look like:

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));
}

Example call to this function for use in AJAX autocomplete search:

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()."

 $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);
  • 写回答

1条回答 默认 最新

  • douchen4915 2013-03-06 22:24
    关注

    Look at the note in the function instructions: shmop_open

    shmop_open 3rd and 4th parameters should be 0 when opening an already existing segment. If you are getting a cache, the segement should already be created, therefore you don't need to get the segment size in get_cache.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题