2 * Copyright (C) 2008-2009 Patrick Ohly <patrick.ohly@gmx.de>
3 * Copyright (C) 2009 Intel Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) version 3.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #ifndef INCL_TRACKINGSYNCSOURCE
22 #define INCL_TRACKINGSYNCSOURCE
24 #include <syncevo/SyncSource.h>
25 #include <syncevo/ConfigNode.h>
27 #include <boost/shared_ptr.hpp>
31 #include <syncevo/declarations.h>
36 * This class implements change tracking. Data sources which want to use
37 * this functionality have to provide the following functionality
38 * by implementing the pure virtual functions below:
40 * - enumerate all existing items
41 * - provide LUID and "revision string":
42 * The LUID must remain *constant* when the user edits an item (it
43 * may change when SyncEvolution changes an item), whereas the
44 * revision string must *change* each time the item is changed
46 * Both can be arbitrary strings, but keeping them simple (printable
47 * ASCII, no white spaces, no equal sign) makes debugging simpler
48 * because they can be stored as they are as key/value pairs in the
49 * sync source's change tracking config node (the .other.ini files when
50 * using file-based configuration). More complex strings use escape
51 * sequences introduced with an exclamation mark for unsafe characters.
52 * - import/export/update single items
53 * - persistently store all changes in flush()
54 * - clean up in close()
56 * A derived class may (but doesn't have to) override additional
57 * functions to modify or replace the default implementations, e.g.:
58 * - dumping the complete database (export())
60 * Potential implementations of the revision string are:
61 * - a modification time stamp
62 * - a hash value of a textual representation of the item
63 * (beware, such a hash might change as the textual representation
64 * changes even though the item is unchanged)
66 class TrackingSyncSource : public TestingSyncSource,
67 virtual public SyncSourceRevisions,
68 virtual public SyncSourceAdmin
72 * Creates a new tracking sync source.
74 * @param granularity sync sources whose revision string
75 * is based on time should specify the number
76 * of seconds which has to pass before changes
77 * are detected reliably (see SyncSourceRevisions
78 * for details), otherwise pass 0
80 TrackingSyncSource(const SyncSourceParams ¶ms,
81 int granularitySeconds = 1);
82 ~TrackingSyncSource() {}
85 * ConfigNode used for change tracking in SyncSourceRevisions.
86 * Derived classes might need that when implementing operations
87 * which have side effects on other items (for example,
88 * EvolutionCalendarSource::removeItem()).
90 ConfigNode &getTrackingNode() { return *m_trackingNode; }
93 * returns a list of all know sources for the kind of items
94 * supported by this sync source
96 virtual Databases getDatabases() = 0;
99 * Actually opens the data source specified in the constructor,
100 * will throw the normal exceptions if that fails. Should
101 * not modify the state of the sync source.
103 * The expectation is that this call is fairly light-weight, but
104 * does enough checking to determine whether the source is
105 * usable. More expensive operations (like determining changes)
106 * should be done in the beginSync() callback.
108 * In clients, it will be called for all sources before
109 * the sync starts. In servers, it is called for each source once
110 * the client asks for it, but not sooner.
112 virtual void open() = 0;
115 * A quick check whether the source currently has data. Currently
116 * used as part of the "allow slow sync" checking after open() and
117 * before beginSync(). Returning false is acceptable when it is
118 * uncertain and too expensive to check.
120 virtual bool isEmpty() = 0;
123 * fills the complete mapping from LUID to revision string of all
124 * currently existing items
126 * Usually both LUID and revision string must be non-empty. The
127 * only exception is a refresh-from-client: in that case the
128 * revision string may be empty. The implementor of this call
129 * cannot know whether empty strings are allowed, therefore it
130 * should not throw errors when it cannot create a non-empty
131 * string. The caller of this method will detect situations where
132 * a non-empty string is necessary and none was provided.
134 virtual void listAllItems(SyncSourceRevisions::RevisionMap_t &revisions) = 0;
137 * Create or modify an item.
139 * The sync source should be flexible: if the LUID is non-empty, it
140 * shall modify the item referenced by the LUID. If the LUID is
141 * empty, the normal operation is to add it. But if the item
142 * already exists (e.g., a calendar event which was imported
143 * by the user manually), then the existing item should be
144 * updated also in the second case.
146 * Passing a LUID of an item which does not exist is an error.
147 * This error should be reported instead of covering it up by
148 * (re)creating the item.
150 * Errors are signaled by throwing an exception. Returning empty
151 * strings in the result is an error which triggers an "item could
152 * not be stored" error.
154 * @param luid identifies the item to be modified, empty for creating
155 * @param item contains the new content of the item
156 * @param raw item has internal format instead of engine format;
157 * testing and backup/restore might use such an internal format
158 * which may be different (more complete!) than the
159 * format when talking to the sync engine
160 * @return the result of inserting the item
162 virtual InsertItemResult insertItem(const std::string &luid, const std::string &item, bool raw) = 0;
165 * Return item data in engine format.
167 * @param luid identifies the item
168 * @param raw return item in internal format instead of engine format
169 * @retval item item data
171 virtual void readItem(const std::string &luid, std::string &item, bool raw) = 0;
174 * delete the item (renamed so that it can be wrapped by deleteItem())
176 virtual void removeItem(const string &luid) = 0;
179 * optional: write all changes, throw error if that fails
181 * This is called while the sync is still active whereas
182 * close() is called afterwards. Reporting problems
183 * as early as possible may be useful at some point,
184 * but currently doesn't make a relevant difference.
186 virtual void flush() {}
189 * closes the data source so that it can be reopened
191 * Just as open() it should not affect the state of
192 * the database unless some previous action requires
195 virtual void close() = 0;
198 * Returns the preferred mime type of the items handled by the sync source.
199 * Example: "text/x-vcard"
201 virtual const char *getMimeType() const = 0;
204 * Returns the version of the mime type used by client.
207 virtual const char *getMimeVersion() const = 0;
209 using SyncSource::getName;
212 void checkStatus(SyncSourceReport &changes);
214 /* implementations of SyncSource callbacks */
215 virtual void beginSync(const std::string &lastToken, const std::string &resumeToken);
216 virtual std::string endSync(bool success);
217 virtual void deleteItem(const string &luid);
218 virtual InsertItemResult insertItem(const std::string &luid, const std::string &item);
219 virtual void readItem(const std::string &luid, std::string &item);
220 virtual InsertItemResult insertItemRaw(const std::string &luid, const std::string &item);
221 virtual void readItemRaw(const std::string &luid, std::string &item);
222 virtual void enableServerMode();
223 virtual bool serverModeEnabled() const;
224 virtual const char *getPeerMimeType() const;
226 boost::shared_ptr<ConfigNode> m_trackingNode;
231 #endif // INCL_TRACKINGSYNCSOURCE