<?php
$address = '127.0.0.1';
$port = 81;
set_time_limit (0);
error_reporting(E_ALL);
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_bind($sock, $address, $port);
socket_listen($sock);
$client = null;
while (!$client)
{
if ($newsock = @socket_accept($sock))
{
if (is_resource($newsock))
{
echo "New client connected \n";
$client = $newsock;
}
}
sleep(1);
}
$cache = new LimitedCache();
while(true){
if(!@socket_write($client, ">"))
break;
$str = socket_read($client, 1024);
$data = explode(' ', $str);
if(count($data) == 1)
@socket_write($client, $cache->get(trim($data[0])));
else
@socket_write($client, $cache->set(trim($data[0]), $data[1]));
@socket_write($client, "\n");
}
class Node
{
public $data;
public $prev;
public $next;
function __construct($data)
{
$this->data = $data;
$this->prev = null;
$this->next = null;
}
}
class LimitedCache{
public $head = null;
public $tail = null;
public $map = array();
public $count = 0;
public $limit = 3;
public function set($key, $val){
$is_exist = array_key_exists($key, $this->map);
$deleted_key = null;
if(!$is_exist){
list($deleted_key, $link) = $this->_insert($key);
if($deleted_key)
unset($this->map[$deleted_key]);
}
else
$this->_update($this->map[$key]['link']);
$this->map[$key] = array('data' => $val, 'link' => $link);
return ($is_exist ? 'Updated': 'Saved').
($deleted_key ? ', deleting '.$deleted_key : "");
}
function get($key){
return array_key_exists($key, $this->map)
? $this->map[$key]['data'] : 'Not found';
}
public function _insert($data){
$link = new Node($data);
$link->prev = $this->tail;
if(!$this->tail)
$this->head = $this->tail = &$link;
else{
$this->tail->next = &$link;
$this->tail = &$link;
}
$deleted_key = null;
$this->count += 1;
if($this->count > $this->limit){
// remove head as it's the oldest
$deleted_key = $this->head->data;
$old_head = $this->head;
$this->head = $this->head->next;
$this->head->prev = null;
unset($old_head);
$this->count -= 1;
}
echo "Inserting ".$data."\n";
if($deleted_key)
echo "Deleting ".$deleted_key."\n";
return array($deleted_key, &$link);
}
public function _update($link){
echo "Updating ".$link->data."\n";
if($link == $this->tail)
return;
// remove link from whatever it was
if($link->prev)
$link->prev->next = $link->next;
if($link->next)
$link->next->prev = $link->prev;
$this->tail = $link->prev;
if($link == $this->head)
$this->head = $link->next;
// now move it to the tail
$this->tail->next = $link;
$link->prev = $this->tail;
$link->next = null;
$this->tail = $link;
}
}