From a1ee7d5cbf6a1ad60fb0cf96cd0d97c9e1d47eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lehrke?= Date: Tue, 1 Dec 2009 11:21:13 +0000 Subject: [PATCH] Optimize SyncML performance --- .../inc/horde/Horde/SyncML/Command/Alert.php | 211 +++++++++--------- .../inc/horde/Horde/SyncML/Command/Sync.php | 157 ++++++------- phpgwapi/inc/horde/Horde/SyncML/State.php | 2 +- phpgwapi/inc/horde/Horde/SyncML/State_egw.php | 5 +- phpgwapi/inc/horde/Horde/SyncML/Sync.php | 8 +- .../inc/horde/Horde/SyncML/Sync/SlowSync.php | 12 +- .../horde/Horde/SyncML/Sync/TwoWaySync.php | 37 +-- 7 files changed, 198 insertions(+), 234 deletions(-) diff --git a/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php b/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php index 9d30115b4e..fdf216b7e8 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php +++ b/phpgwapi/inc/horde/Horde/SyncML/Command/Alert.php @@ -174,119 +174,111 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command { // Determine sync type and status response code. Horde::logMessage("SyncML: Alert " . $this->_alert, __FILE__, __LINE__, PEAR_LOG_DEBUG); switch ($this->_alert) { - case ALERT_NEXT_MESSAGE: - $state->setAlert222Received(true); - case ALERT_RESULT_ALERT: - case ALERT_NO_END_OF_DATA: - // Nothing to do on our side - $status = new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert'); - $status->setCmdRef($this->_cmdID); - if ($this->_sourceLocURI != null) { - $status->setSourceRef($this->_sourceLocURI); - } - if ($this->_targetLocURI != null) { - $status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI)); - } - if ($this->_alert == ALERT_NEXT_MESSAGE) { - if ($this->_sourceLocURI != null) { - $status->setItemSourceLocURI($this->_sourceLocURI); - } - if ($this->_targetLocURI != null) { - $status->setItemTargetLocURI(isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI); - } - } - $currentCmdID = $status->output($currentCmdID, $output); - return $currentCmdID; - case ALERT_TWO_WAY: - if ($anchormatch) { - $synctype = ALERT_TWO_WAY; - $response = RESPONSE_OK; - } else { - $synctype = ALERT_SLOW_SYNC; - $response = RESPONSE_REFRESH_REQUIRED; - } - break; + case ALERT_NEXT_MESSAGE: + $state->setAlert222Received(true); + case ALERT_RESULT_ALERT: + case ALERT_NO_END_OF_DATA: + // Nothing to do on our side + $status = new Horde_SyncML_Command_Status(RESPONSE_OK, 'Alert'); + $status->setCmdRef($this->_cmdID); + if ($this->_sourceLocURI != null) { + $status->setSourceRef($this->_sourceLocURI); + } + if ($this->_targetLocURI != null) { + $status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI)); + } + if ($this->_alert == ALERT_NEXT_MESSAGE) { + if ($this->_sourceLocURI != null) { + $status->setItemSourceLocURI($this->_sourceLocURI); + } + if ($this->_targetLocURI != null) { + $status->setItemTargetLocURI(isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI); + } + } + $currentCmdID = $status->output($currentCmdID, $output); + return $currentCmdID; + case ALERT_TWO_WAY: + if ($anchormatch) { + $synctype = ALERT_TWO_WAY; + $response = RESPONSE_OK; + } else { + $synctype = ALERT_SLOW_SYNC; + $response = RESPONSE_REFRESH_REQUIRED; + } + break; - case ALERT_SLOW_SYNC: - $synctype = ALERT_SLOW_SYNC; - $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; - break; + case ALERT_SLOW_SYNC: + $synctype = ALERT_SLOW_SYNC; + $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; + break; - case ALERT_ONE_WAY_FROM_CLIENT: - if ($anchormatch) { - $synctype = ALERT_ONE_WAY_FROM_CLIENT; - $response = RESPONSE_OK; - } else { - $synctype = ALERT_REFRESH_FROM_CLIENT; - $response = RESPONSE_REFRESH_REQUIRED; - } - break; + case ALERT_ONE_WAY_FROM_CLIENT: + if ($anchormatch) { + $synctype = ALERT_ONE_WAY_FROM_CLIENT; + $response = RESPONSE_OK; + } else { + $synctype = ALERT_REFRESH_FROM_CLIENT; + $response = RESPONSE_REFRESH_REQUIRED; + } + break; - case ALERT_REFRESH_FROM_CLIENT: - $synctype = ALERT_REFRESH_FROM_CLIENT; - $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; + case ALERT_REFRESH_FROM_CLIENT: + $synctype = ALERT_REFRESH_FROM_CLIENT; + $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; - // We will erase the current server content, - // then we can add the client's contents. + // We will erase the current server content, + // then we can add the client's contents. - $hordeType = $state->getHordeType($this->_targetLocURI); + $hordeType = $state->getHordeType($this->_targetLocURI); - $state->setTargetURI($this->_targetLocURI); - $deletes = $state->getClientItems(); - if (is_array($deletes)) { - foreach ($deletes as $delete) { - $registry->call($hordeType . '/delete', array($delete)); - } - Horde::logMessage("SyncML: RefreshFromClient " . count($deletes) . " entries deleted for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG); - } - $anchormatch = false; - break; + $state->setTargetURI($this->_targetLocURI); + $deletes = $state->getClientItems(); + if (is_array($deletes)) { + foreach ($deletes as $delete) { + $registry->call($hordeType . '/delete', array($delete)); + } + Horde::logMessage("SyncML: RefreshFromClient " . count($deletes) . " entries deleted for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG); + } + $anchormatch = false; + break; - case ALERT_ONE_WAY_FROM_SERVER: - if ($anchormatch) { - $synctype = ALERT_ONE_WAY_FROM_SERVER; - $response = RESPONSE_OK; - } else { - $synctype = ALERT_REFRESH_FROM_SERVER; - $response = RESPONSE_REFRESH_REQUIRED; - } - break; + case ALERT_ONE_WAY_FROM_SERVER: + if ($anchormatch) { + $synctype = ALERT_ONE_WAY_FROM_SERVER; + $response = RESPONSE_OK; + } else { + $synctype = ALERT_REFRESH_FROM_SERVER; + $response = RESPONSE_REFRESH_REQUIRED; + } + break; - case ALERT_REFRESH_FROM_SERVER: - $synctype = ALERT_REFRESH_FROM_SERVER; - $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; - break; + case ALERT_REFRESH_FROM_SERVER: + $synctype = ALERT_REFRESH_FROM_SERVER; + $response = $anchormatch ? RESPONSE_OK : RESPONSE_REFRESH_REQUIRED; + break; - case ALERT_RESUME: - // @TODO: Suspend and Resume is not supported yet - $synctype = ALERT_SLOW_SYNC; - $response = RESPONSE_REFRESH_REQUIRED; - break; + case ALERT_RESUME: + // @TODO: Suspend and Resume is not supported yet + $synctype = ALERT_SLOW_SYNC; + $response = RESPONSE_REFRESH_REQUIRED; + break; - default: - // We can't handle this one - Horde::logMessage('SyncML: Unknown sync type ' . $this->_alert, - __FILE__, __LINE__, PEAR_LOG_ERR); - $status = new Horde_SyncML_Command_Status(RESPONSE_BAD_REQUEST, 'Alert'); - $status->setCmdRef($this->_cmdID); - if ($this->_sourceLocURI != null) { - $status->setSourceRef($this->_sourceLocURI); - } - if ($this->_targetLocURI != null) { - $status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI)); - } - $currentCmdID = $status->output($currentCmdID, $output); - return $currentCmdID; + default: + // We can't handle this one + Horde::logMessage('SyncML: Unknown sync type ' . $this->_alert, + __FILE__, __LINE__, PEAR_LOG_ERR); + $status = new Horde_SyncML_Command_Status(RESPONSE_BAD_REQUEST, 'Alert'); + $status->setCmdRef($this->_cmdID); + if ($this->_sourceLocURI != null) { + $status->setSourceRef($this->_sourceLocURI); + } + if ($this->_targetLocURI != null) { + $status->setTargetRef((isset($this->_targetLocURIParameters) ? $this->_targetLocURI.'?/'.$this->_targetLocURIParameters : $this->_targetLocURI)); + } + $currentCmdID = $status->output($currentCmdID, $output); + return $currentCmdID; } - // Store client's Next Anchor in State and - // set server's Next Anchor. After successful sync - // this is then written to persistence for negotiation of - // further syncs. - $state->setClientAnchorNext($type, $this->_metaAnchorNext); - $serverAnchorNext = time(); - $state->setServerAnchorNext($type, $serverAnchorNext); - // Now set interval to retrieve server changes from, defined by // ServerAnchor [Last,Next] if ($synctype != ALERT_TWO_WAY && @@ -305,7 +297,7 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command { . $this->_targetLocURI . '; sync type ' . $synctype, __FILE__, __LINE__, PEAR_LOG_DEBUG); $sync = &Horde_SyncML_Sync::factory($synctype); - $state->clearConflictItems($this->_targetLocURI); + $state->clearConflictItems($this->_targetLocURI); } $sync->setTargetLocURI($this->_targetLocURI); $sync->setSourceLocURI($this->_sourceLocURI); @@ -313,6 +305,21 @@ class Horde_SyncML_Command_Alert extends Horde_SyncML_Command { $sync->setsyncType($synctype); $sync->setFilterExpression($this->_filterExpression); $state->setSync($this->_targetLocURI, $sync); + $hordeType = $state->getHordeType($this->_targetLocURI); + $changes =& $registry->call($hordeType. '/listBy', + array('action' => 'modify', + 'timestamp' => $serverAnchorLast, + 'type' => $this->_targetLocURI, + 'filter' => $this->_filterExpression)); + $state->setChangedItems($this->_targetLocURI, $changes); + + // Store client's Next Anchor in State and + // set server's Next Anchor. After successful sync + // this is then written to persistence for negotiation of + // further syncs. + $state->setClientAnchorNext($type, $this->_metaAnchorNext); + $serverAnchorNext = time(); + $state->setServerAnchorNext($type, $serverAnchorNext); $status = new Horde_SyncML_Command_Status($response, 'Alert'); $status->setCmdRef($this->_cmdID); diff --git a/phpgwapi/inc/horde/Horde/SyncML/Command/Sync.php b/phpgwapi/inc/horde/Horde/SyncML/Command/Sync.php index a620cb6d5f..3c53651ddc 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/Command/Sync.php +++ b/phpgwapi/inc/horde/Horde/SyncML/Command/Sync.php @@ -127,87 +127,92 @@ class Horde_SyncML_Command_Sync extends Horde_SyncML_Command { function syncToClient($currentCmdID, &$output) { - Horde::logMessage('SyncML: starting sync to client', __FILE__, __LINE__, PEAR_LOG_DEBUG); + Horde::logMessage('SyncML: starting sync to client', + __FILE__, __LINE__, PEAR_LOG_DEBUG); - $state = &$_SESSION['SyncML.state']; + $state = &$_SESSION['SyncML.state']; - if($state->getSyncStatus() >= CLIENT_SYNC_FINNISHED && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) - { - $deviceInfo = $state->getClientDeviceInfo(); - $targets = $state->getTargets(); - foreach($targets as $target) - { - $sync = &$state->getSync($target); - Horde::logMessage('SyncML['. session_id() .']: sync alerttype '. $sync->_syncType .' found for target ' . $target, __FILE__, __LINE__, PEAR_LOG_DEBUG); - if ($sync->_syncType == ALERT_ONE_WAY_FROM_CLIENT || - $sync->_syncType == ALERT_REFRESH_FROM_CLIENT) { - - Horde::logMessage('SyncML['. session_id() .']: From client Sync, no sync of '. $target .' to client', __FILE__, __LINE__, PEAR_LOG_DEBUG); - $state->clearSync($target); - - } else if ($state->getSyncStatus() >= CLIENT_SYNC_ACKNOWLEDGED) { - - Horde::logMessage("SyncML: starting sync to client $target", __FILE__, __LINE__, PEAR_LOG_DEBUG); - $attrs = array(); - - $state->setSyncStatus(SERVER_SYNC_DATA_PENDING); - - $output->startElement($state->getURI(), 'Sync', $attrs); - $output->startElement($state->getURI(), 'CmdID', $attrs); - $output->characters($currentCmdID); - $currentCmdID++; - $output->endElement($state->getURI(), 'CmdID'); - - $output->startElement($state->getURI(), 'Target', $attrs); - $output->startElement($state->getURI(), 'LocURI', $attrs); - $chars = $sync->_sourceLocURI; - $output->characters($chars); - $output->endElement($state->getURI(), 'LocURI'); - $output->endElement($state->getURI(), 'Target'); - - $output->startElement($state->getURI(), 'Source', $attrs); - $output->startElement($state->getURI(), 'LocURI', $attrs); - $chars = (isset($sync->_targetLocURIParameters) ? $sync->_targetLocURI.'?/'.$sync->_targetLocURIParameters : $sync->_targetLocURI); - $output->characters($chars); - $output->endElement($state->getURI(), 'LocURI'); - $output->endElement($state->getURI(), 'Source'); - - if(!$sync->_syncDataLoaded) + if ($state->getSyncStatus() >= CLIENT_SYNC_FINNISHED + && $state->getSyncStatus() < SERVER_SYNC_FINNISHED) + { + $deviceInfo = $state->getClientDeviceInfo(); + if (($targets = $state->getTargets())) { + foreach ($targets as $target) { - $numberOfItems = $sync->loadData(); - if($deviceInfo['supportNumberOfChanges']) - { - $output->startElement($state->getURI(), 'NumberOfChanges', $attrs); - $output->characters($numberOfItems); - $output->endElement($state->getURI(), 'NumberOfChanges'); - } + $sync = &$state->getSync($target); + Horde::logMessage('SyncML[' . session_id() . ']: sync alerttype ' . + $sync->_syncType . ' found for target ' . $target, + __FILE__, __LINE__, PEAR_LOG_DEBUG); + if ($sync->_syncType == ALERT_ONE_WAY_FROM_CLIENT || + $sync->_syncType == ALERT_REFRESH_FROM_CLIENT) { + Horde::logMessage('SyncML[' . session_id() . + ']: From client Sync, no sync of ' . $target . + ' to client', __FILE__, __LINE__, PEAR_LOG_DEBUG); + $state->clearSync($target); + + } elseif ($state->getSyncStatus() >= CLIENT_SYNC_ACKNOWLEDGED) { + + Horde::logMessage("SyncML: starting sync to client $target", + __FILE__, __LINE__, PEAR_LOG_DEBUG); + $attrs = array(); + + $state->setSyncStatus(SERVER_SYNC_DATA_PENDING); + + $output->startElement($state->getURI(), 'Sync', $attrs); + $output->startElement($state->getURI(), 'CmdID', $attrs); + $output->characters($currentCmdID); + $currentCmdID++; + $output->endElement($state->getURI(), 'CmdID'); + + $output->startElement($state->getURI(), 'Target', $attrs); + $output->startElement($state->getURI(), 'LocURI', $attrs); + $chars = $sync->_sourceLocURI; + $output->characters($chars); + $output->endElement($state->getURI(), 'LocURI'); + $output->endElement($state->getURI(), 'Target'); + + $output->startElement($state->getURI(), 'Source', $attrs); + $output->startElement($state->getURI(), 'LocURI', $attrs); + $chars = (isset($sync->_targetLocURIParameters) ? $sync->_targetLocURI.'?/'.$sync->_targetLocURIParameters : $sync->_targetLocURI); + $output->characters($chars); + $output->endElement($state->getURI(), 'LocURI'); + $output->endElement($state->getURI(), 'Source'); + + if(!$sync->_syncDataLoaded) + { + $numberOfItems = $sync->loadData(); + if($deviceInfo['supportNumberOfChanges']) + { + $output->startElement($state->getURI(), 'NumberOfChanges', $attrs); + $output->characters($numberOfItems); + $output->endElement($state->getURI(), 'NumberOfChanges'); + } + } + + $currentCmdID = $sync->endSync($currentCmdID, $output); + + $output->endElement($state->getURI(), 'Sync'); + + if (isset($state->curSyncItem) || + $state->getNumberOfElements() === false) { + break; + } + } else { + Horde::logMessage("SyncML: Waiting for client ACKNOWLEDGE for $target", + __FILE__, __LINE__, PEAR_LOG_DEBUG); + } } + } - $currentCmdID = $sync->endSync($currentCmdID, $output); - - $output->endElement($state->getURI(), 'Sync'); - - if (isset($state->curSyncItem) || - $state->getNumberOfElements() === false) { - break; - } - } else { - Horde::logMessage("SyncML: Waiting for client ACKNOWLEDGE for $target", __FILE__, __LINE__, PEAR_LOG_DEBUG); - } - } - - // no syncs left - if($state->getTargets() === FALSE && - !isset($state->curSyncItem)) { - $state->setSyncStatus(SERVER_SYNC_FINNISHED); - } - - Horde::logMessage('SyncML: syncStatus(syncToClient) = '. $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG); - - } - - return $currentCmdID; - + // no syncs left + if ($state->getTargets() === false && + !isset($state->curSyncItem)) { + $state->setSyncStatus(SERVER_SYNC_FINNISHED); + } + Horde::logMessage('SyncML: syncStatus(syncToClient) = ' . + $state->getSyncStatus(), __FILE__, __LINE__, PEAR_LOG_DEBUG); + } + return $currentCmdID; } function endElement($uri, $element) diff --git a/phpgwapi/inc/horde/Horde/SyncML/State.php b/phpgwapi/inc/horde/Horde/SyncML/State.php index e695a256f0..61c744a551 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/State.php +++ b/phpgwapi/inc/horde/Horde/SyncML/State.php @@ -612,7 +612,7 @@ class Horde_SyncML_State { function getTargets() { if(count($this->_syncs) < 1) - return FALSE; + return false; foreach($this->_syncs as $target => $sync) { diff --git a/phpgwapi/inc/horde/Horde/SyncML/State_egw.php b/phpgwapi/inc/horde/Horde/SyncML/State_egw.php index 6efaae12bb..92d5a60c1e 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/State_egw.php +++ b/phpgwapi/inc/horde/Horde/SyncML/State_egw.php @@ -213,8 +213,9 @@ class EGW_SyncML_State extends Horde_SyncML_State /** * returns GUIDs of all client items */ - function getClientItems() { - $mapID = $this->_locName . $this->_sourceURI . $this->_targetURI; + function getClientItems($type=false) { + if (!$type) $type = $this->_targetURI; + $mapID = $this->_locName . $this->_sourceURI . $type; $guids = array(); foreach($GLOBALS['egw']->db->select('egw_contentmap', 'map_guid', array( diff --git a/phpgwapi/inc/horde/Horde/SyncML/Sync.php b/phpgwapi/inc/horde/Horde/SyncML/Sync.php index ef21fb19dd..dd4c9a7450 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/Sync.php +++ b/phpgwapi/inc/horde/Horde/SyncML/Sync.php @@ -177,14 +177,8 @@ class Horde_SyncML_Sync { $sourceURI = $state->getSourceURI(); $hordeType = $state->getHordeType($type); $serverAnchorLast = $state->getServerAnchorLast($type); - $state->setTargetURI($type); $changes = array(); - // First we get all changes done after the previous sync start - foreach ($registry->call($hordeType. '/listBy', - array('action' => 'modify', - 'timestamp' => $serverAnchorLast, - 'type' => $type, - 'filter' => $this->_filterExpression)) as $change) { + foreach($state->getChangedItems($type) as $change) { // now we have to remove the ones // that came from the last sync with this client $guid_ts = $state->getSyncTSforAction($change, 'modify'); diff --git a/phpgwapi/inc/horde/Horde/SyncML/Sync/SlowSync.php b/phpgwapi/inc/horde/Horde/SyncML/Sync/SlowSync.php index d91c05274b..8a9d704f9c 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/Sync/SlowSync.php +++ b/phpgwapi/inc/horde/Horde/SyncML/Sync/SlowSync.php @@ -308,21 +308,11 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync { $hordeType = $state->getHordeType($syncType); $state->setTargetURI($syncType); $future = $state->getServerAnchorNext($syncType); - $delta_add = 0; - Horde::logMessage("SyncML: reading added items from database for $hordeType", - __FILE__, __LINE__, PEAR_LOG_DEBUG); - /* The items, which now match the filter criteria are show here, too - $delta_add = count($registry->call($hordeType. '/listBy', - array('action' => 'add', - 'timestamp' => $future, - 'type' => $syncType, - 'filter' => $this->_filterExpression))); - */ $state->mergeAddedItems($syncType, $registry->call($hordeType. '/list', array('filter' => $this->_filterExpression))); $this->_syncDataLoaded = TRUE; - return count($state->getAddedItems($syncType)) - $delta_add + count($state->getConflictItems($syncType)); + return count($state->getAddedItems($syncType)) + count($state->getConflictItems($syncType)); } } diff --git a/phpgwapi/inc/horde/Horde/SyncML/Sync/TwoWaySync.php b/phpgwapi/inc/horde/Horde/SyncML/Sync/TwoWaySync.php index 267ef372a7..d68ba1ccfc 100644 --- a/phpgwapi/inc/horde/Horde/SyncML/Sync/TwoWaySync.php +++ b/phpgwapi/inc/horde/Horde/SyncML/Sync/TwoWaySync.php @@ -409,27 +409,8 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync { $state = & $_SESSION['SyncML.state']; $syncType = $this->_targetLocURI; $hordeType = $state->getHordeType($syncType); - $state->setTargetURI($syncType); $refts = $state->getServerAnchorLast($syncType); $future = $state->getServerAnchorNext($syncType); - $delta_mod = 0; - $delta_add = 0; - - Horde :: logMessage("SyncML: reading changed items from database for $hordeType", - __FILE__, __LINE__, PEAR_LOG_DEBUG); - $delta_mod = count($registry->call($hordeType . '/listBy', array ( - 'action' => 'modify', - 'timestamp' => $future, - 'type' => $syncType, - 'filter' => $this->_filterExpression - ))); - - $changedItems =& $registry->call($hordeType . '/listBy', array ( - 'action' => 'modify', - 'timestamp' => $refts, - 'type' => $syncType, - 'filter' => $this->_filterExpression - )); $addedItems =& $registry->call($hordeType . '/listBy', array ( 'action' => 'add', @@ -438,12 +419,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync { 'filter' => $this->_filterExpression )); - // added items may show up as changed, too - $changedItems = array_diff($changedItems, $addedItems); - - $state->mergeChangedItems($syncType, $changedItems); - - $state->mergeAddedItems($syncType, $addedItems); + $state->setAddedItems($syncType, $addedItems); $state->setDeletedItems($syncType, $registry->call($hordeType . '/listBy', array ( 'action' => 'delete', @@ -452,17 +428,8 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync { 'filter' => $this->_filterExpression ))); - /* The items, which now match the filter criteria are show here, too - $delta_add = count($registry->call($hordeType . '/listBy', array ( - 'action' => 'add', - 'timestamp' => $future, - 'type' => $syncType, - 'filter' => $this->_filterExpression - ))); - */ - $this->_syncDataLoaded = TRUE; - return count($state->getChangedItems($syncType)) - $delta_mod + count($state->getDeletedItems($syncType)) + count($state->getAddedItems($syncType)) - $delta_add + count($state->getConflictItems($syncType)); + return count($state->getChangedItems($syncType)) + count($state->getDeletedItems($syncType)) + count($state->getAddedItems($syncType)) + count($state->getConflictItems($syncType)); } } \ No newline at end of file