Last active
September 20, 2019 15:04
-
-
Save rafageist/bac54cdf840121e11f6a25a45e0f3fe0 to your computer and use it in GitHub Desktop.
Unique IP access checker with concurrency control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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