00001 /* 00002 * Copyright (C) 2005-2008 Patrick Ohly 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 #ifndef INCL_EVOLUTIONSYNCSOURCE 00020 #define INCL_EVOLUTIONSYNCSOURCE 00021 00022 #include "config.h" 00023 #include "SyncEvolutionConfig.h" 00024 #include "EvolutionSmartPtr.h" 00025 00026 #include <boost/shared_ptr.hpp> 00027 #include <string> 00028 #include <vector> 00029 #include <set> 00030 #include <ostream> 00031 #include <stdexcept> 00032 using namespace std; 00033 00034 #include <time.h> 00035 00036 #include <spds/SyncSource.h> 00037 #include <spdm/ManagementNode.h> 00038 #include <base/Log.h> 00039 00040 #include "eds_abi_wrapper.h" 00041 00042 class EvolutionSyncSource; 00043 00044 /** 00045 * This set of parameters always has to be passed when constructing 00046 * EvolutionSyncSource instances. 00047 */ 00048 struct EvolutionSyncSourceParams { 00049 /** 00050 * @param name the name needed by SyncSource 00051 * @param nodes a set of config nodes to be used by this source 00052 * @param changeId is used to track changes in the Evolution backend: 00053 * a unique string constructed from an ID for SyncEvolution 00054 * and the URL/database we synchronize against 00055 */ 00056 EvolutionSyncSourceParams(const string &name, 00057 const SyncSourceNodes &nodes, 00058 const string &changeId) : 00059 m_name(name), 00060 m_nodes(nodes), 00061 m_changeId(stripChangeId(changeId)) 00062 {} 00063 00064 const string m_name; 00065 const SyncSourceNodes m_nodes; 00066 const string m_changeId; 00067 00068 /** remove special characters from change ID */ 00069 static string stripChangeId(const string changeId) { 00070 string strippedChangeId = changeId; 00071 size_t offset = 0; 00072 while (offset < strippedChangeId.size()) { 00073 switch (strippedChangeId[offset]) { 00074 case ':': 00075 case '/': 00076 case '\\': 00077 strippedChangeId.erase(offset, 1); 00078 break; 00079 default: 00080 offset++; 00081 } 00082 } 00083 return strippedChangeId; 00084 } 00085 }; 00086 00087 /** 00088 * The SyncEvolution core has no knowledge of existing SyncSource 00089 * implementations. Implementations have to register themselves 00090 * by instantiating this class exactly once with information 00091 * about themselves. 00092 * 00093 * It is also possible to add configuration options. For that define a 00094 * derived class. In its constructor use 00095 * EvolutionSyncSourceConfig::getRegistry() 00096 * resp. EvolutionSyncConfig::getRegistry() to define new 00097 * configuration properties. The advantage of registering them is that 00098 * the user interface will automatically handle them like the 00099 * predefined ones. The namespace of these configuration options 00100 * is shared by all sources and the core. 00101 * 00102 * For properties with arbitrary names use the 00103 * SyncSourceNodes::m_trackingNode. 00104 */ 00105 class RegisterSyncSource 00106 { 00107 public: 00108 /** 00109 * Users select a SyncSource and its data format via the "type" 00110 * config property. Backends have to add this kind of function to 00111 * the SourceRegistry_t in order to be considered by the 00112 * SyncSource creation mechanism. 00113 * 00114 * The function will be called to check whether the backend was 00115 * meant by the user. It should return a new instance which will 00116 * be freed by the caller or NULL if it does not support the 00117 * selected type. 00118 * 00119 * Inactive sources should return the special InactiveSource 00120 * pointer value if they recognize without a doubt that the user 00121 * wanted to instantiate them: for example, an inactive 00122 * EvolutionContactSource will return NULL for "addressbook" but 00123 * InactiveSource for "evolution-contacts". 00124 */ 00125 typedef EvolutionSyncSource *(*Create_t)(const EvolutionSyncSourceParams ¶ms); 00126 00127 /** special return value of Create_t, not a real sync source! */ 00128 static EvolutionSyncSource *const InactiveSource; 00129 00130 /** 00131 * @param shortDescr a few words identifying the data to be synchronized, 00132 * e.g. "Evolution Calendar" 00133 * @param enabled true if the sync source can be instantiated, 00134 * false if it was not enabled during compilation or is 00135 * otherwise not functional 00136 * @param create factory function for sync sources of this type 00137 * @param typeDescr multiple lines separated by \n which get appended to 00138 * the the description of the type property, e.g. 00139 * "Evolution Memos = memo = evolution-memo\n" 00140 * " plain text in UTF-8 (default) = text/plain\n" 00141 * " iCalendar 2.0 = text/calendar\n" 00142 * " The later format is not tested because none of the\n" 00143 * " supported SyncML servers accepts it.\n" 00144 * @param typeValues the config accepts multiple names for the same internal 00145 * type string; this list here is added to that list of 00146 * aliases. It should contain at least one unique string 00147 * the can be used to pick this sync source among all 00148 * SyncEvolution sync sources (testing, listing backends, ...). 00149 * Example: Values() + (Aliases("Evolution Memos") + "evolution-memo") 00150 */ 00151 RegisterSyncSource(const string &shortDescr, 00152 bool enabled, 00153 Create_t create, 00154 const string &typeDescr, 00155 const Values &typeValues); 00156 public: 00157 const string m_shortDescr; 00158 const bool m_enabled; 00159 const Create_t m_create; 00160 const string m_typeDescr; 00161 const Values m_typeValues; 00162 }; 00163 00164 typedef list<const RegisterSyncSource *> SourceRegistry; 00165 00166 00167 #ifdef ENABLE_INTEGRATION_TESTS 00168 #include <ClientTest.h> 00169 typedef ClientTest::Config ClientTestConfig; 00170 #else 00171 /** 00172 * this class doesn't exist and cannot be referenced in code which is 00173 * compiled without ENABLE_INTEGRATION_TEST, but we only need to 00174 * declare a reference to it, so that's okay 00175 */ 00176 class ClientTestConfig; 00177 class ClientTest; 00178 #endif 00179 00180 /** 00181 * In addition to registering the sync source itself by creating an 00182 * instance of RegisterSyncSource, configurations for testing it can 00183 * also be registered. A sync source which supports more than one data 00184 * exchange format can register one configuration for each format, but 00185 * not registering any configuration is also okay. 00186 * 00187 * This code depends on the C++ client library test framework and 00188 * therefore CPPUnit. To avoid a hard dependency on that in the normal 00189 * "syncevolution" binary, the actual usage of the test Config class 00190 * is limited to the *Register.cpp files when compiling them for 00191 * inclusion in the "client-test" binary, i.e., they are protected by 00192 * #ifdef ENABLE_UNIT_TESTS. 00193 * 00194 * Sync sources have to work stand-alone without a full SyncClient 00195 * configuration for all local tests. The minimal configuration prepared 00196 * for the source includes: 00197 * - a tracking node (as used f.i. by TrackingSyncSource) which 00198 * points towards "~/.config/syncevolution/client-test-changes" 00199 * - a unique change ID (as used f.i. by EvolutionContactSource) 00200 * - a valid "evolutionsource" property in the config node, starting 00201 * with the CLIENT_TEST_EVOLUTION_PREFIX env variable or (if that 00202 * wasn't set) the "SyncEvolution_Test_" prefix 00203 * - "evolutionuser/password" if CLIENT_TEST_EVOLUTION_USER/PASSWORD 00204 * are set 00205 * 00206 * No other properties are set, which implies that currently sync sources 00207 * which require further parameters cannot be tested. 00208 * 00209 * @warning There is a potential problem with the registration 00210 * mechanism. Both the sync source tests as well as the CPPUnit tests 00211 * derived from them are registrered when global class instances are 00212 * initialized. If the RegisterTestEvolution instance in 00213 * client-test-app.cpp is initialized *before* the sync source tests, 00214 * then those won't show up in the test list. Currently the right 00215 * order seems to be used, so everything works as expected. 00216 */ 00217 class RegisterSyncSourceTest 00218 { 00219 public: 00220 /** 00221 * This call is invoked after setting up the config with default 00222 * values for the test cases selected via the constructor's 00223 * testCaseName parameter (one of vcard21, vcard30, ical20, itodo20; 00224 * see ClientTest in the Funambol client library for the current 00225 * list). 00226 * 00227 * This call can then override any of the values or (if there 00228 * are no predefined test cases) add them. 00229 * 00230 * The "type" property must select your sync source and the 00231 * data format for the test. 00232 * 00233 * @retval config change any field whose default is not suitable 00234 */ 00235 virtual void updateConfig(ClientTestConfig &config) const = 0; 00236 00237 /** 00238 * @param configName a unique string: the predefined names known by 00239 * ClientTest::getTestData() are already used for the initial 00240 * set of Evolution sync sources, for new sync sources 00241 * build a string by combining them with the sync source name 00242 * (e.g., "sqlite_vcard30") 00243 * @param testCaseName a string recognized by ClientTest::getTestData() or an 00244 * empty string if there are no predefined test cases 00245 */ 00246 RegisterSyncSourceTest(const string &configName, 00247 const string &testCaseName); 00248 virtual ~RegisterSyncSourceTest() {} 00249 00250 /** 00251 * Dump items in the native format, not the one currently selected 00252 * for exchange with the SyncML server. Useful for testing sync 00253 * sources which normally use one format internally, but also 00254 * support another one (EvolutionContactSource). 00255 */ 00256 static int dump(ClientTest &client, SyncSource &source, const char *file); 00257 00258 const string m_configName; 00259 const string m_testCaseName; 00260 }; 00261 00262 class TestRegistry : public vector<const RegisterSyncSourceTest *> 00263 { 00264 public: 00265 // TODO: using const RegisterSyncSourceTest * operator [] (int); 00266 const RegisterSyncSourceTest * operator [] (const string &configName) const { 00267 BOOST_FOREACH(const RegisterSyncSourceTest *test, *this) { 00268 if (test->m_configName == configName) { 00269 return test; 00270 } 00271 } 00272 throw out_of_range(string("test config registry: ") + configName); 00273 return NULL; 00274 } 00275 }; 00276 00277 00278 /** 00279 * SyncEvolution accesses all sources through this interface. This 00280 * class also implements common functionality for all SyncSources: 00281 * - handling of change IDs and URI 00282 * - finding the calender/contact backend (only for Evolution) 00283 * - default implementation of SyncSource interface 00284 * 00285 * The default interface assumes that the backend's 00286 * beginSyncThrow() finds all items as well as new/modified/deleted 00287 * ones and stores their UIDs in the respective lists. 00288 * Then the Items iterators just walk through these lists, 00289 * creating new items via createItem(). 00290 * 00291 * Error reporting is done via the Log class and this instance 00292 * then just tracks whether any error has occurred. If that is 00293 * the case, then the caller has to assume that syncing somehow 00294 * failed and a full sync is needed the next time. 00295 * 00296 * It also adds Evolution specific interfaces and utility functions. 00297 */ 00298 class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig 00299 { 00300 public: 00301 /** 00302 * Creates a new Evolution sync source. 00303 */ 00304 EvolutionSyncSource(const EvolutionSyncSourceParams ¶ms) : 00305 SyncSource(params.m_name.c_str(), NULL), 00306 EvolutionSyncSourceConfig(params.m_name, params.m_nodes), 00307 m_changeId( params.m_changeId ), 00308 m_allItems( *this, "existing", SYNC_STATE_NONE ), 00309 m_newItems( *this, "new", SYNC_STATE_NEW ), 00310 m_updatedItems( *this, "updated", SYNC_STATE_UPDATED ), 00311 m_deletedItems( *this, "deleted", SYNC_STATE_DELETED ), 00312 m_isModified( false ), 00313 m_modTimeStamp(0), 00314 m_hasFailed( false ) 00315 { 00316 setConfig(this); 00317 } 00318 virtual ~EvolutionSyncSource() {} 00319 00320 /** 00321 * SyncSource implementations must register themselves here via 00322 * RegisterSyncSource 00323 */ 00324 static SourceRegistry &getSourceRegistry(); 00325 00326 /** 00327 * SyncSource tests are registered here by the constructor of 00328 * RegisterSyncSourceTest 00329 */ 00330 static TestRegistry &getTestRegistry(); 00331 00332 struct Database { 00333 Database(const string &name, const string &uri, bool isDefault = false) : 00334 m_name( name ), m_uri( uri ), m_isDefault(isDefault) {} 00335 string m_name; 00336 string m_uri; 00337 bool m_isDefault; 00338 }; 00339 typedef vector<Database> Databases; 00340 00341 /** 00342 * returns a list of all know data sources for the kind of items 00343 * supported by this sync source 00344 */ 00345 virtual Databases getDatabases() = 0; 00346 00347 /** 00348 * Actually opens the data source specified in the constructor, 00349 * will throw the normal exceptions if that fails. Should 00350 * not modify the state of the sync source: that can be deferred 00351 * until the server is also ready and beginSync() is called. 00352 */ 00353 virtual void open() = 0; 00354 00355 /** 00356 * Extract information for the item identified by UID 00357 * and store it in a new SyncItem. The caller must 00358 * free that item. May throw exceptions. 00359 * 00360 * The information that has to be set in the new item is: 00361 * - content 00362 * - UID 00363 * - mime type 00364 * 00365 * @param uid identifies the item 00366 */ 00367 virtual SyncItem *createItem(const string &uid) = 0; 00368 00369 /** 00370 * closes the data source so that it can be reopened 00371 * 00372 * Just as open() it should not affect the state of 00373 * the database unless some previous action requires 00374 * it. 00375 */ 00376 virtual void close() = 0; 00377 00378 /** 00379 * Dump all data from source unmodified into the given stream. 00380 */ 00381 virtual void exportData(ostream &out) = 0; 00382 00383 /** 00384 * file suffix for database files 00385 */ 00386 virtual string fileSuffix() const = 0; 00387 00388 /** 00389 * Returns the preferred mime type of the items handled by the sync source. 00390 * Example: "text/x-vcard" 00391 */ 00392 virtual const char *getMimeType() const = 0; 00393 00394 /** 00395 * Returns the version of the mime type used by client. 00396 * Example: "2.1" 00397 */ 00398 virtual const char *getMimeVersion() const = 0; 00399 00400 /** 00401 * A string representing the source types (with versions) supported by the SyncSource. 00402 * The string must be formatted as a sequence of "type:version" separated by commas ','. 00403 * For example: "text/x-vcard:2.1,text/vcard:3.0". 00404 * The version can be left empty, for example: "text/x-s4j-sifc:". 00405 * Supported types will be sent as part of the DevInf. 00406 */ 00407 virtual const char* getSupportedTypes() const = 0; 00408 00409 /** 00410 * resets the lists of all/new/updated/deleted items 00411 */ 00412 void resetItems(); 00413 00414 /** 00415 * returns true iff some failure occured 00416 */ 00417 bool hasFailed() { return m_hasFailed; } 00418 void setFailed(bool failed) { m_hasFailed = failed; } 00419 00420 /** 00421 * Convenience function, to be called inside a catch() block of 00422 * the sync source. 00423 * Rethrows the exception to determine what it is, then logs it 00424 * as an error and sets the state of the sync source to failed. 00425 */ 00426 void handleException(); 00427 00428 /** 00429 * Ensures that the requested amount of time has passed since 00430 * the last modification of the local database. 00431 * 00432 * This time stamp is automatically updated by addItem(), 00433 * updateItem(), deleteItem(). A sync source which overrides 00434 * these virtual functions (shouldn't be necessary!) or 00435 * does other modifications has to call databaseModified() 00436 * explicitly after each modification. 00437 * 00438 * If the requested delay has already passed, this function 00439 * returns immediately. Therefore delays requested by more 00440 * than one active sync source don't add up. 00441 * 00442 * The main usage for this functionality is change tracking 00443 * via time stamps. In that case this function should be 00444 * called in close(). 00445 */ 00446 void sleepSinceModification(int seconds); 00447 00448 /** 00449 * Increments the time stamp of the latest database modification. 00450 * 00451 * To be called after modifying the local database and 00452 * before returning control to the caller. 00453 */ 00454 void databaseModified(); 00455 00456 /** 00457 * factory function for a EvolutionSyncSource that provides the 00458 * source type specified in the params.m_nodes.m_configNode 00459 * 00460 * @param error throw a runtime error describing what the problem is if no matching source is found 00461 * @return NULL if no source can handle the given type 00462 */ 00463 static EvolutionSyncSource *createSource(const EvolutionSyncSourceParams ¶ms, 00464 bool error = true); 00465 00466 /** 00467 * Factory function for a EvolutionSyncSource with the given name 00468 * and handling the kind of data specified by "type" (e.g. 00469 * "Evolution Contacts:text/x-vcard"). 00470 * 00471 * The source is instantiated with dummy configuration nodes under 00472 * the pseudo server name "testing". This function is used for 00473 * testing sync sources, not for real syncs. If the prefix is set, 00474 * then <prefix>_<name>_1 is used as database, just as in the 00475 * Client::Sync and Client::Source tests. Otherwise the default 00476 * database is used. 00477 * 00478 * @param error throw a runtime error describing what the problem is if no matching source is found 00479 * @return NULL if no source can handle the given type 00480 */ 00481 static EvolutionSyncSource *createTestingSource(const string &name, const string &type, bool error, 00482 const char *prefix = getenv("CLIENT_TEST_EVOLUTION_PREFIX")); 00483 00484 /** 00485 * @name default implementation of SyncSource iterators 00486 * 00487 * @todo getFirstItemKey() and getNextItemKey() are marked for removal 00488 * and will be replaced by removeAllItems(). Remove the calls when 00489 * they are no longer needed. In the meantime implement them with 00490 * m_allItems. 00491 */ 00492 /**@{*/ 00493 virtual SyncItem* getFirstItem() throw() { return m_allItems.start(); } 00494 virtual SyncItem* getNextItem() throw() { return m_allItems.iterate(); } 00495 virtual SyncItem* getFirstNewItem() throw() { return m_newItems.start(); } 00496 virtual SyncItem* getNextNewItem() throw() { return m_newItems.iterate(); } 00497 virtual SyncItem* getFirstUpdatedItem() throw() { return m_updatedItems.start(); } 00498 virtual SyncItem* getNextUpdatedItem() throw() { return m_updatedItems.iterate(); } 00499 virtual SyncItem* getFirstDeletedItem() throw() { return m_deletedItems.start(); } 00500 virtual SyncItem* getNextDeletedItem() throw() { return m_deletedItems.iterate(); } 00501 virtual SyncItem* getFirstItemKey() throw() { return m_allItems.start(); } 00502 virtual SyncItem* getNextItemKey() throw() { return m_allItems.iterate(); } 00503 /**@}*/ 00504 00505 /** 00506 * @name SyncSource methods that are provided by EvolutionSyncSource 00507 * and implemented via the corresponding *Throw() calls 00508 */ 00509 /**@{*/ 00510 virtual int beginSync() throw(); 00511 virtual int endSync() throw(); 00512 virtual void setItemStatus(const char *key, int status) throw(); 00513 virtual int addItem(SyncItem& item) throw(); 00514 virtual int updateItem(SyncItem& item) throw(); 00515 virtual int deleteItem(SyncItem& item) throw(); 00516 /**@}*/ 00517 00518 /** 00519 * The client library invokes this call to delete all local 00520 * items. SyncSources derived from EvolutionSyncSource should 00521 * take care of that when beginSyncThrow() is called with 00522 * deleteLocal == true and thus do not need to implement 00523 * this method. If a derived source doesn't do that, then the 00524 * implementation of this call will simply iterate over all 00525 * stored LUIDs and remove them. 00526 * 00527 * @return 0 for success, non-zero for failure 00528 */ 00529 virtual int removeAllItems() throw(); 00530 00531 /** 00532 * Disambiguate getName(): we have inherited it from both SyncSource and 00533 * AbstractSyncSourceConfig. Both must return the same string. 00534 */ 00535 const char *getName() throw() { return SyncSource::getName(); } 00536 00537 /** 00538 * source specific part of beginSync() - throws exceptions in case of error 00539 * 00540 * @param needAll fill m_allItems 00541 * @param needPartial fill m_new/deleted/modifiedItems 00542 * @param deleteLocal erase all items 00543 */ 00544 virtual void beginSyncThrow(bool needAll, 00545 bool needPartial, 00546 bool deleteLocal) = 0; 00547 00548 /** 00549 * @name source specific part of endSync/setItemStatus/addItem/updateItem/deleteItem: 00550 * throw exception in case of error 00551 */ 00552 /**@{*/ 00553 virtual void endSyncThrow() = 0; 00554 virtual void setItemStatusThrow(const char *key, int status); 00555 virtual int addItemThrow(SyncItem& item) = 0; 00556 virtual int updateItemThrow(SyncItem& item) = 0; 00557 virtual int deleteItemThrow(SyncItem& item) = 0; 00558 /**@}*/ 00559 00560 /** 00561 * @name log a one-line info about an item 00562 * 00563 * The first two have to provided by derived classes because only 00564 * they know how to present the item to the user. When being passed 00565 * a SyncItem note that it may or may not contain data. 00566 * 00567 * The third version is an utility function which is provided 00568 * for derived classes. It does the right thing for vCard, vCalendar 00569 * and plain text (in a crude way, without really parsing them), 00570 * but needs access to the item data. 00571 */ 00572 /**@{*/ 00573 virtual void logItem(const string &uid, const string &info, bool debug = false) = 0; 00574 virtual void logItem(const SyncItem &item, const string &info, bool debug = false) = 0; 00575 virtual void logItemUtil(const string data, const string &mimeType, const string &mimeVersion, 00576 const string &uid, const string &info, bool debug = false); 00577 /**@}*/ 00578 00579 protected: 00580 #ifdef HAVE_EDS 00581 /** 00582 * searches the list for a source with the given uri or name 00583 * 00584 * @param list a list previously obtained from Gnome 00585 * @param id a string identifying the data source: either its name or uri 00586 * @return pointer to source or NULL if not found 00587 */ 00588 ESource *findSource( ESourceList *list, const string &id ); 00589 #endif 00590 00591 #ifdef HAVE_EDS 00592 /** 00593 * throw an exception after an operation failed and 00594 * remember that this instance has failed 00595 * 00596 * output format: <source name>: <action>: <error string> 00597 * 00598 * @param action a string describing the operation or object involved 00599 * @param gerror if not NULL: a more detailed description of the failure, 00600 * will be freed 00601 */ 00602 void throwError(const string &action, 00603 GError *gerror); 00604 #endif 00605 00606 /** 00607 * throw an exception after an operation failed and 00608 * remember that this instance has failed 00609 * 00610 * output format: <source name>: <action>: <error string> 00611 * 00612 * @param action a string describing the operation or object involved 00613 * @param error the errno error code for the failure 00614 */ 00615 void throwError(const string &action, int error); 00616 00617 /** 00618 * throw an exception after an operation failed and 00619 * remember that this instance has failed 00620 * 00621 * output format: <source name>: <failure> 00622 * 00623 * @param action a string describing what was attempted *and* how it failed 00624 */ 00625 void throwError(const string &failure); 00626 00627 const string m_changeId; 00628 00629 class Items : public set<string> { 00630 const_iterator m_it; 00631 EvolutionSyncSource &m_source; 00632 const string m_type; 00633 const SyncState m_state; 00634 00635 public: 00636 Items( EvolutionSyncSource &source, const string &type, SyncState state ) : 00637 m_source( source ), 00638 m_type( type ), 00639 m_state( state ) 00640 {} 00641 00642 /** 00643 * start iterating, return first item if available 00644 * 00645 * Lists items in increasing lexical order. This is not required by 00646 * the SyncML standard, but it makes debugging easier. The 00647 * EvolutionCalendarSource relies on it: its uids are shorter 00648 * for parent items and thus they appear in the list before 00649 * their children. 00650 */ 00651 SyncItem *start(); 00652 00653 /** return current item if available, step to next one */ 00654 SyncItem *iterate(); 00655 00656 /** 00657 * add to list, with logging 00658 * 00659 * @return true if the item had not been added before 00660 */ 00661 bool addItem(const string &uid); 00662 }; 00663 00664 /** UIDs of all/all new/all updated/all deleted items */ 00665 Items m_allItems, 00666 m_newItems, 00667 m_updatedItems, 00668 m_deletedItems; 00669 00670 /** 00671 * remembers whether items have been modified during the sync: 00672 * if it is, then the destructor has to advance the change marker 00673 * or these modifications will be picked up during the next 00674 * two-way sync 00675 */ 00676 bool m_isModified; 00677 00678 private: 00679 /** 00680 * private wrapper function for add/delete/updateItemThrow() 00681 */ 00682 int processItem(const char *action, 00683 int (EvolutionSyncSource::*func)(SyncItem& item), 00684 SyncItem& item, 00685 bool needData) throw(); 00686 00687 /** time stamp of latest database modification, for sleepSinceModification() */ 00688 time_t m_modTimeStamp; 00689 00690 /** keeps track of failure state */ 00691 bool m_hasFailed; 00692 }; 00693 00694 #endif // INCL_EVOLUTIONSYNCSOURCE