Stack list

Contenu du snippet

Salut à tous!

Ca vole pas haut, j'ai eu besoin de faire une petite stacklist pour un appli web background
Le principe est simple, suite à la saisie d'un code l'utilisateur récupère un pdf. On sauhaite ajouter un traitement en arrière plan sur la saisie (exemple: l'utilisateur saisie un code barre et recupère l image. Par la suite il faut stocker ce code barre et récupérer des informations liées)
Et avec 2 contraintes:

- Pas de nouvelle bases de données / table => donc système de fichier
- L'utilisateur ne doit pas être impacté lors de sa saisie => donc asynchrone
- traitement fifo (first in first out)

Du coup l'idée => faire une stack list.

J'ai fais certains choix dans ce contexte:
- La donnée sera a prioris du string mais tant qu'à faire, objet
-> 1 fichier par objet de stack (serialize)
-> ajout fichier master (list) pour lecture
- Vu qu'il y a N utilisateurs en même temps: risque de perte de données
-> il me faut un lock => 2 fichiers clef (si 1=2 => pas lock)
-> si lock et process urgent -> fichier temporaire (fonction GC pour consolider)


De plus dans mon cas le traitement qui suit n'est pas urgent (pas d'utilisateur) donc on peu attendre tranquillement que le master soit unlock.

Bref c'est assez grossier, mais ca peut être utile, ne serai-ce que pour avoir des idées ^^

NOTE 1 : penser à setter le repertoire $stackFolder (et le créé)
NOTE 2 : il y a une mini procedure de test ( basé sur $testStep .. c'est moche mais j'ai d'autres trucs à faire ^^)

hf!

naga

<?php 

class cLock { 
 private $stackFolder = 'D:wwwWebrootof49ctest' ; 
 private $objectName;
 public $testStep;
 private $bMaster;
 
 private $incID; 
 
 private $bConsolidating;
 /*if bConsolidating is true,  other process will create a stamp file*/
 
 public function __construct($fName){
  $this->testStep = -1;
  $this->objectName = $fName;
  $this->incID =  $this->guid(); 
  $this->bMaster = false;
 }
 public function __destruct(){
  if($this->bMaster) {   
   $flock2 = $this->stackFolder . $this->objectName . '_KEY2'; 
   file_put_contents($flock2, $this->incID); 
   $this->bMaster = false;
  }
 }
 
 public function addObject( $o , $bSensi) {
  if($this->testStep > 0 ) { print 'Add {' . $o . '} <br>'  ; }
  $this->incID =  $this->guid();
  $fMaster = $this->stackFolder . $this->objectName . '_MASTER'; 
  $this->lock(); 
  if( !$this->bMaster ){
   if( !$bSensi ){
    for ($i = 1; $i <= 5 && !$this->bMaster; $i++) {
     usleep(20000);
     $this->lock();
    }    
   }
   if( !$this->bMaster ) {
    $this->incID =  $this->guid();
    $fDT = $this->stackFolder  . $this->objectName . '+' . $this->incID ;
   }
  }
  if($this->bMaster) $fDT = $this->stackFolder .$this->incID; 
  file_put_contents($fDT, serialize($o));
  if($this->bMaster) {
   if($this->testStep > 0 ) { print 'Added as master {' . $o . '} <br>'  ; }
   file_put_contents($fMaster, $this->incID . '|', FILE_APPEND);
   $this->unlock();
  } else {
   if($this->testStep > 0 ) { print 'Added as slave {' . $o . '} <br>'  ; }
  }  
  if( !$bSensi ){ $this->GC(); }
 }
 
 public function lock(){  
  if($this->testStep == 2 ) return false;
  $this->bMaster = $this->isFree(true);
  return $this->bMaster;
 }
 public function unlock(){
  $flock2 = $this->stackFolder . $this->objectName . '_KEY2'; 
  file_put_contents($flock2, $this->incID); 
  $this->bMaster = false;
  return $this->isFree();
 }
 public function isFree($bInst = false) {
  if($this->bMaster) return true;
  $flock1 = $this->stackFolder . $this->objectName . '_KEY1'; 
  $flock2 = $this->stackFolder . $this->objectName . '_KEY2'; 
  if(file_exists($flock1)) { 
   if(file_exists($flock2)) { 
    $ID1 = file_get_contents($flock1);
    $ID2 = file_get_contents($flock2);
    if($ID1 != $ID2){
     return false;     
    } 
   } 
  } 
  if( $bInst ) {
   $this->incID = $this->guid();  
   file_put_contents($flock1, $this->incID); 
   $this->bMaster = true;
   return true;
  } else {
   return true;      
  } 
 }
 
 public function getStack( $iCount = 1 , $bRemove = false , $bUnser = true){
  $this->GC();
  $fMaster = $this->stackFolder . $this->objectName . '_MASTER'; 
  $this->lock(); 
  if( !$this->bMaster ){
   for ($i = 1; $i <= 5 && !$this->bMaster; $i++) {
    usleep(20000);
    $this->lock();
   }  
   if( !$this->bMaster ) {
    throw new Exception('Error : stacklist {' . $this->objectName . '} is locked!');
    exit();
   }
  }
  $arrStack = array();
  $fileContent = file_get_contents($fMaster);
  if($this->testStep == 3 ) { 
   print '{' . $fileContent  . '} red in master <br>';
  }
  $iC = 0;
  $cursor = 0;
  $MaxLen = strlen($fileContent);
  while ($cursor<$MaxLen && $iC < $iCount) {
   $id = "";
   $car = '';
   while($cursor<$MaxLen && $car != '|') {
    $car = $fileContent[$cursor];
    if($car != '|') $id .= $car;
    $cursor++;
   }
   if($id != ''){
    $fnm = $this->stackFolder . $id;
    if(file_exists($fnm)) { 
     $arrStack[] = ($bUnser ? unserialize(file_get_contents($fnm)) : file_get_contents($fnm) );
     if($bRemove) {
      if($this->testStep != 3 ) { 
       unlink($fnm);
      } else { 
       print '{' . $fnm  . '} to be remove <br>';
      }
     }
    } 
   }
   $iC++;
  }  
  if($this->testStep == 3 ) {
   print '{' . substr ( $fileContent , $cursor)  . '} new content in master <br>';
   print_r($arrStack);
  } else {
   file_put_contents($fMaster, substr ( $fileContent , $cursor)); 
  }
  
  $this->unlock();
  return $arrStack;
 }
 
 
 
 public function GC(){
  if(!$this->lock())return;
  $list = $this->getStampedList();
  $fMaster = $this->stackFolder . $this->objectName . '_MASTER'; 
  foreach( $list as $fName) {
   $fN = basename($fName);
   $fN = str_replace( $this->objectName . '+','',  $fN);
   rename ( $fName , $this->stackFolder  . $fN ) ; 
   
   file_put_contents($fMaster, $fN . '|', FILE_APPEND);   
  }
  $this->unlock();
 }
 public function getStampedList(){return glob($this->stackFolder  . $this->objectName . '+*');}
 /*generate unique ID*/
 public function guid(){
  if (function_exists('com_create_guid') === true)
   return str_replace('-','',trim(com_create_guid(), '{}'));

  $data = openssl_random_pseudo_bytes(16);
  $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
  $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
  return vsprintf('%s%s%s%s%s%s%s%s', str_split(bin2hex($data), 4));
 }
}

if(isset($_GET['__DEBUG'])) {
 $oL = new cLock('test');
 
 $oL->testStep = 1;
 $oL->addObject('test1',true);
 $oL->addObject('test2',true);
 $oL->addObject('test3',true);
 $oL->addObject('test4',true);
 
 
 $oL->testStep = 2;
 $oL->addObject('test5',true);
 $oL->addObject('test6',true);
 $oL->addObject('test7',true);
 $oL->addObject('test8',true);
 
 
 $oL->testStep = 1;
 $oL->GC();
 
 $oL->testStep = 3;
 $oL->getStack(3);
}

?>

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.