Page MenuHomePhorge

No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/kolab_sync_backend_state.php b/lib/kolab_sync_backend_state.php
index dfd2127..b239d36 100644
--- a/lib/kolab_sync_backend_state.php
+++ b/lib/kolab_sync_backend_state.php
@@ -1,202 +1,201 @@
<?php
/**
+--------------------------------------------------------------------------+
| Kolab Sync (ActiveSync for Kolab) |
| |
| Copyright (C) 2011-2012, Kolab Systems AG <contact@kolabsys.com> |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/> |
+--------------------------------------------------------------------------+
| Author: Aleksander Machniak <machniak@kolabsys.com> |
+--------------------------------------------------------------------------+
*/
/**
* Kolab backend class for the folder state storage
*/
class kolab_sync_backend_state extends kolab_sync_backend_common implements Syncroton_Backend_ISyncState
{
protected $table_name = 'syncroton_synckey';
protected $interface_name = 'Syncroton_Model_ISyncState';
/**
* create new sync state
*
* @param Syncroton_Model_ISyncState $_syncState
* @return Syncroton_Model_SyncState
*/
public function create($object, $_keepPreviousSyncState = true)
{
$object = parent::create($object);
if ($_keepPreviousSyncState !== true) {
// remove all other synckeys
$this->_deleteOtherStates($object);
}
return $object;
}
protected function _deleteOtherStates(Syncroton_Model_ISyncState $_state)
{
// remove all other synckeys
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($_state->device_id);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($_state->type);
$where[] = $this->db->quote_identifier('counter') . ' <> ' . $this->db->quote($_state->counter);
$this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
return true;
}
/**
* @see kolab_sync_backend_common::object_to_array()
*/
protected function object_to_array($object)
{
$data = parent::object_to_array($object);
if (is_array($object->pendingdata)) {
$data['pendingdata'] = json_encode($object->pendingdata);
}
return $data;
}
/**
* @see kolab_sync_backend_common::get_object()
*/
protected function get_object($data)
{
$object = parent::get_object($data);
if ($object->pendingdata) {
$object->pendingdata = json_decode($object->pendingdata);
}
return $object;
}
/**
* always returns the latest syncstate
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
* @return Syncroton_Model_SyncState
*/
public function getSyncState($_deviceId, $_folderId)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$select = $this->db->limitquery('SELECT * FROM ' . $this->table_name . ' WHERE ' . implode(' AND ', $where)
.' ORDER BY counter DESC', 0, 1);
$state = $this->db->fetch_assoc($select);
if (empty($state)) {
throw new Syncroton_Exception_NotFound('SyncState not found');
}
return $this->get_object($state);
}
/**
* delete all stored synckeys for given type
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
*/
public function resetState($_deviceId, $_folderId)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
$where[] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where[] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
$this->db->query('DELETE FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
}
/**
* get array of ids which got send to the client for a given class
*
* @param Syncroton_Model_IDevice|string $_deviceId
* @param Syncroton_Model_IFolder|string $_folderId
*
* @return Syncroton_Model_SyncState
*/
public function validate($_deviceId, $_folderId, $_syncKey)
{
$deviceId = $_deviceId instanceof Syncroton_Model_IDevice ? $_deviceId->id : $_deviceId;
$folderId = $_folderId instanceof Syncroton_Model_IFolder ? $_folderId->id : $_folderId;
+ // get sync data for current request and check if it's the last one
+ // by fetching synckey+1
+ $states = array();
+ $keys = array($_syncKey, $_syncKey + 1);
+
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['type'] = $this->db->quote_identifier('type') . ' = ' . $this->db->quote($folderId);
- $where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey);
+ $where['counter'] = $this->db->quote_identifier('counter') . ' IN (' . $this->db->array2list($keys, 'int') . ')';
- $select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
- $state = $this->db->fetch_assoc($select);
+ $select = $this->db->query('SELECT * FROM ' . $this->table_name .' WHERE ' . implode(' AND ', $where));
- if (empty($state)) {
- return false;
+ while ($row = $this->db->fetch_assoc($select)) {
+ $states[$row['counter']] = $this->get_object($row);
}
- $state = $this->get_object($state);
-
- // check if this was the latest syncKey
- $where['counter'] = $this->db->quote_identifier('counter') . ' = ' . $this->db->quote($_syncKey + 1);
-
- $select = $this->db->query('SELECT * FROM syncroton_synckey WHERE ' . implode(' AND ', $where));
-
- if ($moreRecentState = $this->db->fetch_assoc($select)) {
- $moreRecentState = $this->get_object($moreRecentState);
+ if (empty($states) || empty($states[$_syncKey])) {
+ return false;
}
+ $state = $states[$_syncKey];
+
$where = array();
$where['device_id'] = $this->db->quote_identifier('device_id') . ' = ' . $this->db->quote($deviceId);
$where['folder_id'] = $this->db->quote_identifier('folder_id') . ' = ' . $this->db->quote($folderId);
$where['is_deleted'] = $this->db->quote_identifier('is_deleted') . ' = 1';
// found more recent synckey => the last sync repsonse got not received by the client
- if ($moreRecentState instanceof Syncroton_Model_ISyncState) {
+ if (!empty($states[$_syncKey + 1])) {
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' = ' . $this->db->quote($state->counter);
- // undelete entries marked as deleted in Syncroton_content table
+ // undelete entries marked as deleted in syncroton_content table
$this->db->query('UPDATE syncroton_content SET is_deleted = 0 WHERE ' . implode(' AND ', $where));
- // remove entries added during latest sync in Syncroton_content table
+ // remove entries added during latest sync in syncroton_content table
unset($where['is_deleted']);
$where['synckey'] = $this->db->quote_identifier('creation_synckey') . ' > ' . $this->db->quote($state->counter);
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
else {
- // finaly delete all entries marked for removal in Syncroton_content table
+ // finaly delete all entries marked for removal in syncroton_content table
$this->db->query('DELETE FROM syncroton_content WHERE ' . implode(' AND ', $where));
}
// remove all other synckeys
$this->_deleteOtherStates($state);
return $state;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Apr 18, 10:12 AM (4 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
435672
Default Alt Text
(9 KB)

Event Timeline