2008-01-14 22:25:03 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2008 Patrick Ohly
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "TrackingSyncSource.h"
|
2008-04-07 19:59:17 +02:00
|
|
|
#include "SafeConfigNode.h"
|
|
|
|
|
|
|
|
#include <ctype.h>
|
2008-01-14 22:25:03 +01:00
|
|
|
|
2008-03-06 23:23:13 +01:00
|
|
|
TrackingSyncSource::TrackingSyncSource(const EvolutionSyncSourceParams ¶ms) :
|
|
|
|
EvolutionSyncSource(params),
|
2008-04-07 19:59:17 +02:00
|
|
|
m_trackingNode(new SafeConfigNode(params.m_nodes.m_trackingNode))
|
2008-01-14 22:25:03 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrackingSyncSource::beginSyncThrow(bool needAll,
|
|
|
|
bool needPartial,
|
|
|
|
bool deleteLocal)
|
|
|
|
{
|
|
|
|
RevisionMap_t revisions;
|
|
|
|
listAllItems(revisions);
|
|
|
|
|
2008-02-03 12:23:30 +01:00
|
|
|
// slow sync or refresh-from-server/client: clear tracking node and
|
|
|
|
// recreate it based on current content of database
|
|
|
|
if (!needPartial) {
|
2008-04-10 21:54:02 +02:00
|
|
|
map<string, string> props;
|
|
|
|
m_trackingNode->readProperties(props);
|
2008-03-06 23:23:13 +01:00
|
|
|
|
|
|
|
for (map<string, string>::iterator it = props.begin();
|
|
|
|
it != props.end();
|
|
|
|
it++) {
|
|
|
|
const string &uid(it->first);
|
|
|
|
m_deletedItems.addItem(uid.c_str());
|
|
|
|
m_trackingNode->removeProperty(uid);
|
2008-02-03 12:23:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-14 22:25:03 +01:00
|
|
|
for (RevisionMap_t::const_iterator it = revisions.begin();
|
|
|
|
it != revisions.end();
|
|
|
|
it++) {
|
|
|
|
const string &uid = it->first;
|
|
|
|
const string &revision = it->second;
|
|
|
|
|
|
|
|
if (deleteLocal) {
|
|
|
|
deleteItem(uid);
|
|
|
|
} else {
|
|
|
|
// always remember the item, need full list to find deleted items
|
|
|
|
m_allItems.addItem(uid);
|
|
|
|
|
|
|
|
if (needPartial) {
|
2008-03-06 23:23:13 +01:00
|
|
|
string serverRevision(m_trackingNode->readProperty(uid));
|
2008-01-14 22:25:03 +01:00
|
|
|
|
2008-03-06 23:23:13 +01:00
|
|
|
if (!serverRevision.size()) {
|
2008-01-14 22:25:03 +01:00
|
|
|
m_newItems.addItem(uid);
|
2008-03-06 23:23:13 +01:00
|
|
|
m_trackingNode->setProperty(uid, revision);
|
2008-01-14 22:25:03 +01:00
|
|
|
} else {
|
2008-03-06 23:23:13 +01:00
|
|
|
if (revision != serverRevision) {
|
2008-01-14 22:25:03 +01:00
|
|
|
m_updatedItems.addItem(uid);
|
2008-03-06 23:23:13 +01:00
|
|
|
m_trackingNode->setProperty(uid, revision);
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
|
|
|
}
|
2008-02-03 12:23:30 +01:00
|
|
|
} else {
|
|
|
|
// refresh-from-client: make sure that all items we are about
|
|
|
|
// to send to server are also in our tracking node (otherwise
|
|
|
|
// the next incremental sync will go wrong)
|
2008-03-06 23:23:13 +01:00
|
|
|
m_trackingNode->setProperty(uid, revision);
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-03 12:23:30 +01:00
|
|
|
// clear information about all items that we recognized as deleted
|
2008-01-14 22:25:03 +01:00
|
|
|
if (needPartial) {
|
2008-04-10 21:54:02 +02:00
|
|
|
map<string, string> props;
|
|
|
|
m_trackingNode->readProperties(props);
|
2008-03-06 23:23:13 +01:00
|
|
|
|
|
|
|
for (map<string, string>::iterator it = props.begin();
|
|
|
|
it != props.end();
|
|
|
|
it++) {
|
|
|
|
const string &uid(it->first);
|
|
|
|
if (m_allItems.find(uid) == m_allItems.end()) {
|
|
|
|
m_deletedItems.addItem(uid.c_str());
|
|
|
|
m_trackingNode->removeProperty(uid);
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!needAll) {
|
|
|
|
// did not need full list after all...
|
|
|
|
m_allItems.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrackingSyncSource::endSyncThrow()
|
|
|
|
{
|
|
|
|
// store changes persistently
|
|
|
|
flush();
|
|
|
|
|
|
|
|
if (!hasFailed()) {
|
2008-03-06 23:23:13 +01:00
|
|
|
m_trackingNode->flush();
|
2008-01-14 22:25:03 +01:00
|
|
|
} else {
|
|
|
|
// SyncEvolution's error handling for failed sources
|
|
|
|
// forces a slow sync the next time. Therefore the
|
|
|
|
// content of the tracking node is irrelevant in
|
|
|
|
// case of a failure.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrackingSyncSource::exportData(ostream &out)
|
|
|
|
{
|
|
|
|
RevisionMap_t revisions;
|
|
|
|
listAllItems(revisions);
|
|
|
|
|
|
|
|
for (RevisionMap_t::const_iterator it = revisions.begin();
|
|
|
|
it != revisions.end();
|
|
|
|
it++) {
|
|
|
|
const string &uid = it->first;
|
2008-03-18 14:36:59 +01:00
|
|
|
cxxptr<SyncItem> item(createItem(uid), "sync item");
|
2008-01-14 22:25:03 +01:00
|
|
|
|
|
|
|
out << (char *)item->getData() << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int TrackingSyncSource::addItemThrow(SyncItem& item)
|
|
|
|
{
|
2008-04-07 20:38:25 +02:00
|
|
|
InsertItemResult res = insertItem("", item);
|
|
|
|
item.setKey(res.m_uid.c_str());
|
|
|
|
m_trackingNode->setProperty(res.m_uid, res.m_revision);
|
|
|
|
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int TrackingSyncSource::updateItemThrow(SyncItem& item)
|
|
|
|
{
|
2008-04-07 20:38:25 +02:00
|
|
|
const string uid = item.getKey();
|
|
|
|
InsertItemResult res = insertItem(uid, item);
|
|
|
|
if (res.m_uid != uid) {
|
|
|
|
m_trackingNode->removeProperty(uid);
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
2008-04-07 20:38:25 +02:00
|
|
|
item.setKey(res.m_uid.c_str());
|
|
|
|
m_trackingNode->setProperty(res.m_uid, res.m_revision);
|
|
|
|
return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
|
2008-01-14 22:25:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int TrackingSyncSource::deleteItemThrow(SyncItem& item)
|
|
|
|
{
|
|
|
|
const string uid = item.getKey();
|
|
|
|
deleteItem(uid);
|
2008-03-06 23:23:13 +01:00
|
|
|
m_trackingNode->removeProperty(uid);
|
2008-01-14 22:25:03 +01:00
|
|
|
return STC_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TrackingSyncSource::setItemStatusThrow(const char *uid, int status)
|
|
|
|
{
|
|
|
|
}
|