<?php
 
/**
 
 * @author Colin McKinnon
 
 * @licence LGPL version 3
 
 * @package item cache
 
 *
 
 * example of underflow/overflow handlers for itemCache
 
 *
 
 * e.g.
 
 *
 
 * $h = new ic_backend('localhost','user','s3cr3t','main.keystore');
 
 * list($overflow, $underflow)=$h->getHandlers();
 
 * $ic = new itemCache(200, $overflow, 10, $underflow);
 
 *
 
 * while ($r=fetch_input_set()) {
 
 *     $r['lookup']=$ic->get($r['key']);
 
 *       if ($r['lookup']==null) {
 
 *     // i.e. the database set is not complete either...
 
 *           $r['lookup']=go_fetch_value_using_expensive_lookup('$r['key']);
 
 *           $ic->add($r['key'], $r['lookup']);
 
 *           // NB the implicit true flag ensures the data will be written back 
 
 *           // when evicted
 
 *     }
 
 *       write_output_set($r);
 
 * }
 
 * $ic->flush(); 
 
 * exit;
 
 *
 
 * Of course a really efficient solution might benefit from using a 
 
 * second instance of itemCache to handle the I/O on the input set 
 
 * to batch write operations.
 
 * 
 
 */
 
class ic_backend {
 
    private $dbh;
 
    private $tableref;
 
 
    public function __construct($mysql_host, $mysql_user, $mysql_pass, $mysql_tableref)
 
    {
 
        $this->dbh=mysql_connect($mysql_host, $mysql_user, $mysql_pass);
 
        if (!$this->dbh) {
 
            trigger_error('Failed to conect to database: ' . mysql_error());
 
        }
 
        $this->tableref=$mysql_tableref;
 
    }
 
 
    public function getHandlers()
 
    {
 
        return array(
 
            'overflow'=>array($this, 'overflow'),
 
            'underflow'=>array($this, 'underflow'));
 
    }
 
  /**
 
   * @param mixed $key
 
   * @param object $itemCache
 
   *
 
   * It's the responsibility of the handler to insert the entry
 
   * into the cache. 
 
   */
 
    public function underflow($key, $itemCache)
 
    {
 
        $mykey=mysql_real_escape_string($key, $this->dbh);
 
        $qry="SELECT value FROM ' . $this->tableref . ' WHERE key='$mykey' LIMIT 0,1";
 
        $result=mysql_query($qry, $this->dbh);
 
        if ($result) {
 
            if ($row=mysql_fetch_assoc($result)) {
 
                $itemCache->add($key, $row['value'], false);
 
                // NB the false flag tells the cache not to write this
 
                // value back when evicted
 
            } else {
 
                /* Currently failed lookup (also missing from the database) 
 
                 * is not cacheable, but we might want to make it cacheable
 
                 * e.g.
 
                 * $itemCache->add($key, null);
 
                 */
 
            }
 
        } else {
 
            trigger_error('Error fetching data: ' . mysql_error());
 
        }
 
    }
 
  /**
 
   * @param array $data - array of ($key1=>$val1, $key2=>$val2....)
 
   *
 
   * invoked from itemCache
 
   */
 
    public function overflow($data)
 
    {
 
        $qry="INSERT IGNORE INTO " . $this->tableref . " (key, value) ";
 
        $join=' VALUES ';
 
        foreach ($data as $key=>$val) {
 
            $qry.=$join . "('" . mysql_real_escape_string($key, $this->dbh)
 
                . "','" . mysql_real_escape_string($value, $this->dbh) . "')";
 
            $join=',';
 
        }
 
        if (!mysql_query($qry, $this->dbh)) {
 
            trigger_error('Failed inserting data: ' . mysql_error());
 
        }
 
    }
 
}
 
 
 |