- if ((dbm::is_result($lock)) AND !$lock['locked']) {
- dba::update('locks', array('locked' => true), array('name' => $fn_name));
- $got_lock = true;
- } elseif (!dbm::is_result($lock)) {
- dbm::insert('locks', array('name' => $fn_name, 'locked' => true));
+ $memcache = self::connectMemcache();
+ if (is_object($memcache)) {
+ $cachekey = get_app()->get_hostname().";lock:".$fn_name;
+
+ do {
+ // We only lock to be sure that nothing happens at exactly the same time
+ dba::lock('locks');
+ $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) || ($pid == getmypid())) {
+ $lock = false;
+ }
+ }
+ if (is_bool($lock)) {
+ $memcache->set($cachekey, getmypid(), MEMCACHE_COMPRESSED, 300);
+ $got_lock = true;
+ }
+
+ dba::unlock();
+
+ if (!$got_lock && ($timeout > 0)) {
+ usleep(rand(10000, 200000));
+ }
+ } while (!$got_lock && ((time() - $start) < $timeout));
+
+ return $got_lock;
+ }
+
+ do {
+ dba::lock('locks');
+ $lock = dba::select('locks', array('locked', 'pid'), array('name' => $fn_name), array('limit' => 1));
+
+ if (DBM::is_result($lock)) {
+ if ($lock['locked']) {
+ // When the process id isn't used anymore, we can safely claim the lock for us.
+ if (!posix_kill($lock['pid'], 0)) {
+ $lock['locked'] = false;
+ }
+ // We want to lock something that was already locked by us? So we got the lock.
+ if ($lock['pid'] == getmypid()) {
+ $got_lock = true;
+ }
+ }
+ if (!$lock['locked']) {
+ dba::update('locks', array('locked' => true, 'pid' => getmypid()), array('name' => $fn_name));
+ $got_lock = true;
+ }
+ } elseif (!DBM::is_result($lock)) {
+ dba::insert('locks', array('name' => $fn_name, 'locked' => true, 'pid' => getmypid()));