ultimix
cache.php
Go to the documentation of this file.
1 <?php
2 
3  /*
4  * This source code is a part of the Ultimix Project.
5  * It is distributed under BSD license. All other third side source code (like tinyMCE) is distributed under
6  * it's own license wich could be found from the corresponding files or sources.
7  * This source code is provided "as is" without any warranties or garanties.
8  *
9  * Have a nice day!
10  *
11  * @url http://ultimix.sorceforge.net
12  *
13  * @author Alexey "gdever" Dodonov
14  */
15 
26  class cache_1_0_0{
27 
38  var $Cache;
39 
50  var $Security = false;
51 
62  var $CacheWasUpdated = false;
63 
74  var $TableOfContents = false;
75 
86  var $CacheSwitch = true;
87 
98  var $CacheTimeout = 120;
99 
114  function __construct()
115  {
116  try
117  {
118  $this->Security = get_package( 'security' , 'last' , __FILE__ );
119  $PageName = $this->Security->get_gp( 'page_name' , 'command' , 'default' );
120 
121  $this->Cache = @file_get_contents( dirname( __FILE__ ).'/data/'.$PageName.'.cache' );
122 
123  $this->TableOfContents = @file_get_contents( dirname( __FILE__ ).'/data/'.$PageName.'.table' );
124 
125  if( $this->TableOfContents !== false )
126  {
127  $this->TableOfContents = unserialize( $this->TableOfContents );
128  }
129 
130  $this->reset();
131  }
132  catch( Exception $e )
133  {
134  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
135  }
136  }
137 
152  function reset()
153  {
154  try
155  {
156  $Conf = file_get_contents( dirname( __FILE__ ).'/conf/cf_cache' );
157  $Conf = explode( ';' , $Conf );
158  $Conf[ 0 ] = explode( '=' , $Conf[ 0 ] );
159  $Conf[ 1 ] = explode( '=' , $Conf[ 1 ] );
160  $this->CacheSwitch = $Conf[ 0 ][ 1 ] == 'on';
161  $this->CacheTimeout = intval( $Conf[ 1 ][ 1 ] );
162  }
163  catch( Exception $e )
164  {
165  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
166  }
167  }
168 
191  private function get_header_parameters( $md5SectionOriginName )
192  {
193  try
194  {
195  $HeaderSize = 32 + 1 + 32 + 1;
196 
197  $ReadCursor = $this->TableOfContents[ $md5SectionOriginName ][ 'read_cursor' ];
198 
199  $SectionSize = $this->TableOfContents[ $md5SectionOriginName ][ 'section_size' ];
200 
201  return( array( $HeaderSize , $ReadCursor , $SectionSize ) );
202  }
203  catch( Exception $e )
204  {
205  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
206  }
207  }
208 
231  private function fetch_data( $md5SectionOriginName )
232  {
233  try
234  {
235  list( $HeaderSize , $Cursor , $SectionSize ) = $this->get_header_parameters( $md5SectionOriginName );
236 
237  return( substr( $this->Cache , $Cursor + $HeaderSize , $SectionSize - $HeaderSize ) );
238  }
239  catch( Exception $e )
240  {
241  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
242  }
243  }
244 
267  function get_data( $SectionOriginName )
268  {
269  try
270  {
271  if( $this->TableOfContents === false )
272  {
273  return( false );
274  }
275 
276  $md5SectionOriginName = md5( $SectionOriginName );
277  if( isset( $this->TableOfContents[ $md5SectionOriginName ] ) === false )
278  {
279  return( false );
280  }
281 
282  $CreateDate = $this->TableOfContents[ $md5SectionOriginName ][ 'tags' ][ '_timeout' ];
283  if( time() - $CreateDate > $this->CacheTimeout )
284  {
285  $this->delete_data( $SectionOriginName );
286  return( false );
287  }
288 
289  return( $this->fetch_data( $md5SectionOriginName ) );
290  }
291  catch( Exception $e )
292  {
293  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
294  }
295  }
296 
319  private function update_cache( $md5SectionOriginName , $Data )
320  {
321  try
322  {
323  list( $HeaderSize , $Cursor , $SectionSize ) = $this->get_header_parameters( $md5SectionOriginName );
324 
325  $NewDataSize = strlen( $Data );
326 
327  $this->Cache = substr_replace(
328  $this->Cache ,
329  $md5SectionOriginName.':'.sprintf( "%032d" , $NewDataSize + $HeaderSize ).':'.$Data ,
330  $Cursor ,
331  $SectionSize
332  );
333  }
334  catch( Exception $e )
335  {
336  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
337  }
338  }
339 
362  private function update_table( $md5SectionOriginName , $Data )
363  {
364  try
365  {
366  list( $HeaderSize , $Cursor , $SectionSize ) = $this->get_header_parameters( $md5SectionOriginName );
367 
368  $NewDataSize = strlen( $Data );
369 
370  $NewTable = array();
371  foreach( $this->TableOfContents as $Key => $Value )
372  {
373  if( $Value[ 'read_cursor' ] === $Cursor )
374  {
375  $Value[ 'section_size' ] = $HeaderSize + $NewDataSize;
376  }
377  elseif( $Value[ 'read_cursor' ] > $Cursor )
378  {
379  $Value[ 'read_cursor' ] += $HeaderSize + $NewDataSize - $SectionSize;
380  }
381  $Value[ 'tags' ][ '_timeout' ] = time();
382  $NewTable[ $Key ] = $Value;
383  }
384  $this->TableOfContents = $NewTable;
385  }
386  catch( Exception $e )
387  {
388  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
389  }
390  }
391 
414  function set_data( $SectionOriginName , $Data )
415  {
416  try
417  {
418  if( $this->TableOfContents === false )
419  {
420  throw( new Exception( 'Cache is empty' ) );
421  }
422  $md5SectionOriginName = md5( $SectionOriginName );
423  if( isset( $this->TableOfContents[ $md5SectionOriginName ] ) )
424  {
425  $this->update_cache( $md5SectionOriginName , $Data );
426 
427  $this->update_table( $md5SectionOriginName , $Data );
428 
429  if( $this->CacheSwitch === true )
430  {
431  $this->CacheWasUpdated = true;
432  }
433  }
434  else
435  {
436  throw( new Exception( 'Section '.$SectionOriginName.' was not found' ) );
437  }
438  }
439  catch( Exception $e )
440  {
441  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
442  }
443  }
444 
475  function add_data( $SectionOriginName , $Data , $Tags = array() )
476  {
477  try
478  {
479  $this->delete_data( $SectionOriginName );
480  $md5SectionOriginName = md5( $SectionOriginName );
481  $SectionSize = 32 + 1 + 32 + 1 + strlen( $Data );
482  $this->TableOfContents[ $md5SectionOriginName ] = array(
483  'section_size' => $SectionSize , 'read_cursor' => strlen( $this->Cache )
484  );
485  $this->Cache .= $md5SectionOriginName.":".sprintf( "%032d" , $SectionSize ).":$Data";
486  $this->TableOfContents[ $md5SectionOriginName ][ 'tags' ] = array_merge(
487  $Tags , array( '_cache_sys' , '_timeout' => time() )
488  );
489 
490  if( $this->CacheSwitch === true )
491  {
492  $this->CacheWasUpdated = true;
493  }
494  }
495  catch( Exception $e )
496  {
497  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
498  }
499  }
500 
519  function delete_data( $SectionOriginName )
520  {
521  try
522  {
523  if( $this->CacheSwitch === false )
524  {
525  return;
526  }
527  $this->delete_section( md5( $SectionOriginName ) );
528  }
529  catch( Exception $e )
530  {
531  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
532  }
533  }
534 
560  function data_exists( $SectionOriginName )
561  {
562  try
563  {
564  if( $this->TableOfContents === false )
565  {
566  return( false );
567  }
568  else
569  {
570  return( isset( $this->TableOfContents[ md5( $SectionOriginName ) ] ) );
571  }
572  }
573  catch( Exception $e )
574  {
575  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
576  }
577  }
578 
605  private function compile_new_table_of_contents( $ReadCursor , $SectionSize )
606  {
607  try
608  {
609  $NewTable = array();
610 
611  foreach( $this->TableOfContents as $Key => $Value )
612  {
613  if( $Value[ 'read_cursor' ] === $ReadCursor )
614  {
615  /* nop */
616  }
617  else
618  {
619  if( $Value[ 'read_cursor' ] > $ReadCursor )
620  {
621  $Value[ 'read_cursor' ] -= $SectionSize;
622  }
623  $NewTable[ $Key ] = $Value;
624  }
625  }
626 
627  return( $NewTable );
628  }
629  catch( Exception $e )
630  {
631  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
632  }
633  }
634 
653  private function delete_section( $SectionName )
654  {
655  try
656  {
657  if( $this->TableOfContents !== false && isset( $this->TableOfContents[ $SectionName ] ) )
658  {
659  $ReadCursor = $this->TableOfContents[ $SectionName ][ 'read_cursor' ];
660  $SectionSize = $this->TableOfContents[ $SectionName ][ 'section_size' ];
661  $this->Cache = substr_replace( $this->Cache , '' , $ReadCursor , $SectionSize );
662 
666  $this->TableOfContents = $this->compile_new_table_of_contents( $ReadCursor , $SectionSize );
667 
668  $this->CacheWasUpdated = true;
669  }
670  }
671  catch( Exception $e )
672  {
673  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
674  }
675  }
676 
695  function delete_data_by_tag( $Tag )
696  {
697  try
698  {
699  if( $this->CacheSwitch === false )
700  {
701  return;
702  }
703  $Sections = array();
704 
705  foreach( $this->TableOfContents as $Key => $Value )
706  {
707  if( array_search( $Tag , $Value[ 'tags' ] ) !== false )
708  {
709  $Sections [] = $Key;
710  }
711  }
712 
713  foreach( $Sections as $Key => $Value )
714  {
715  $this->delete_section( $Value );
716  }
717  }
718  catch( Exception $e )
719  {
720  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
721  }
722  }
723 
738  function flush()
739  {
740  try
741  {
742  if( $this->CacheWasUpdated && $this->CacheSwitch === true )
743  {
744  $this->drop_cache();
745 
746  $PageName = $this->Security->get_gp( 'page_name' , 'command' , 'default' );
747 
750  file_put_contents( dirname( __FILE__ ).'/data/'.$PageName.'.cache' , $this->Cache );
751 
754  file_put_contents(
755  dirname( __FILE__ ).'/data/'.$PageName.'.table' , serialize( $this->TableOfContents )
756  );
757  }
758  }
759  catch( Exception $e )
760  {
761  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
762  }
763  }
764 
779  function drop_cache()
780  {
781  try
782  {
783  $PageName = $this->Security->get_gp( 'page_name' , 'command' , 'default' );
784 
785  @unlink( dirname( __FILE__ ).'./data/'.$PageName.'.cache' );
786  @unlink( dirname( __FILE__ ).'./data/'.$PageName.'.table' );
787  }
788  catch( Exception $e )
789  {
790  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
791  }
792  }
793 
808  function __destruct()
809  {
810  try
811  {
812  if( $this->CacheSwitch === false )
813  {
814  return;
815  }
816 
817  $this->flush();
818  }
819  catch( Exception $e )
820  {
821  $a = func_get_args();_throw_exception_object( __METHOD__ , $a , $e );
822  }
823  }
824  }
825 
826 ?>