use Friendica\App;
use Friendica\Core\Config;
+use Friendica\Util\Lock;
if (!file_exists("boot.php") AND (sizeof($_SERVER["argv"]) != 0)) {
$directory = dirname($_SERVER["argv"][0]);
function poller_run($argv, $argc){
global $a, $db;
- if (is_null($a)) {
- $a = new App(dirname(__DIR__));
- }
+ $a = new App(dirname(__DIR__));
- if(is_null($db)) {
- @include(".htconfig.php");
- require_once("include/dba.php");
- $db = new dba($db_host, $db_user, $db_pass, $db_data);
- unset($db_host, $db_user, $db_pass, $db_data);
- };
+ @include(".htconfig.php");
+ require_once("include/dba.php");
+ $db = new dba($db_host, $db_user, $db_pass, $db_data);
+ unset($db_host, $db_user, $db_pass, $db_data);
Config::load();
load_hooks();
+ if (($argc <= 1) OR ($argv[1] != "no_cron")) {
+ poller_run_cron();
+ }
+
$a->start_process();
if ($a->min_memory_reached()) {
return;
}
- if(($argc <= 1) OR ($argv[1] != "no_cron")) {
- poller_run_cron();
+ if ($a->max_processes_reached()) {
+ return;
}
- if ($a->max_processes_reached()) {
+ if (!Lock::set('poller_worker')) {
return;
}
return;
}
+ Lock::remove('poller_worker');
+
$starttime = time();
while ($r = poller_worker_process()) {
return;
}
+ if (!Lock::set('poller_worker')) {
+ return;
+ }
+
// Count active workers and compare them with a maximum value that depends on the load
if (poller_too_much_workers()) {
logger('Active worker limit reached, quitting.', LOGGER_DEBUG);
return;
}
+ Lock::remove('poller_worker');
+
if (!poller_execute($r[0])) {
logger('Process execution failed, quitting.', LOGGER_DEBUG);
return;
if (array_search(__file__,get_included_files())===0){
poller_run($_SERVER["argv"],$_SERVER["argc"]);
+ Lock::removeAll();
+
poller_unclaim_process();
get_app()->end_process();
*
*/
+use Friendica\Core\Config;
+use Memcache;
use dba;
use dbm;
* @brief This class contain Functions for preventing parallel execution of functions
*/
class Lock {
+ /**
+ * @brief Check for memcache and open a connection if configured
+ *
+ * @return object|boolean The memcache object - or "false" if not successful
+ */
+ public static function memcache() {
+ if (!function_exists('memcache_connect')) {
+ return false;
+ }
+
+ if (!Config::get('system', 'memcache')) {
+ return false;
+ }
+
+ $memcache_host = Config::get('system', 'memcache_host', '127.0.0.1');
+ $memcache_port = Config::get('system', 'memcache_port', 11211);
+
+ $memcache = new Memcache;
+
+ if (!$memcache->connect($memcache_host, $memcache_port)) {
+ return false;
+ }
+
+ return $memcache;
+ }
/**
* @brief Sets a lock for a given name
$got_lock = false;
$start = time();
+ $memcache = self::memcache();
+ if (is_object($memcache)) {
+ $cachekey = get_app()->get_hostname().";lock:".$fn_name;
+
+ do {
+ $lock = $memcache->get($cachekey);
+
+ if (!is_bool($lock)) {
+ $pid = (int)$lock;
+
+ // When the process id isn't used anymore, we can safely claim the lock for us.
+ // Or we do want to lock something that was already locked by us.
+ if (!posix_kill($pid, 0) OR ($pid == getmypid())) {
+ $lock = false;
+ }
+ }
+ if (is_bool($lock)) {
+ $memcache->set($cachekey, getmypid(), MEMCACHE_COMPRESSED, 300);
+ $got_lock = true;
+ }
+ if (!$got_lock) {
+ sleep($wait_sec);
+ }
+ } while (!$got_lock AND ((time() - $start) < $timeout));
+
+ return $got_lock;
+ }
do {
dba::lock('locks');
$lock = dba::select('locks', array('locked', 'pid'), array('name' => $fn_name), array('limit' => 1));
* @param string $fn_name Name of the lock
*/
public static function remove($fn_name) {
+ $memcache = self::memcache();
+ if (is_object($memcache)) {
+ $cachekey = get_app()->get_hostname().";lock:".$fn_name;
+ $lock = $memcache->get($cachekey);
+
+ if (!is_bool($lock)) {
+ if ((int)$lock == getmypid()) {
+ $memcache->delete($cachekey);
+ }
+ }
+ return;
+ }
+
dba::update('locks', array('locked' => false, 'pid' => 0), array('name' => $fn_name, 'pid' => getmypid()));
return;
}
+
+ /**
+ * @brief Removes all lock that were set by us
+ */
+ public static function removeAll() {
+ $memcache = self::memcache();
+ if (is_object($memcache)) {
+ // We cannot delete all cache entries, but this doesn't matter with memcache
+ return;
+ }
+
+ dba::update('locks', array('locked' => false, 'pid' => 0), array('pid' => getmypid()));
+ return;
+ }
}