00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "TrackingSyncSource.h"
00020 #include "SafeConfigNode.h"
00021 #include "PrefixConfigNode.h"
00022
00023 #include <ctype.h>
00024
00025 TrackingSyncSource::TrackingSyncSource(const EvolutionSyncSourceParams ¶ms) :
00026 EvolutionSyncSource(params),
00027 m_trackingNode(new PrefixConfigNode("item-",
00028 boost::shared_ptr<ConfigNode>(new SafeConfigNode(params.m_nodes.m_trackingNode))))
00029 {
00030 }
00031
00032 void TrackingSyncSource::beginSyncThrow(bool needAll,
00033 bool needPartial,
00034 bool deleteLocal)
00035 {
00036 RevisionMap_t revisions;
00037 listAllItems(revisions);
00038
00039
00040
00041 if (!needPartial) {
00042 map<string, string> props;
00043 m_trackingNode->readProperties(props);
00044
00045 BOOST_FOREACH(const StringPair &prop, props) {
00046 const string &uid(prop.first);
00047 m_deletedItems.addItem(uid.c_str());
00048 m_trackingNode->removeProperty(uid);
00049 }
00050 }
00051
00052 BOOST_FOREACH(const StringPair &mapping, revisions) {
00053 const string &uid = mapping.first;
00054 const string &revision = mapping.second;
00055
00056
00057
00058
00059
00060 if (uid.empty()) {
00061 throwError("could not read UID for an item");
00062 }
00063 bool fromClient = needAll && !needPartial && !deleteLocal;
00064 if (!fromClient && revision.empty()) {
00065 throwError(string("could not read revision identifier for item ") + uid + ": only refresh-from-client synchronization is supported");
00066 }
00067
00068 if (deleteLocal) {
00069 deleteItem(uid);
00070 } else {
00071
00072 m_allItems.addItem(uid);
00073
00074 if (needPartial) {
00075 string serverRevision(m_trackingNode->readProperty(uid));
00076
00077 if (!serverRevision.size()) {
00078 m_newItems.addItem(uid);
00079 m_trackingNode->setProperty(uid, revision);
00080 } else {
00081 if (revision != serverRevision) {
00082 m_updatedItems.addItem(uid);
00083 m_trackingNode->setProperty(uid, revision);
00084 }
00085 }
00086 } else {
00087
00088
00089
00090 m_trackingNode->setProperty(uid, revision);
00091 }
00092 }
00093 }
00094
00095
00096 if (needPartial) {
00097 map<string, string> props;
00098 m_trackingNode->readProperties(props);
00099
00100 BOOST_FOREACH(const StringPair &mapping, props) {
00101 const string &uid(mapping.first);
00102 if (m_allItems.find(uid) == m_allItems.end()) {
00103 m_deletedItems.addItem(uid);
00104 m_trackingNode->removeProperty(uid);
00105 }
00106 }
00107 }
00108
00109 if (!needAll) {
00110
00111 m_allItems.clear();
00112 }
00113 }
00114
00115 void TrackingSyncSource::endSyncThrow()
00116 {
00117
00118 flush();
00119
00120 if (!hasFailed()) {
00121 m_trackingNode->flush();
00122 } else {
00123
00124
00125
00126
00127 }
00128 }
00129
00130 void TrackingSyncSource::exportData(ostream &out)
00131 {
00132 RevisionMap_t revisions;
00133 listAllItems(revisions);
00134
00135 BOOST_FOREACH(const StringPair &mapping, revisions) {
00136 const string &uid = mapping.first;
00137 cxxptr<SyncItem> item(createItem(uid), "sync item");
00138
00139 out << (char *)item->getData() << "\n";
00140 }
00141 }
00142
00143 int TrackingSyncSource::addItemThrow(SyncItem& item)
00144 {
00145 InsertItemResult res = insertItem("", item);
00146 item.setKey(res.m_uid.c_str());
00147 if (res.m_uid.empty() || res.m_revision.empty()) {
00148 throwError("could not add item");
00149 }
00150 m_trackingNode->setProperty(res.m_uid, res.m_revision);
00151 return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
00152 }
00153
00154 int TrackingSyncSource::updateItemThrow(SyncItem& item)
00155 {
00156 const string uid = item.getKey();
00157 InsertItemResult res = insertItem(uid, item);
00158 if (res.m_uid != uid) {
00159 m_trackingNode->removeProperty(uid);
00160 }
00161 item.setKey(res.m_uid.c_str());
00162 if (res.m_uid.empty() || res.m_revision.empty()) {
00163 throwError("could not update item");
00164 }
00165 m_trackingNode->setProperty(res.m_uid, res.m_revision);
00166 return res.m_merged ? STC_CONFLICT_RESOLVED_WITH_MERGE : STC_OK;
00167 }
00168
00169 int TrackingSyncSource::deleteItemThrow(SyncItem& item)
00170 {
00171 const string uid = item.getKey();
00172 deleteItem(uid);
00173 m_trackingNode->removeProperty(uid);
00174 return STC_OK;
00175 }
00176
00177 void TrackingSyncSource::setItemStatusThrow(const char *uid, int status)
00178 {
00179 }