Location: PHPKode > projects > Simple Way to Usenet > libs/swun/rpc/rpc_cache_file.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */
class rpc_cache_file {
	
	private static $indexes = Array('date', 'title', 'size');
	private static $CACHE;
	private $LIST;

	public function __construct($conf){ 
		if (!isset(self::$CACHE) ){
			configs::set('file_repo', 'cache_rpc', Array('type'=>'local', 'conf'=>configs::get('hellarpc', 'cacheconf')));
			self::$CACHE = new file_abstract('cache_rpc');
			self::$CACHE->connect();			
		}
	}
	
	
	//Status
	public function set_status($rpc, $status){
		$hdl = self::$CACHE->file_open("/status_$rpc",'w+');
		if ( FALSE === $hdl ){ return FALSE; }
		$status = base64_encode(serialize($status));
		$o = self::$CACHE->file_put($hdl, $status);
		self::$CACHE->file_close($hdl);
		return $o;
	}
	
	public function get_status($rpc){
		if ( FALSE === self::$CACHE->isfile("/status_$rpc") ){ return FALSE; }
		$status = self::$CACHE->readfile("/status_$rpc");
		return unserialize(base64_decode($status));
	}
	
	public function status_isexpired($rpc, $to){
		if ( FALSE === self::$CACHE->isfile("/status_$rpc") ){ 
			return TRUE; 
		}
		clearstatcache();
		$last = self::$CACHE->getmtime("/status_$rpc");
		$periode = time() - $last;
		return ($periode >= $to );
	}
	
	public function get_lastreq($rpc){
		if ( FALSE === self::$CACHE->isfile("/status_$rpc") ){ return FALSE; }
		return self::$CACHE->getmtime("/status_$rpc");
	}
	
	public function set_lastbrw($rpc, $time){
		$hdl = self::$CACHE->file_open("/browse_$rpc",'w+');
		if ( FALSE === $hdl ){ return FALSE; }
		$o = self::$CACHE->file_put($hdl, $time);
		self::$CACHE->file_close($hdl);
		return $o;
	}
	
	public function get_lastbrw($rpc){
		if ( FALSE === self::$CACHE->isfile("/browse_$rpc") ){ return FALSE; }
		return self::$CACHE->readfile("/browse_$rpc");
	}
	
	
	
	//browser
	public function clean_browser($rpc){
		$p = '/'.$rpc;
		$limit = $this->get_lastbrw($rpc);
		//not older than lastbrw or remove ;)
		if ( FALSE === self::$CACHE->isdir($p) ){ return FALSE; }
		while ( FALSE !== ( $catid = self::$CACHE->readdir($p)) ){
			if ( self::$CACHE->isdir("$p/$catid") ){
				while ( FALSE !== ( $hash = self::$CACHE->readdir("$p/$catid")) ){
					if ( FALSE === ereg("index", $hash) ){
						if ( $limit > self::$CACHE->getmtime("$p/$catid/$hash") ){
							$data = self::$CACHE->readfile("$p/$catid/$hash");
							$data = unserialize(base64_decode($data));
							if ( FALSE !== $data ){
								echo "--- $p/$catid/$hash [".$data['title']."]\n";
								if ( !empty($data['engine']) ){ $this->remove_id($rpc, $data['engine'], $data['id']); }
							} else {
								 echo "--- $p/$catid/$hash\n";
							}
							self::$CACHE->remove("$p/$catid/$hash");
							$this->drop_indexes($rpc, $catid, $hash);
						}
					} 
				}
			} elseif ( FALSE === ereg("index", $catid) ){
				if ( $limit > self::$CACHE->getmtime("$p/$catid") ){
					echo "--- $p/$catid\n"; 
					self::$CACHE->remove("$p/$catid");
					$this->drop_indexes($rpc, '', $catid);
				} 
			}
		}
		return TRUE;
	}
	
	private function drop_indexes($rpc, $catid, $hash){
		$bp = "/$rpc/$catid";
		foreach(self::$indexes as $k => $index){
			$p = "$bp/index.$index";
			$data = self::$CACHE->readfile($p);
			if ( FALSE !== $data ){
				$data = split("\n", $data);
				foreach($data as $k => $line){
					if ( !empty($line) ){
						$buf = split("{--}", trim($line));
						if ( $buf[0] !== $hash ){ $ndata[$buf[0]] = $buf[1]; }
						unset($data[$k]);
					}
				}
				unset($data);
			}
			if ( isset($ndata) ){ 
				foreach($ndata as $hash => $val){ $data[] = $hash.'{--}'.$val; }
				if ( isset($data) ){
					$data = implode("\n", $data);
					$hdl = self::$CACHE->file_open($p, 'w+');
					if ( FALSE !== $hdl ){
						self::$CACHE->file_put($hdl, $data);
						self::$CACHE->file_close($hdl);
					}
				}
			}
		}
	}
	
	
	public function hash_iscached($rpc, $catid, $hash){ return self::$CACHE->isfile("/$rpc/$catid/$hash"); }
	
	public function update_item(&$ITEM){ 
		return $this->create_item(&$ITEM);
	}
	
	private function create_item(&$ITEM){
		$c = $ITEM->get_content();
		$data=Array('rpc'	=>$ITEM->get_rpc(),	
					'hash'	=>$ITEM->get_hash(),
					'catid'	=>$ITEM->get_catid(),
					'title'	=>$ITEM->get_title(),
					'data'	=>base64_encode(serialize($c)), 
					'engine'=>$ITEM->get_engine(),
					'id'	=>$ITEM->get_id(),
					'date'	=>$ITEM->get_date(),
					'size'	=>$c['size'],
					'time'	=>time() );
		$p = '/'.$data['rpc'];
		if ( FALSE === self::$CACHE->createdir($p, TRUE) ){ return FALSE; }
		$p .= '/'.$data['catid'];
		if ( FALSE === self::$CACHE->createdir($p, TRUE) ){ return FALSE; }
		$hdl = self::$CACHE->file_open("$p/".$data['hash'], 'w+');
		if ( FALSE === $hdl ){ return FALSE; }
		$buf = base64_encode(serialize($data));
		$o = self::$CACHE->file_put($hdl, $buf);
		unset($data);
		return $o;
	}
	
	public function insert_item(&$ITEM){
		$o = $this->create_item(&$ITEM);
		if ( $o ){
			$c = $ITEM->get_content();
			$data=Array('rpc'	=>$ITEM->get_rpc(),	
						'catid'	=>$ITEM->get_catid(),
						'hash'	=>$ITEM->get_hash(),
						'title'	=>$ITEM->get_title(),
						'date'	=>$ITEM->get_date(),
						'size'	=>$c['size'],
						'engine'=>$ITEM->get_engine(),
						'id'	=>$ITEM->get_id(),);
			unset($c);
			foreach(self::$indexes as $k => &$index){
				$this->append_to_index($data['rpc'], $data['catid'], $index, $data['hash'], $data[$index]);
			}
			if ( $data['engine'] != '' AND $data['id'] != '' ){
				$this->append_id($data['rpc'], $data['engine'], $data['id']);
			}
		}
		return $o;
	}
	
	
	private function append_id($rpc, $engine, $id){
		$p = "/$rpc/index.id";
		$ids = self::$CACHE->readfile($p);
		$ids = split("\n", trim($ids));
		foreach($ids as $k => &$entry){
			if ( $entry === "$engine:$id"){ return TRUE; }
		}
		$ids[count($ids)] = "$engine:$id";
		$ids = implode($ids, "\n");
		$hdl = self::$CACHE->file_open($p, 'w+');
		if ( FALSE === $hdl ){ return FALSE; }
		$o = self::$CACHE->file_put($hdl, $ids);
		self::$CACHE->file_close($hdl);
		return $o;
	}
	
	private function remove_id($rpc, $engine, $id){
		$p = "/$rpc/index.id";
		$ids = self::$CACHE->readfile($p);
		$ids = split("\n", trim($ids));
		foreach($ids as $k => &$entry){
			if ( $entry !== "$engine:$id"){ $nids[] = $entry; }
		}
		if ( isset($nids) ){
			$nids = implode($nids, "\n");
			$hdl = self::$CACHE->file_open($p, 'w+');
			if ( FALSE === $hdl ){ return FALSE; }
			$o = self::$CACHE->file_put($hdl, $nids);
			self::$CACHE->file_close($hdl);
			return $o;
		}
		return self::$CACHE->remove($p);
	}
	
	private function append_to_index($rpc, $catid, $index, $hash, $val){
		$p = "/$rpc/$catid/index.$index";
		$hdl = self::$CACHE->file_open($p, 'a');
		if ( FALSE === $hdl ){ return FALSE; }
		self::$CACHE->file_put($hdl, "$hash{--}$val\n");
		self::$CACHE->file_close($hdl);
	}
	
		
	public function listbycat($rpc, $catid, $order, $way){
		if ( !isset($this->LIST) ){
			$p = "/$rpc/$catid/index.$order";
			$data = self::$CACHE->readfile($p);
			if ( FALSE === $data ){ return FALSE; }
			$data = split("\n", trim($data));
			foreach($data as $k => $line){
				if ( !empty($line) ){
					$buf = split("{--}", trim($line));
					$this->LIST[$buf[0]] = $buf[1];
					unset($data[$k]);
				} 
			}
			unset($data);
			if ( !isset($this->LIST) ){ return FALSE; }
			
			if ( $way === 'ASC'){ 	array_multisort($this->LIST, SORT_ASC); }
			if ( $way === 'DESC'){ 	array_multisort($this->LIST, SORT_DESC); }
			
		}
		$hash = key(&$this->LIST);
		if ( FALSE === $hash OR empty($hash) ){ unset($this->LIST);return FALSE; }
		next(&$this->LIST);
		$p = "/$rpc/$catid/$hash";
		$data = self::$CACHE->readfile($p);
		if ( FALSE === $data ){ 
			errors::raise("data restore failed, $p not found", CORE_LOG_ERROR, 'RPCBRW'); 
			unset($this->LIST);return FALSE; 
		}
		$data = unserialize(base64_decode($data));
		if ( FALSE === $data ){ unset($this->LIST);return FALSE; }
		return $data;
	}
	
	public function idisonrpc($rpc, $engine, $id){
		$p = "/$rpc/index.id";
		$ids = self::$CACHE->readfile($p);
		$ids = split("\n", $ids);
		foreach($ids as $k => &$entry){
			if ( $entry === "$engine:$id"){ return TRUE; }
		}
		return FALSE;
		//keep ids in an other file, by rpc
	}
}
Return current item: Simple Way to Usenet