<?php

// uglyyyyy... cannot override, so Registry pattern?! it's a sample only, lucky
define('CACHE_ENGINE_FILELOCK_PATH_LOCKFILE''./cache/*.tmp.lock');

class 
Cache_Engine_Filelock extends Cache_Engine_File
{
  
/**
   * all functions extended
   */
  
  /**
   * override waiting method for Cache_Engine_File
   * 
   * @param int|bool iWaitTimeout waiting timeout in microseconds or false not to wait or true for infinity waiting
   */
  
protected function _waitUnlock($iWaitTimeout)
  {
    if(
$iWaitTimeout)
    {
      try
      {
        
// quick first check
        
if(is_file($this->_path(false'lock')))
        {
          
// wait for unlock file
          
$iWaitTimeout /= 1000000;
          
$iLockTime microtime(true);
          
$bLockWait true;

          
// wait for the file
          
try
          {
            while(
is_file($this->_path(false'lock')))
            {
              
$iLockWaitDelta microtime(true) - $iLockTime;

              if(
$iLockWaitDelta $iWaitTimeout && $iWaitTimeout !== true)
                { 
$bLockWait false; break; }

              
usleep(rand(1999));
            }
          }
          
// cache lock path does not exists
          
catch(Cache_Exception_Runtime $oE) {}

          if(!
$bLockWait)
            throw new 
Cache_Exception_Runtime('Unable to access cache, it is totally locked, after "' $iWaitTimeout '" s.');
        }
      }
      
// cache lock path does not exists
      
catch(Cache_Exception_Runtime $oE) {}
    }
    else
    {
      try
      {
        if(
is_file($this->_path(false'lock')))
          throw new 
Cache_Exception_Runtime('Unable to access cache, it is currently locked, after "' $iWaitTimeout '" s.');
      }
      
// cache path does not exists
      
catch(Cache_Exception_Runtime $oE) {}
    }

    return 
true;
  }
  
  protected function 
_path($bAutogenerateDirectoryZonePath false$sMode null)
  {
    if(
$bAutogenerateDirectoryZonePath)
    {
      
// @todo
      // .. generate the path by mkdir() if does not exists
    
}
    
    
$sPathMode ($sMode == 'lock') ? CACHE_ENGINE_FILELOCK_PATH_LOCKFILE CACHE_ENGINE_FILE_PATH;
    
$sPath dirname($sPathMode);
    
    foreach(
$this->_oParent->_aZonePath as $sItem)
      if(!
is_dir($sPath .= $sItem '/'))
        throw new 
Cache_Exception_Runtime('Cache path does not exists at ' $sPath '.');
    
    
$sPath str_replace('*'$this->_oParent->_sZonebasename($sPathMode));
    return 
$sPath;
  }
}