]> git.mxchange.org Git - friendica.git/commitdiff
Lock now can use the memcache as well
authorMichael <heluecht@pirati.ca>
Sun, 4 Jun 2017 15:59:20 +0000 (15:59 +0000)
committerMichael <heluecht@pirati.ca>
Sun, 4 Jun 2017 15:59:20 +0000 (15:59 +0000)
include/poller.php
src/Util/Lock.php

index 22fb65a4f8fda474f225fa45971daef9e82426ec..60937fb7e0107ffe36af055bf9b7af859359f725 100644 (file)
@@ -2,6 +2,7 @@
 
 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]);
@@ -19,16 +20,12 @@ require_once("boot.php");
 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();
 
@@ -41,6 +38,10 @@ function poller_run($argv, $argc){
 
        load_hooks();
 
+       if (($argc <= 1) OR ($argv[1] != "no_cron")) {
+               poller_run_cron();
+       }
+
        $a->start_process();
 
        if ($a->min_memory_reached()) {
@@ -55,11 +56,11 @@ function poller_run($argv, $argc){
                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;
        }
 
@@ -69,6 +70,8 @@ function poller_run($argv, $argc){
                return;
        }
 
+       Lock::remove('poller_worker');
+
        $starttime = time();
 
        while ($r = poller_worker_process()) {
@@ -83,12 +86,18 @@ function poller_run($argv, $argc){
                        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;
@@ -724,6 +733,8 @@ function poller_run_cron() {
 if (array_search(__file__,get_included_files())===0){
        poller_run($_SERVER["argv"],$_SERVER["argc"]);
 
+       Lock::removeAll();
+
        poller_unclaim_process();
 
        get_app()->end_process();
index 1a33e819f0f335da6eb2ddf0190a4d15fc560739..175ad34e36617c668ddb885dd1cfa1e45093a59f 100644 (file)
@@ -8,6 +8,8 @@ namespace Friendica\Util;
  *
  */
 
+use Friendica\Core\Config;
+use Memcache;
 use dba;
 use dbm;
 
@@ -15,6 +17,31 @@ 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
@@ -33,6 +60,33 @@ class Lock {
                $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));
@@ -73,7 +127,34 @@ class Lock {
         * @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;
+       }
 }