Commit 971009ff authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #613 in ZP/z-push from...

Merge pull request #613 in ZP/z-push from feature/ZP-1122-sync-loop-failsafe-check-for-out-of-memory to develop

* commit '704e0c93':
  ZP-1122 Read configured memory limit once, check memory limit after each message export and stop when limit is reached.
parents 1381ceb5 704e0c93
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
************************************************/ ************************************************/
class Request { class Request {
const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when synching
const UNKNOWN = "unknown"; const UNKNOWN = "unknown";
/** /**
...@@ -83,6 +84,7 @@ class Request { ...@@ -83,6 +84,7 @@ class Request {
static private $koeBuildDate; static private $koeBuildDate;
static private $koeCapabilites; static private $koeCapabilites;
static private $expectedConnectionTimeout; static private $expectedConnectionTimeout;
static private $memoryLimit;
/** /**
* Initializes request data * Initializes request data
...@@ -183,6 +185,11 @@ class Request { ...@@ -183,6 +185,11 @@ class Request {
if(defined('USE_FULLEMAIL_FOR_LOGIN') && ! USE_FULLEMAIL_FOR_LOGIN) { if(defined('USE_FULLEMAIL_FOR_LOGIN') && ! USE_FULLEMAIL_FOR_LOGIN) {
self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser); self::$authUser = Utils::GetLocalPartFromEmail(self::$authUser);
} }
// get & convert configured memory limit
(int)preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
self::$memoryLimit = $m[1] * pow(1024, strpos('BKMG', $m[2])) * self::MAXMEMORYUSAGE;
}, strtoupper(ini_get('memory_limit')));
} }
/** /**
...@@ -632,6 +639,18 @@ class Request { ...@@ -632,6 +639,18 @@ class Request {
return (time() - $_SERVER["REQUEST_TIME"]) >= self::GetExpectedConnectionTimeout(); return (time() - $_SERVER["REQUEST_TIME"]) >= self::GetExpectedConnectionTimeout();
} }
/**
* Indicates if the memory usage limit is almost reached.
* Processing should stop then to prevent hard out-of-memory issues.
* The threshold is hardcoded at 90% in Request::MAXMEMORYUSAGE.
*
* @access public
* @return boolean
*/
static public function IsRequestMemoryLimitReached() {
return memory_get_peak_usage(true) >= self::$memoryLimit;
}
/**---------------------------------------------------------------------------------------------------------- /**----------------------------------------------------------------------------------------------------------
* Private stuff * Private stuff
*/ */
......
...@@ -826,6 +826,12 @@ class Sync extends RequestProcessor { ...@@ -826,6 +826,12 @@ class Sync extends RequestProcessor {
$setupExporter = false; $setupExporter = false;
} }
// if max memory allocation is reached, stop processing other collections
if (Request::IsRequestMemoryLimitReached()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as max memory allocatation reached, omitting output for collection.", $spa->GetFolderId()));
$setupExporter = false;
}
// ZP-907: never send changes of UNKNOWN folders to an Outlook client // ZP-907: never send changes of UNKNOWN folders to an Outlook client
if (Request::IsOutlook() && self::$deviceManager->GetFolderTypeFromCacheById($spa->GetFolderId()) == SYNC_FOLDER_TYPE_UNKNOWN && $spa->HasSyncKey()) { if (Request::IsOutlook() && self::$deviceManager->GetFolderTypeFromCacheById($spa->GetFolderId()) == SYNC_FOLDER_TYPE_UNKNOWN && $spa->HasSyncKey()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as type is UNKNOWN.", $spa->GetFolderId())); ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync(): no exporter setup for '%s' as type is UNKNOWN.", $spa->GetFolderId()));
...@@ -1214,7 +1220,7 @@ class Sync extends RequestProcessor { ...@@ -1214,7 +1220,7 @@ class Sync extends RequestProcessor {
} }
} }
if($n >= $windowSize || Request::IsRequestTimeoutReached()) { if($n >= $windowSize || Request::IsRequestTimeoutReached() || Request::IsRequestMemoryLimitReached()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Exported maxItems of messages: %d / %d", $n, $changecount)); ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Exported maxItems of messages: %d / %d", $n, $changecount));
break; break;
} }
...@@ -1229,9 +1235,9 @@ class Sync extends RequestProcessor { ...@@ -1229,9 +1235,9 @@ class Sync extends RequestProcessor {
self::$encoder->endTag(); self::$encoder->endTag();
// log the request timeout // log the request timeout
if (Request::IsRequestTimeoutReached()) { if (Request::IsRequestTimeoutReached() || Request::IsRequestMemoryLimitReached()) {
ZLog::Write(LOGLEVEL_DEBUG, "HandleSync(): Stopping export as maximum request timeout is almost reached!"); ZLog::Write(LOGLEVEL_DEBUG, "HandleSync(): Stopping export as limits of request timeout or available memory are almost reached!");
// Send a <MoreAvailable/> tag if we reached the request timeout, there are more changes and a moreavailable was not already send // Send a <MoreAvailable/> tag if we reached the request timeout or max memory, there are more changes and a moreavailable was not already send
if (!$moreAvailableSent && ($n > $windowSize)) { if (!$moreAvailableSent && ($n > $windowSize)) {
self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true); self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true);
$spa->DelFolderStat(); $spa->DelFolderStat();
......
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