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 @@
************************************************/
class Request {
const MAXMEMORYUSAGE = 0.9; // use max. 90% of allowed memory when synching
const UNKNOWN = "unknown";
/**
......@@ -83,6 +84,7 @@ class Request {
static private $koeBuildDate;
static private $koeCapabilites;
static private $expectedConnectionTimeout;
static private $memoryLimit;
/**
* Initializes request data
......@@ -183,6 +185,11 @@ class Request {
if(defined('USE_FULLEMAIL_FOR_LOGIN') && ! USE_FULLEMAIL_FOR_LOGIN) {
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 {
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
*/
......
......@@ -826,6 +826,12 @@ class Sync extends RequestProcessor {
$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
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()));
......@@ -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));
break;
}
......@@ -1229,9 +1235,9 @@ class Sync extends RequestProcessor {
self::$encoder->endTag();
// log the request timeout
if (Request::IsRequestTimeoutReached()) {
ZLog::Write(LOGLEVEL_DEBUG, "HandleSync(): Stopping export as maximum request timeout is almost reached!");
// Send a <MoreAvailable/> tag if we reached the request timeout, there are more changes and a moreavailable was not already send
if (Request::IsRequestTimeoutReached() || Request::IsRequestMemoryLimitReached()) {
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 or max memory, there are more changes and a moreavailable was not already send
if (!$moreAvailableSent && ($n > $windowSize)) {
self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true);
$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