Skip to content

Instantly share code, notes, and snippets.

@rafageist
Last active September 20, 2019 15:04
Show Gist options
  • Save rafageist/bac54cdf840121e11f6a25a45e0f3fe0 to your computer and use it in GitHub Desktop.
Save rafageist/bac54cdf840121e11f6a25a45e0f3fe0 to your computer and use it in GitHub Desktop.
Unique IP access checker with concurrency control
<?php
/**
* Check if a IP exists in a storage with concurrency control for several HTTP requests
*
* Based in divengine\nodes::waitAndDo() queue algorithm
*
* @author rafageist
*/
function IpCheck($ip)
{
$exclusiveFolder = "./ips";
$mark = 'used';
$max_execution_time = 60;
$ipFolder = "$exclusiveFolder/".str_replace(".", "/", $ip);
$threadId = uniqid('', true);
@mkdir($ipFolder, 0777, true);
file_put_contents("$ipFolder/$threadId", $max_execution_time); // max execution time in seconds for this thread
$i = 0;
$last = null;
$file = null;
do {
// current thread
$dir = opendir($ipFolder);
$file = readdir($dir);
while ($file == '.' || $file == '..' || $file == $mark) {
$file = @readdir($dir);
}
closedir($dir);
if ($file == false) {
throw new Exception("No access to the queue");
}
// If at the same time another process already deleted the current item, then ignore and continue
$max = intval(@file_get_contents("$ipFolder/$file")); // Get the maximum time of the current thread
if ($file === $threadId) {
// it's my turn, I stop the loopUnique IP access checker with concurrency control
break;
}
if ($last !== $file) {
// if another thread deletes the item, renew the max count
$i = 0;
}
$last = $file;
usleep(1000); //sleep 1/1000 seconds
$i++;
if ($i > $max * 100) {
// ignore if file does not exist
// release the item and continue
@unlink("$ipFolder/$file");
$i = 0;
}
} while ($file !== false && $file !== $threadId);
// Turn for me...Do something...
$result = false;
if (!file_exists("$ipFolder/used")) {
$result = true;
file_put_contents("$ipFolder/$mark", date("Y-m-d h:i:s"));
}
// Done!
// Destroy thread in the queue
@unlink("$ipFolder/$threadId");
return $result;
}
// test
var_dump(IpCheck("10.1.1.2"));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment