jeudi 27 août 2015

ANYEM : PHP Synchronized Data Structure Server


1. INTRODUCTION


ANYEM is an open source project, written in PHP. The main objective of this project is to give the possibility for PHP Developers to :
  • Share variables between different PHP instances;
  • Share variables between different PHP Applications;
  • Synchronize access for variables;
ANYEM_SERVER Written in PHP and it is based on Socket.

It holds data in memory, and use Judy Array. Below is the exhaustive list of operations that ANYEM_SERVER can treat :

OperationTypeDescription
GET synchronized reserve a variable and returns his value;
PUT synchronized unreserve a variable and update his new value;
DELETE synchronized delete the variable from ANYEM_SERVER;
RELEASEsynchronized unreserve a variable without changing his value;
READ not synchronizedthe value of the variable from ANYEM_SERVER;

ANYEM_CLIENT
PHP Package that contains classes to interact with ANYEM_SERVER

2. HOW TO INSTALL

ANYEM_SERVER
  • Download both: ANYEM_SERVER and ANYEM_SHARED and place them in the same directory;
  • ANYEM_SERVER requirements:
    • Log4PHP : You can use the version delivered in the package or download Log4PHP from Apache Server
    • Judy : You can build Judy for Linux or Windows Server by following the documentation from the official PHP web site: How to install Judy, or download the compiled DLL for Windows from the official PECL website: Judy DLL Do not forget to update your php.ini by adding judy library to the list of PHP Extension
  • ANYEM_SERVER configuration This configuration is pretty simple: go to ANYEM_SHARED/config and edit the file anyem_config_shared.properties as follow
    portdesignates the port on which ANYEM_SERVER will listen for connections;
    maxResourceSerializedLengthdesignates the maximum number of bytes read;
  • Environment configuration Add PHP installation directory to your PATH environment variable
Now, start your ANYEM_SERVER from command line
php ANYEM_SERVER/anyem.app.server.impl/ServerImpl.php
You should see the dump of the configuration used by the server and these three informations messages:
  • socket created successfully...
  • socket binded successfully...
  • socket listening successfully...
  • Thats all for the server :)
ANYEM_CLIENT
  1. Download both: ANYEM_CLIENT and ANYEM_SHARED and place them in the same directory;
  2. ANYEM_CLIENT requirements:
    Log4PHP : You can use the version delivered in the package or download Log4PHP from Apache Server
  3. ANYEM_CLIENT configuration:
    1. You must copy the file that has been configured in:
      ANYEM_SERVER/ANYEM_SHARED/config/anyem_config_shared.properties,
      Paste it in:
      ANYEM_CLIENT/ANYEM_SHARED/config
      and keep the same file name
    2. Go to ANYEM_CLIENT/config and edit anyem_config.properties:
      addressdesignates the ANYEM_SERVER address;
      defaultMaxAttemptdefault value that designates the maximum number of attempts that the client can made to reserve a variable,vthis value can be changed by code;
      defaultDelayAttemptdefault value that designates the delay in µSeconds between two reservation attempts, this value can be changed by code;

3. USAGE (EXAMPLE)


    require_once (__DIR__ . '/../../ANYEM_SHARED/' . 'anyem.resource.impl/ResourceIdentifierImpl.php');
    require_once (__DIR__ . '/../../ANYEM_SHARED/' . 'anyem.resource.impl/ResponseWrapperImpl.php') ;
    require_once (__DIR__ . '/../anyem.client.impl/ClientConnectionImpl.php');
    require_once (__DIR__ . '/../anyem.client.impl/AnyemClientImpl.php');
    // get a new clientConnection Object using ClientConnectionImpl factory
    $clientConnection   = ClientConnectionImpl::newClient();
    // it is important to give an identifier to your object, it will be user as a unique ID by ANYEM_SERVER
    // the constructor of ResourceIdentifierImpl needs 3 parameters tha will help to identify more easily your variables
    $identifier         = new ResourceIdentifierImpl("anyem.com", "anyemNameSpace", "a");
    // now you can construct your AnyemClientImpl object, you can use it to get, put, delete, release and read your variable in your PHP script 
    $anyemClient        = new AnyemClientImpl($clientConnection, $identifier);

    // Example of : GET, Update and PUT a variable 
    // this mode is synchronzed, anyone who will attempt to do an update operation of this variable that it is 
    // identified by $identifier object, will wait until you will done
    $a;
    try {
        $responseWrapper = $anyemClient->get($a);
    }
    catch (Exception $e) {
        print $e->getMessage() . "\n";
        continue;
    }
    $a = $responseWrapper->getResource()->getData();
    // will give the content of $a from ANYEM_SERVER
    print_r ($a);
    // update $a
    $a++;
    $anyemClient->put($a);
    // now the variable is released, someone else cas reserve it
    ```


Download Links:
Download ANYEM Project from Github
Download ANYEM Project from PHPClasses

mercredi 29 avril 2015

Sort Array of Objects

I want to share with you a code that i have written to sort an Array of objects with multi-criteria
Example is a good teacher :

<?php
class User {
    private $name;     private $age;     public function __construct($name, $age) {         $this->name = $name;         $this->age   = $age;     }         public function getName() {         return $this->name;     }          public function getAge() {         return $this->age;     } } ?>


<?php
    $users = array(new User('Denis' , 25),
new User('Anis'  , 29),
new User('Anis'  , 26),
new User('Nikita', 15),
new User('Zelda' , 34),
new User('Zelda' , 90));

// to sort your array based on name with ASC Order
// 1st : Create the search criteria
// the first parameter must be the getter, second : order by ASC or DSC, third the type of your data
$criteria_1 = new Criteria ('getName', Criteria::_SORT_ASC, Criteria::_SORT_STRING);
// create the sorter object. Note that the second parameter must be an array
$sortObject = new SortObjectArray($users, array($criteria_1));
var_dump ($sortObject->getSortedObjectArray());

// Using Multi-Criteria (like ORDER BY NAME, AGE in SQL)
$criteria_2 = new Criteria ('getAge', Criteria::_SORT_DSC, Criteria::_SORT_INTEGER); $sortObject = new SortObjectArray($users, array($criteria_1, $criteria_2)); var_dump ($sortObject->getSortedObjectArray());
Here the source code
class Criteria {
 const _SORT_INTEGER = 1;
 const _SORT_FLOAT   = 2;
 const _SORT_STRING  = 3;
 const _SORT_ASC = 1;
 const _SORT_DSC = 2;
 
 private $sortType;
 private $sortCriteria;
 private $sortOrder;
 private $strict;
 
 public function __construct($sortCriteria, $sortOrder, $sortType, $strict = FALSE) {
  $this->setSortCriteria($sortCriteria);
  $this->setSortOrder($sortOrder);
  $this->setSortType($sortType);
  $this->setStrict($strict);
 }
 public function setStrict($strict) {
  if(!is_bool($strict)) {
   throw new Exception("parameter must be a boolean");
  }
  $this->strict = $strict;
 }
 public function isStrict() {
  return $this->strict;
 }
 
 public function getSortType() {
  return $this->sortType;
 }
 /**
 * the primitive type variables that will be used for sorting
 * @param1 sortType integer, must be on of (_SORT_INTEGER|_SORT_FLOAT|_SORT_STRING)
 * @throws Exception
 */
 public function setSortType($sortType) {
  if(is_null($sortType)) {
   throw new Exception("MANDATORY_ATTRIBUTE");
  }
  $sortType = (int)$sortType;
  if(!is_integer($sortType) ||
    ($sortType != self::_SORT_INTEGER && $sortType != self::_SORT_FLOAT && $sortType != self::_SORT_STRING)) {
   throw new Exception("sort must be in integer. use theses defines : (_SORT_INTEGER|_SORT_FLOAT|_SORT_STRING)");
  }             
  $this->sortType = $sortType;
 }
 /**
 * @param1 string, must be the accessor of the object, example : getProject::getCmsserver::getId, or getProject::getFileserver::getName. Note : use the defined separator CRITERIA_SEPERATOR 
  */
 public function setSortCriteria($sortCriteria) {
  if(is_null($sortCriteria) || strlen($sortCriteria) == 0) {
   throw new Exception("MANDATORY_ATTRIBUTE");
  }
  $this->sortCriteria = $sortCriteria;
 }
 
 public function getSortCriteria() {
  return $this->sortCriteria;
 }
 
 /**
 * @param1 the order of sort, must be one of (_SORT_ASC|_SORT_DSC)
  */
 public function setSortOrder($sortOrder) {
  if(is_null($sortOrder)) {
   throw new Exception("MANDATORY_ATTRIBUTE");
  }
  $sortOrder = (int)$sortOrder;
  if(!is_integer($sortOrder) ||
      ($sortOrder != self::_SORT_ASC && $sortOrder != self::_SORT_DSC)) {
   throw new Exception("sort must be in integer. use theses defines : (_SORT_ASC|_SORT_DSC)");
  }
  $this->sortOrder = $sortOrder;
 }
 public function getSortOrder() {
  return $this->sortOrder;
 }
}

class SortObjectArray {
 const CRITERIA_SEPERATOR = "::";
 
 private $criteria;
 private $objectArray;
 private $sortedObjectArray;
 
 private function setObjectArray($objectArray) {
  if(is_null($objectArray) || !is_array($objectArray)) {
   throw new Exception("MANDATORY_ATTRIBUTE");
  }
  if(count($objectArray) < 1) {
   throw new Exception('table to be sort must at least has 2 elements, current size = ' . count($objectArray));
  }
  $this->objectArray = $objectArray;
 }
 private function getObjectArray() {
  return $this->objectArray;
 }
 
 private function setSortedObjectArray($sortedObjectArray) {
  $this->sortedObjectArray = $sortedObjectArray;
 }
 public function getSortedObjectArray() {
  return $this->sortedObjectArray;
 }
 private function setCriteria($criteria) {
  $this->criteria = $criteria;
 }
 private function getCriteria() {
  return $this->criteria;
 }
 /**
 * @param1 array of Objects to be sorted
 * @param2 array of Criteria's Object
 */
 public function __construct($objectArray, $criteria) {
  $this->setObjectArray($objectArray);
  $this->setCriteria($criteria);
  $this->doSorting();
 }
 
 /**
 * this function will create an interval that will be used by function to cut out the original array, that will be sorted independently
 * @param1 array of Objects
 * @param2 Criteria Object
 * @return array of integers, will be the computed interval
 */
 public function computeInterval($objectArray, $criteria) {
  if(!is_array($objectArray) || count($objectArray) == 0) {
   throw new Exception("can not compute anything");
  }
  if(count($objectArray) == 1) {
   return array(0, 0);
  }
  $interval    = array();
  $predecessor = NULL;
  $position    = 0;
  foreach($objectArray as $object) {
   if(is_null($predecessor)) {
    $predecessor = $this->getValue($object, $criteria->getSortCriteria());
    continue;
   }
   if($this->compare($predecessor,
      $this->getValue($object, $criteria->getSortCriteria()),
      $criteria) != 0) {
    $interval[] = $position;
    $predecessor = $this->getValue($object, $criteria->getSortCriteria());
   }
   $position++;
  }
  //var_dump(array_merge(array(0), $interval, array(count($objectArray)-1)));
  return array_merge(array(-1), $interval, array(count($objectArray)-1));
 }
 
 /**
 * bubble sort
 * @param1 array of Objects
 * @param2 Criteria Object
 * @return array of Objects, sorted
  */
 public function sortArray($objectArray, $criteria) {
  for($i=0 ; $i<count($objectArray)-1 ; $i++) {
   for($j=($i+1) ; $j<count($objectArray) ; $j++) {
    $r = $this->compare($this->getValue($objectArray[$i], $criteria->getSortCriteria()),
    $this->getValue($objectArray[$j], $criteria->getSortCriteria()),
    $criteria);        
    if($r < 0 && $criteria->getSortOrder() == Criteria::_SORT_DSC) {
     $temp = $objectArray[$i];
     $objectArray[$i] = $objectArray[$j];
     $objectArray[$j] = $temp;
     continue;
    }
    if($r > 0 && $criteria->getSortOrder()  == Criteria::_SORT_ASC) {
     $temp = $objectArray[$i];
     $objectArray[$i] = $objectArray[$j];
     $objectArray[$j] = $temp;
     continue;
    }
   }
  }
  return $objectArray ;
 }
 
 public function doSorting() {
  $tempObjectArray = array();     
  $objectArray     = $this->getObjectArray();
  $criteriaArray   = $this->getCriteria();

  for($i=0 ; $i<count($criteriaArray) ; $i++) {
   if($i==0) {           
    $objectArray = $this->sortArray($objectArray, $criteriaArray[$i]);
    continue;
   }
   $tempObjectArray = array();     
   $interval = $this->computeInterval($objectArray, $criteriaArray[$i-1]);
   $subArrays = $this->extractArraysByInterval($objectArray, $interval);
   foreach($subArrays as $arrayToSort) {
    $arrayToSort = $this->sortArray($arrayToSort, $criteriaArray[$i]);
    $tempObjectArray = array_merge($tempObjectArray, $arrayToSort);
   }
   $objectArray = $tempObjectArray;
  }
  $this->setSortedObjectArray($objectArray);
 }
 
 public function extractArraysByInterval($objectArray, $interval) {
  $extractedArrays = array();
  for($i=0 ; $i<count($interval)-1 ; $i++) {
   $temp = array();
   for($j=$interval[$i]+1 ; $j<=$interval[$i+1] ; $j++) {
    $temp[] = $objectArray[$j];
   }
   $extractedArrays[] = $temp;
  }
  return $extractedArrays;
 }
 
 /**
 * @return integer == 0 if varOne & varTwo are equals, < 0 if varOne is less than varTwo, > 0 if varOne is greater than varTwo
 */
 public function compare($varOne, $varTwo, $criteria) {
  switch($criteria->getSortType()) {           
   case Criteria::_SORT_INTEGER : {
    $varOne = (int)$varOne;
    $varTwo = (int)$varTwo;
    return $varOne - $varTwo;
   }
   case Criteria::_SORT_FLOAT : {
    $varOne = (float)$varOne;
    $varTwo = (float)$varTwo;
    return $varOne - $varTwo;
   }
   default : {
    $varOne = (string)$varOne;
    $varTwo = (string)$varTwo;
    if($criteria->isStrict() === FALSE) {
        return strcmp($varOne, $varTwo);
    }
    return strcasecmp($varOne, $varTwo);
   }
  }
 }
 public function getValue($object, $sortCriteria) {
  $value = $object;            
  $sortCriteria = explode(self::CRITERIA_SEPERATOR, $sortCriteria);
  foreach($sortCriteria as $criteria) {
   $value = $value->{$criteria}();
  }
  return $value;
 }
}

samedi 31 janvier 2015

Compile Your PHP Code

PHP is known as a web programming language, but guess what ! it is a fully language that it can be used like Java, C, python... or any other client side language.

In my first tutorial, i will learn you, with a simple example, how you can do that.

Let's start by some configuration :

1 - Download PHP (if you have not a PHP installed in your machine, or if you want to do some upgrade) : http://php.net/downloads.php
2 - Extract the downloaded archive in your chosen folder.
3 - Add PHP folder to your environemnt variable PATH (same variable name on Windows/Linux/MacOs)
4 - Open a command prompt and type : php --version

You should see the version of the installed PHP
Now, create this simple PHP source, i will suppose that it will be C:\test.php
We will write a code that will do the sum of two values that will be given in arguments :

<?php
printf ("\nHello, You are using PHP Like C.\n");
printf ("----------------------------------\n");

if (count($argv) != 3 || is_numeric($argv[1]) || !is_numeric($argv[2])) {
    printf ("Expecting 2 valid numbers...try again :)\n");
    exit (0);
}
printf ("%d + %d = %d\n", $argv[1], $argv[2], $argv[1] + $argv[2]);
printf ("See you next time :)\n");
printf ("----------------------------------\n");

?>

Now, open a command prompt and type :
php C:\test.php 5 15
If all it is ok, you should see the sum of 5 and 15

Ok, it is good to know that we can use PHP code in client side, like a true programming language, but if i want to run my script on another machine, i must install PHP on it ?
The response, is no :)

Let's continue our configuration :

5 - Download Phalanger from this URL : http://phalanger.codeplex.com/
5 - Install it on your machine.
6 - On Windows, you can see a new shortcut added in your start panel : "Phalanger Command Prompt". Click on it.
7 - Compile your PHP code using this command : phpc.exe C:\test.php

Now you will find your compiled test.php script as test.exe under Phalanger_Installation_Path/Bin/bin

In my case test.exe is located under : C:\Program Files (x86)\Phalanger 3.0\Bin\bin

Open a command prompt under this path and type test.exe 5 15

All done ! now you know that you can build a whole applicatin with PHP and distribute it easily :)

My configuration :
 - Windows 7 Professional 64 Bits
 - PHP 5.5.11 (cli) (built: Apr  8 2014 15:07:14)
- Phalanger 3.0

See you next time :)
Anis