Commit 8dcb8f26 authored by doctrine's avatar doctrine

Added a folder remotely

parent 1ddb9159
<?php
/**
* Doctrine_CacheFile
* @author Konsta Vesterinen
* @package Doctrine ORM
* @url www.phpdoctrine.com
* @license LGPL
* @version 1.0 alpha
*/
class Doctrine_Cache_File implements Countable {
const STATS_FILE = "stats.cache";
/**
* @var string $path path for the cache files
*/
private $path;
/**
* @var array $fetched an array of fetched primary keys
*/
private $fetched = array();
/**
* @var Doctrine_Table $objTable
*/
private $objTable;
/**
* constructor
* @param Doctrine_Table $objTable
*/
public function __construct(Doctrine_Table $objTable) {
$this->objTable = $objTable;
$name = $this->getTable()->getTableName();
$manager = Doctrine_Manager::getInstance();
$dir = $manager->getAttribute(Doctrine::ATTR_CACHE_DIR);
if( ! is_dir($dir))
mkdir($dir, 0777);
if( ! is_dir($dir.DIRECTORY_SEPARATOR.$name))
mkdir($dir.DIRECTORY_SEPARATOR.$name, 0777);
$this->path = $dir.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
/**
* create stats file
*/
if( ! file_exists($this->path.self::STATS_FILE))
touch($this->path.self::STATS_FILE);
}
/**
* @return Doctrine_Table
*/
public function getTable() {
return $this->objTable;
}
/**
* @return integer number of cache files
*/
public function count() {
$c = -1;
foreach(glob($this->path."*.cache") as $file) {
$c++;
}
return $c;
}
/**
* getStats
* @return array an array of fetch statistics, keys as primary keys
* and values as fetch times
*/
public function getStats() {
$f = file_get_contents($this->path.self::STATS_FILE);
// every cache file starts with a ":"
$f = substr(trim($f),1);
$e = explode(":",$f);
return array_count_values($e);
}
/**
* store store a Doctrine_Record into file cache
* @param Doctrine_Record $record data access object to be stored
* @return boolean whether or not storing was successful
*/
public function store(Doctrine_Record $record) {
if($record->getState() != Doctrine_Record::STATE_CLEAN)
return false;
$file = $this->path.$record->getID().".cache";
if(file_exists($file))
return false;
$clone = clone $record;
$id = $clone->getID();
$fp = fopen($file,"w+");
fwrite($fp,serialize($clone));
fclose($fp);
$this->fetched[] = $id;
return true;
}
/**
* clean
* @return void
*/
public function clean() {
$stats = $this->getStats();
arsort($stats);
$size = $this->objTable->getAttribute(Doctrine::ATTR_CACHE_SIZE);
$count = count($stats);
$i = 1;
$preserve = array();
foreach($stats as $id => $count) {
if($i > $size)
break;
$preserve[$id] = true;
$i++;
}
foreach(glob($this->path."*.cache") as $file) {
$e = explode(".",basename($file));
$c = count($e);
$id = $e[($c - 2)];
if( ! isset($preserve[$id]))
@unlink($this->path.$id.".cache");
}
$fp = fopen($this->path.self::STATS_FILE,"w+");
fwrite($fp,"");
fclose($fp);
}
/**
* @param integer $id primary key of the DAO
* @return string filename and path
*/
public function getFileName($id) {
return $this->path.$id.".cache";
}
/**
* @return array an array of fetched primary keys
*/
public function getFetched() {
return $this->fetched;
}
/**
* fetch fetch a Doctrine_Record from the file cache
* @param integer $id
*/
public function fetch($id) {
$name = $this->getTable()->getComponentName();
$file = $this->path.$id.".cache";
if( ! file_exists($file))
throw new InvalidKeyException();
$data = file_get_contents($file);
$record = unserialize($data);
if( ! ($record instanceof Doctrine_Record)) {
// broken file, delete silently
$this->delete($id);
throw new InvalidKeyException();
}
$this->fetched[] = $id;
return $record;
}
/**
* exists check the existence of a cache file
* @param integer $id primary key of the cached DAO
* @return boolean whether or not a cache file exists
*/
public function exists($id) {
$name = $this->getTable()->getComponentName();
$file = $this->path.$id.".cache";
return file_exists($file);
}
/**
* deleteAll
* @return void
*/
public function deleteAll() {
foreach(glob($this->path."*.cache") as $file) {
@unlink($file);
}
$fp = fopen($this->path.self::STATS_FILE,"w+");
fwrite($fp,"");
fclose($fp);
}
/**
* delete delete a cache file
* @param integer $id primary key of the cached DAO
*/
public function delete($id) {
$file = $this->path.$id.".cache";
if( ! file_exists($file))
return false;
@unlink($file);
return true;
}
/**
* deleteMultiple delete multiple cache files
* @param array $ids an array containing cache file ids
* @return integer the number of files deleted
*/
public function deleteMultiple(array $ids) {
$deleted = 0;
foreach($ids as $id) {
if($this->delete($id)) $deleted++;
}
return $deleted;
}
/**
* destructor
* the purpose of this destructor is to save all the fetched
* primary keys into the cache stats
*/
public function __destruct() {
if( ! empty($this->fetched)) {
$fp = fopen($this->path.self::STATS_FILE,"a");
fwrite($fp,":".implode(":",$this->fetched));
fclose($fp);
}
/**
*
* cache auto-cleaning algorithm
* $ttl is the number of page loads between each cache cleaning
* the default is 100 page loads
*
* this means that the average number of page loads between
* each cache clean is 100 page loads (= 100 constructed Doctrine_Managers)
*
*/
$ttl = $this->objTable->getAttribute(Doctrine::ATTR_CACHE_TTL);
$l1 = (mt_rand(1,$ttl) / $ttl);
$l2 = (1 - 1/$ttl);
if($l1 > $l2)
$this->clean();
}
}
?>
<?php
class Doctrine_Cache_Manager {
}
?>
<?php
class Doctrine_Cache_Memcache extends Doctrine_Cache {
}
?>
<?php
class Doctrine_Cache_Sqlite {
/**
* STATS_FILE constant
* the name of the statistics file
*/
const STATS_FILE = "stats.cache";
/**
* SELECT constant
* used as a base for SQL SELECT queries
*/
const SELECT = "SELECT object FROM %s WHERE id %s";
/**
* INSERT constant
* used as a base for SQL INSERT queries
*/
const INSERT = "REPLACE INTO %s (id, object) VALUES (?, ?)";
/**
* DELETE constant
* used as a base for SQL DELETE queries
*/
const DELETE = "DELETE FROM %s WHERE id %s";
/**
* @var Doctrine_Table $table
*/
private $table;
/**
* @var PDO $dbh
*/
private $dbh;
/**
* @var array $fetched an array of fetched primary keys
*/
private $fetched = array();
public function __construct(Doctrine_Table $table) {
$this->table = $table;
$dir = $this->table->getSession()->getAttribute(Doctrine::ATTR_CACHE_DIR);
if( ! is_dir($dir))
mkdir($dir, 0777);
$this->path = $dir.DIRECTORY_SEPARATOR;
$this->dbh = $this->table->getSession()->getCacheHandler();
try {
$this->dbh->query("CREATE TABLE ".$this->table->getTableName()." (id INTEGER UNIQUE, object TEXT)");
} catch(PDOException $e) {
}
/**
* create stats file
*/
if( ! file_exists($this->path.self::STATS_FILE))
touch($this->path.self::STATS_FILE);
}
/*
* stores a Doctrine_Record into cache
* @param Doctrine_Record $record record to be stored
* @return boolean whether or not storing was successful
*/
public function store(Doctrine_Record $record) {
if($record->getState() != Doctrine_Record::STATE_CLEAN)
return false;
$clone = clone $record;
$id = $clone->getID();
$stmt = $this->dbh->query(sprintf(self::INSERT,$this->table->getTableName()));
$stmt->execute(array($id, serialize($clone)));
return true;
}
/**
* fetches a Doctrine_Record from the cache
* @param mixed $id
* @return mixed false on failure, Doctrine_Record on success
*/
public function fetch($id) {
$stmt = $this->dbh->query(sprintf(self::SELECT,$this->table->getTableName(),"= ?"));
$stmt->execute(array($id));
$data = $stmt->fetch(PDO::FETCH_NUM);
if($data === false)
throw new InvalidKeyException();
$this->fetched[] = $id;
$record = unserialize($data[0]);
if(is_string($record)) {
$this->delete($id);
throw new InvalidKeyException();
}
return $record;
}
/**
* fetches multiple records from the cache
* @param array $keys
* @return mixed false on failure, an array of Doctrine_Record objects on success
*/
public function fetchMultiple(array $keys) {
$count = (count($keys)-1);
$keys = array_values($keys);
$sql = sprintf(self::SELECT,$this->table->getTableName(),"IN (".str_repeat("?, ",$count)."?)");
$stmt = $this->dbh->query($sql);
$stmt->execute($keys);
while($data = $stmt->fetch(PDO::FETCH_NUM)) {
$array[] = unserialize($data[0]);
}
$this->fetched = array_merge($this->fetched, $keys);
if( ! isset($array))
return false;
return $array;
}
/**
* deletes all records from cache
* @return void
*/
public function deleteAll() {
$stmt = $this->dbh->query("DELETE FROM ".$this->table->getTableName());
return $stmt->rowCount();
}
/**
* @param mixed $id
* @return void
*/
public function delete($id) {
$stmt = $this->dbh->query(sprintf(self::DELETE,$this->table->getTableName(),"= ?"));
$stmt->execute(array($id));
if($stmt->rowCount() > 0)
return true;
return false;
}
/**
* count
* @return integer
*/
public function count() {
$stmt = $this->dbh->query("SELECT COUNT(*) FROM ".$this->table->getTableName());
$data = $stmt->fetch(PDO::FETCH_NUM);
// table has two columns so we have to divide the count by two
return ($data[0] / 2);
}
/**
* @param array $keys
* @return integer
*/
public function deleteMultiple(array $keys) {
if(empty($keys))
return 0;
$keys = array_values($keys);
$count = (count($keys)-1);
$sql = sprintf(self::DELETE,$this->table->getTableName(),"IN (".str_repeat("?, ",$count)."?)");
$stmt = $this->dbh->query($sql);
$stmt->execute($keys);
return $stmt->rowCount();
}
/**
* getStats
* @return array an array of fetch statistics, keys as primary keys
* and values as fetch times
*/
public function getStats() {
$f = file_get_contents($this->path.self::STATS_FILE);
// every cache file starts with a ":"
$f = substr(trim($f),1);
$e = explode(":",$f);
return array_count_values($e);
}
/**
* clean
* @return void
*/
public function clean() {
$stats = $this->getStats();
asort($stats);
$size = $this->table->getAttribute(Doctrine::ATTR_CACHE_SIZE);
$count = count($stats);
if($count <= $size)
return 0;
$e = $count - $size;
$keys = array();
foreach($stats as $id => $count) {
if( ! $e--)
break;
$keys[] = $id;
}
return $this->deleteMultiple($keys);
}
/**
* saves statistics
* @return boolean
*/
public function saveStats() {
if( ! empty($this->fetched)) {
$fp = fopen($this->path.self::STATS_FILE,"a");
fwrite($fp,":".implode(":",$this->fetched));
fclose($fp);
$this->fetched = array();
return true;
}
return false;
}
/**
* autoClean
* $ttl is the number of page loads between each cache cleaning
* the default is 100 page loads
*
* this means that the average number of page loads between
* each cache clean is 100 page loads (= 100 constructed Doctrine_Managers)
* @return boolean
*/
public function autoClean() {
$ttl = $this->table->getAttribute(Doctrine::ATTR_CACHE_TTL);
$l1 = (mt_rand(1,$ttl) / $ttl);
$l2 = (1 - 1/$ttl);
if($l1 > $l2) {
$this->clean();
return true;
}
return false;
}
/**
* @param mixed $id
*/
public function addDelete($id) {
$this->delete[] = $id;
}
/**
* destructor
* the purpose of this destructor is to save all the fetched
* primary keys into the cache stats and to clean cache if necessary
*
*/
public function __destruct() {
$this->saveStats();
$this->autoClean();
}
}
?>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment