Commit 10508fac authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #303 in ZP/z-push from feature/ZP-987-memcache-ipc-too-slow to develop

* commit 'ef2eacb3':
  ZP-987 Allow text keys when using memcache IPC, have a defined mutex name in memcache, suppress errors on unlinking memcache-down file, use device id for IPC type (key) in PingTracking and LoopDetection (one datakey + mutex per device!), check if TopCollector is enabled without blocking the mutex.
parents 51098095 ef2eacb3
...@@ -47,6 +47,7 @@ require_once("backend/ipcmemcached/config.php"); ...@@ -47,6 +47,7 @@ require_once("backend/ipcmemcached/config.php");
class IpcMemcachedProvider implements IIpcProvider { class IpcMemcachedProvider implements IIpcProvider {
protected $type; protected $type;
private $typeMutex;
private $maxWaitCycles; private $maxWaitCycles;
private $logWaitCycles; private $logWaitCycles;
private $isDownUntil; private $isDownUntil;
...@@ -70,6 +71,7 @@ class IpcMemcachedProvider implements IIpcProvider { ...@@ -70,6 +71,7 @@ class IpcMemcachedProvider implements IIpcProvider {
*/ */
public function __construct($type, $allocate, $class) { public function __construct($type, $allocate, $class) {
$this->type = $type; $this->type = $type;
$this->typeMutex = $type . "MX";
$this->maxWaitCycles = round(MEMCACHED_MUTEX_TIMEOUT * 1000 / MEMCACHED_BLOCK_WAIT)+1; $this->maxWaitCycles = round(MEMCACHED_MUTEX_TIMEOUT * 1000 / MEMCACHED_BLOCK_WAIT)+1;
$this->logWaitCycles = round($this->maxWaitCycles/5); $this->logWaitCycles = round($this->maxWaitCycles/5);
...@@ -181,20 +183,20 @@ class IpcMemcachedProvider implements IIpcProvider { ...@@ -181,20 +183,20 @@ class IpcMemcachedProvider implements IIpcProvider {
} }
$n = 0; $n = 0;
while(!$this->memcached->add($this->type+10, true, MEMCACHED_MUTEX_TIMEOUT)) { while(!$this->memcached->add($this->typeMutex, true, MEMCACHED_MUTEX_TIMEOUT)) {
if (++$n % $this->logWaitCycles == 0) { if (++$n % $this->logWaitCycles == 0) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("IpcMemcachedProvider->BlockMutex() waiting to aquire mutex for type: %s ", $this->type)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("IpcMemcachedProvider->BlockMutex() waiting to aquire mutex for type: %s ", $this->typeMutex));
} }
// wait before retrying // wait before retrying
usleep(MEMCACHED_BLOCK_WAIT * 1000); usleep(MEMCACHED_BLOCK_WAIT * 1000);
if ($n > $this->maxWaitCycles) { if ($n > $this->maxWaitCycles) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("IpcMemcachedProvider->BlockMutex() could not aquire mutex for type: %s. Check memcache service!", $this->type)); ZLog::Write(LOGLEVEL_ERROR, sprintf("IpcMemcachedProvider->BlockMutex() could not aquire mutex for type: %s. Check memcache service!", $this->typeMutex));
$this->markAsDown(); $this->markAsDown();
return false; return false;
} }
} }
if ($n*MEMCACHED_BLOCK_WAIT > 50) { if ($n*MEMCACHED_BLOCK_WAIT > 50) {
ZLog::Write(LOGLEVEL_WARN, sprintf("IpcMemcachedProvider->BlockMutex() mutex aquired after waiting for %sms for type: %s", ($n*MEMCACHED_BLOCK_WAIT), $this->type)); ZLog::Write(LOGLEVEL_WARN, sprintf("IpcMemcachedProvider->BlockMutex() mutex aquired after waiting for %sms for type: %s", ($n*MEMCACHED_BLOCK_WAIT), $this->typeMutex));
} }
return true; return true;
} }
...@@ -207,7 +209,7 @@ class IpcMemcachedProvider implements IIpcProvider { ...@@ -207,7 +209,7 @@ class IpcMemcachedProvider implements IIpcProvider {
* @return boolean * @return boolean
*/ */
public function ReleaseMutex() { public function ReleaseMutex() {
return $this->memcached->delete($this->type+10); return $this->memcached->delete($this->typeMutex);
} }
/** /**
...@@ -265,7 +267,7 @@ class IpcMemcachedProvider implements IIpcProvider { ...@@ -265,7 +267,7 @@ class IpcMemcachedProvider implements IIpcProvider {
return $timestamp; return $timestamp;
} }
else { else {
unlink(MEMCACHED_DOWN_LOCK_FILE); @unlink(MEMCACHED_DOWN_LOCK_FILE);
} }
} }
return 0; return 0;
......
...@@ -88,8 +88,13 @@ abstract class InterProcessData { ...@@ -88,8 +88,13 @@ abstract class InterProcessData {
if (!$this->provider_class) { if (!$this->provider_class) {
throw new Exception("No IPC provider available"); throw new Exception("No IPC provider available");
} }
// ZP-987: use an own mutex + storage key for each device on non-shared-memory IPC
// this method is not suitable for the TopCollector atm
if (!($this instanceof TopCollector) && $this->provider_class !== 'IpcSharedMemoryProvider') {
$this->type = Request::GetDeviceID(). "-". $this->type;
}
$this->ipcProvider = new $this->provider_class($this->type, $this->allocate, get_class($this)); $this->ipcProvider = new $this->provider_class($this->type, $this->allocate, get_class($this));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("%s initialised with IPC provider '%s'", get_class($this), $this->provider_class)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("%s initialised with IPC provider '%s' with type '%s'", get_class($this), $this->provider_class, $this->type));
} }
catch (Exception $e) { catch (Exception $e) {
......
...@@ -148,10 +148,10 @@ class TopCollector extends InterProcessData { ...@@ -148,10 +148,10 @@ class TopCollector extends InterProcessData {
if ($preserve) if ($preserve)
$this->preserved[] = $addinfo; $this->preserved[] = $addinfo;
if ($this->isEnabled()) {
$ok = false;
// exclusive block // exclusive block
if ($this->blockMutex()) { if ($this->blockMutex()) {
if ($this->isEnabled()) {
$topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA): array(); $topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA): array();
$this->checkArrayStructure($topdata); $this->checkArrayStructure($topdata);
...@@ -159,16 +159,14 @@ class TopCollector extends InterProcessData { ...@@ -159,16 +159,14 @@ class TopCollector extends InterProcessData {
// update // update
$topdata[self::$devid][self::$user][self::$pid] = $this->latest; $topdata[self::$devid][self::$user][self::$pid] = $this->latest;
$ok = $this->setData($topdata, self::TOPDATA); $ok = $this->setData($topdata, self::TOPDATA);
}
$this->releaseMutex(); $this->releaseMutex();
} }
// end exclusive block // end exclusive block
if (!$ok) {
if ($this->isEnabled() === true && !$ok) {
ZLog::Write(LOGLEVEL_WARN, "TopCollector::AnnounceInformation(): could not write to shared memory. Z-Push top will not display this data."); ZLog::Write(LOGLEVEL_WARN, "TopCollector::AnnounceInformation(): could not write to shared memory. Z-Push top will not display this data.");
return false; return false;
} }
}
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment