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