Skip to content

Commit

Permalink
Allow the GLOBAL_WINDOWSIZE to be overridden as well.
Browse files Browse the repository at this point in the history
For installs that really need to limit total responses due to
memory issues.

Also, fixes a small logic error that could lead to the global
windowsize being hit prematurely.
  • Loading branch information
mrubinsk committed Dec 12, 2015
1 parent 60cf793 commit ad5b32f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 22 deletions.
22 changes: 19 additions & 3 deletions framework/ActiveSync/lib/Horde/ActiveSync/Collections.php
Expand Up @@ -77,11 +77,19 @@ class Horde_ActiveSync_Collections implements IteratorAggregate

/**
* Global WINDOWSIZE
* Defaults to 100 (MS-ASCMD 2.2.3.188)
*
* @var integer
*/
protected $_globalWindowSize = 100;

/**
* Flag to indicate we have overridden the globalWindowSize
*
* @var boolean
*/
protected $_windowsizeOverride = false;

/**
* Imported changes flag.
*
Expand Down Expand Up @@ -432,11 +440,19 @@ public function getChangesFlag($collection_id)
* that can be sent (including all collections). This method should be
* renamed for 3.0
*
* @param integer $window The windowsize
* @param integer $window The windowsize
* @param boolean $override If true, this value will override any client
* supplied value.
*/
public function setDefaultWindowSize($window)
public function setDefaultWindowSize($window, $override = false)
{
$this->_globalWindowSize = $window;
if ($override) {
$this->_windowsizeOverride = true;
}

if ($override || empty($this->_windowsizeOverride)) {
$this->_globalWindowSize = $window;
}
}

public function getDefaultWindowSize()
Expand Down
15 changes: 10 additions & 5 deletions framework/ActiveSync/lib/Horde/ActiveSync/Request/Sync.php
Expand Up @@ -274,6 +274,11 @@ protected function _handle()

$pingSettings = $this->_driver->getHeartbeatConfig();

// Override the total, per-request, WINDOWSIZE?
if (!empty($pingSettings['maximumrequestwindowsize'])) {
$this->_collections->setDefaultWindowSize($pingSettings['maximumrequestwindowsize'], true);
}

// If this is >= 12.1, see if we want a looping SYNC.
if ($this->_collections->canDoLoopingSync() &&
$this->_device->version >= Horde_ActiveSync::VERSION_TWELVEONE &&
Expand Down Expand Up @@ -490,13 +495,13 @@ protected function _handle()
? min($collection['windowsize'], $pingSettings['maximumwindowsize'])
: $collection['windowsize'];

if ((!empty($changecount) && $changecount > $max_windowsize) ||
($cnt_global + $changecount > $this->_collections->getDefaultWindowSize())) {
if (!empty($changecount) &&
(($changecount > $max_windowsize) || $cnt_global + $max_windowsize > $this->_collections->getDefaultWindowSize())) {
$this->_logger->info(sprintf(
'[%s] Sending MOREAVAILABLE. WINDOWSIZE = %d, $changecount = %d, $cnt_global = %d',
$this->_procid, $max_windowsize, $changecount, $cnt_global));
'[%s] Sending MOREAVAILABLE. WINDOWSIZE = %d, $changecount = %d, MAX_REQUEST_WINDOWSIZE = %d, $cnt_global = %d',
$this->_procid, $max_windowsize, $changecount, $this->_collections->getDefaultWindowSize(), $cnt_global));
$this->_encoder->startTag(Horde_ActiveSync::SYNC_MOREAVAILABLE, false, true);
$over_window = ($cnt_global + $changecount > $this->_collections->getDefaultWindowSize());
$over_window = ($cnt_global + $max_windowsize > $this->_collections->getDefaultWindowSize());
}

if (!empty($changecount)) {
Expand Down
51 changes: 37 additions & 14 deletions horde/config/conf.xml
Expand Up @@ -2392,21 +2392,44 @@
during each heartbeat.">15</configinteger>
<configheader>Maximum Collection Window Size</configheader>
<configdescription>The Maximum Collection Window Size specifies the
maximum number of messages that can be sent to the client in a single
request before a MOREAVAILABLE flag is sent indicating the remaining
messages should be fetched in the next request. This is normally
automatically handled by the client but it may be helpful to explicitly
limit this if the server is hitting against PHP's memory limit. This is
especially true when synchronizing with Outlook, which has an
extremely high default window size. If you need to set this, start with
a value such as 100 and increase/decrease as necessary after testing. A
value of 0 indicates that the client's value will be honored. Setting this
to lower values will also make it appear that the client is performing the
initial sync quicker, at the expense of needing more server requests.
maximum number of messages from a single collection/folder that can be
sent to the client in a single request before a MOREAVAILABLE flag is sent
(indicating the remaining messages should be fetched in the next request).
This is normally automatically handled by the client but it may be helpful
to explicitly limit this if the server is hitting against PHP's memory
limit. This is especially true when synchronizing with Outlook, which has
an extremely high default window size.
There is also a per-REQUEST limit that can be enforced. The server will
NEVER send more than the per-request value in a single HTTP request. If
the server reaches the per-COLLECTION value, but not the per-REQUEST
value, a MOREAVAILABLE flag will be sent and processing will move on to
the next collection. This continues until the per-request value is
reached. So, for example, you may limit the total number of responses per
request to 100, but the per-collection limit to 10. This will limit the
size of the total response, while allowing more collections to begin to
populate sooner. Setting the per-request closer to or equal to the
per-collection value will still limit the total number of responses, but
it will take more requests to begin to populate each collection.
In Outlook, for example, it will take longer for individual email folders
to BEGIN to populate during initial sync.

If you need to set this, start with a total per-REQUEST limit of 100 and
increase/decrease as necessary after testing. A value of 0 indicates that
the client's value will be honored. Setting the per-REQUEST limit, but
leaving the per-COLLECTION limit at 0 will attempt to honor the
per-collection limit of the client, while still limiting the total number
of responses sent during a single HTTP request.

Setting this to lower values will also make it appear that the client is
performing the initial sync quicker, at the expense of needing more server
requests.
</configdescription>
<configinteger name="maximumwindowsize" desc="The Maximum Window Size to
use, overriding the client sent value. Set to 0 to use the client value.">
0</configinteger>
<configinteger name="maximumwindowsize" desc="The Maximum Collection
Window Size to use, overriding the client sent value. Set to 0 to use
the client value.">0</configinteger>
<configinteger name="maximumrequestwindowsize" desc="The Maximum Request
Window Size to use, overriding the client sent value. Set to 0 to use the
client value.">0</configinteger>
</configsection>
</case>
</configswitch>
Expand Down

0 comments on commit ad5b32f

Please sign in to comment.