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");
class IpcMemcachedProvider implements IIpcProvider {
protected $type;
private $typeMutex;
private $maxWaitCycles;
private $logWaitCycles;
private $isDownUntil;
......@@ -70,6 +71,7 @@ class IpcMemcachedProvider implements IIpcProvider {
*/
public function __construct($type, $allocate, $class) {
$this->type = $type;
$this->typeMutex = $type . "MX";
$this->maxWaitCycles = round(MEMCACHED_MUTEX_TIMEOUT * 1000 / MEMCACHED_BLOCK_WAIT)+1;
$this->logWaitCycles = round($this->maxWaitCycles/5);
......@@ -181,20 +183,20 @@ class IpcMemcachedProvider implements IIpcProvider {
}
$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) {
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
usleep(MEMCACHED_BLOCK_WAIT * 1000);
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();
return false;
}
}
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;
}
......@@ -207,7 +209,7 @@ class IpcMemcachedProvider implements IIpcProvider {
* @return boolean
*/
public function ReleaseMutex() {
return $this->memcached->delete($this->type+10);
return $this->memcached->delete($this->typeMutex);
}
/**
......@@ -265,7 +267,7 @@ class IpcMemcachedProvider implements IIpcProvider {
return $timestamp;
}
else {
unlink(MEMCACHED_DOWN_LOCK_FILE);
@unlink(MEMCACHED_DOWN_LOCK_FILE);
}
}
return 0;
......
......@@ -88,8 +88,13 @@ abstract class InterProcessData {
if (!$this->provider_class) {
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));
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) {
......
......@@ -148,10 +148,10 @@ class TopCollector extends InterProcessData {
if ($preserve)
$this->preserved[] = $addinfo;
if ($this->isEnabled()) {
$ok = false;
// exclusive block
if ($this->blockMutex()) {
if ($this->isEnabled()) {
$topdata = ($this->hasData(self::TOPDATA)) ? $this->getData(self::TOPDATA): array();
$this->checkArrayStructure($topdata);
......@@ -159,16 +159,14 @@ class TopCollector extends InterProcessData {
// update
$topdata[self::$devid][self::$user][self::$pid] = $this->latest;
$ok = $this->setData($topdata, self::TOPDATA);
}
$this->releaseMutex();
}
// end exclusive block
if ($this->isEnabled() === true && !$ok) {
if (!$ok) {
ZLog::Write(LOGLEVEL_WARN, "TopCollector::AnnounceInformation(): could not write to shared memory. Z-Push top will not display this data.");
return false;
}
}
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