<?php
define('idDiGIR_status','$Id: DiGIR_status.php,v 1.5 2003/05/15 18:50:36 vieglais Exp $');
if (defined('idDIGIR_VERSION_REQUEST'))
    return;

include_once('DiGIR_globals.php');
/**
* records an operation in the status pickle and
* returns the current status information as # operation in the time period
* DiGIR_STATUSINTERVAL
*
* @param string $pickle  Name of the file that stores the status infomration
* @param integer $cop    Current operation. 1=metadata, 2=search, 3=inventory
*                        0 = do not update counter, just get data
* @return array    [0] = total, [1]=metadata, [2] = search, [3] = inventory
*/
function getStatus($interval,$pickle, $cop)
{
    $ctime = time();
    $oldtime = $ctime - $interval;
    $ntries = 5;
    $lockName = $pickle.".lock";
    $astatusData = array(0,0,0,0);
    $locked = 0;
    
    //keep trying for $ntries seconds
    while (($cop > 0) && ($ntries > 0))
    {
        if (mkdir($lockName,0777))
        {
            $locked = 1;
            $ntries = 0;
        }
        else
        {
            sleep(1);
            $ntries --;
        }
    }
    $fh = @fopen($pickle,'rb');
    $data = "";
    $astatus = array();
    $anew = array();
    if ($fh)
    {
        //load the status array
        while (!feof($fh))
        {
            $data .= fread($fh, 4096);
        }
        fclose($fh);
    }

    if ($data != "")
        $astatus = unserialize($data);
    
    //create a copy of the array with only entries for the
    //current time interval
    foreach ($astatus as $adata)
    {
        if ($adata[0] > $oldtime)
        {
            array_push($anew,array($adata[0],$adata[1]));
            //increment counters
            $astatusData[$adata[1]] ++;
            $astatusData[0] ++;
        }
    }
    if ($cop == 0)
        return $astatusData;
    
    //push this entry
    $thisop = array($ctime,$cop);
    array_push($anew,$thisop);

    //add this entry to the list
    $astatusData[$thisop[1]] ++;
    $astatusData[0] ++;
    
    //if we got a lock, then write the new data to disk
    if ($locked)
    {
        $fh = fopen($pickle,'wb');
        $data = serialize($anew);
        fwrite($fh,$data);
        fflush($fh);
        fclose($fh);
        //unlock
        rmdir($lockName);
    }
    return $astatusData;
}

//test block - executed if script called directly
if ((isset($_SERVER['SCRIPT_NAME']) && preg_match("/.\/DiGIR_status.php/i",$_SERVER['SCRIPT_NAME'])) ||
    (isset($_SERVER['argv'][0]) && strcasecmp($_SERVER['argv'][0],'DiGIR_status.php') === 0))
{
    $tmp = @include_once('PHPUnit.php');
    if (!$tmp)
    {
            //error - unable to load phpUnit.php!
            $msg = "Fatal Error- unable to load phpUnit.php.\n".
              "There is a problem with the installation that prevents loading the necessary libraries";
            if (headers_sent())
            {
                    echo "<error>".$msg."</error>";
            }
            else
            {
                    echo "<pre>".$msg;
            }
            flush();
            phpinfo();
            die();
    }
    
    define('testpicklefile',DIGIR_CACHE_DIRECTORY."/test_pickle.txt");
    
    class StatusTest extends PHPUnit_TestCase 
    {
        var $pickleFile;
        
        function statusTest($name) 
        {
            $this->PHPUnit_TestCase($name);
        }
        
        function test_status_simple()
        {
            @rmdir(testpicklefile.".lock");
            @unlink(testpicklefile);
            $res = getStatus(DIGIR_STATUSINTERVAL,testpicklefile,1);
            $this->assertEquals(1,$res[1],"metadata status = ".$res[1]);
            $this->assertEquals(1,$res[0],"total status = ".$res[0]);
            
            $res = getStatus(DIGIR_STATUSINTERVAL,testpicklefile,2);
            $this->assertEquals(1,$res[2],"search status = ".$res[2]);
            $this->assertEquals(2,$res[0],"total status = ".$res[0]);
            $res = getStatus(DIGIR_STATUSINTERVAL,testpicklefile,3);
            $this->assertEquals(1,$res[3],"inventory status = ".$res[3]);
            $this->assertEquals(3,$res[0],"total status = ".$res[0]);

            $res = getStatus(DIGIR_STATUSINTERVAL,testpicklefile,0);
            $this->assertEquals(1,$res[3],"(no change) inventory status = ".$res[3]);
            $this->assertEquals(3,$res[0],"(no change) total status = ".$res[0]);
        }

        function test_status_lots()
        {
            //remove residual locks etc
            @unlink(testpicklefile);
            @rmdir(testpicklefile.".lock");
            for ($i=0; $i < 99; $i++)
            {
                getStatus(DIGIR_STATUSINTERVAL,testpicklefile,2);
            }
            $res = getStatus(DIGIR_STATUSINTERVAL,testpicklefile,2);
            $this->assertEquals(0,$res[1],"metadata status = ".$res[1]);
            $this->assertEquals(100,$res[2],"search status = ".$res[2]);
            $this->assertEquals(0,$res[3],"inventory status = ".$res[3]);
            $this->assertEquals(100,$res[0],"total status = ".$res[0]);
        }
        
        function test_status_timeout()
        {
            @unlink(testpicklefile);
            @rmdir(testpicklefile.".lock");
            $res = getStatus(5,testpicklefile,1);
            $this->assertEquals(1,$res[1],"metadata status = ".$res[1]);
            $this->assertEquals(0,$res[2],"search status = ".$res[2]);
            $this->assertEquals(0,$res[3],"inventory status = ".$res[3]);
            $this->assertEquals(1,$res[0],"total status = ".$res[0]);
            sleep(6);
            $res = getStatus(5,testpicklefile,1);
            $this->assertEquals(1,$res[1],"metadata status = ".$res[1]);
            $this->assertEquals(0,$res[2],"search status = ".$res[2]);
            $this->assertEquals(0,$res[3],"inventory status = ".$res[3]);
            $this->assertEquals(1,$res[0],"total status = ".$res[0]);
        }
    }

    echo "<h1>DiGIR_status.php Test</h1>";
    echo "<p>".idDiGIR_status."</p>";
    echo "<p>DIGIR_STATUSINTERVAL = ".DIGIR_STATUSINTERVAL."</p>";
    echo "<p>All tests here should pass.  </p><p>Note that some tests may need to "
    ."wait a couple of seconds, so don't expect an immediate response.</p>"
    ."<hr />";

    flush();
    
    $suite = new PHPUnit_TestSuite('StatusTest');
    $result = PHPUnit::run($suite);
   
    echo $result->toHTML();

    //cleanup!
    @rmdir(testpicklefile.".lock");
    @unlink(testpicklefile);

    echo "<hr /><p>Done.</p>";
}
?>