Imported Upstream version 1.0beta1
[platform/upstream/syncevolution.git] / src / synthesis / src / sysync / stdlogicds.h
1 /**
2  *  @File     stdlogicds.h
3  *
4  *  @Author   Lukas Zeller (luz@synthesis.ch)
5  *
6  *  @brief TStdLogicDS
7  *    Standard database logic implementation, suitable for most (currently all)
8  *    actual DS implementations, but takes as few assumptions about datastore
9  *    so for vastly different sync patterns, this could be replaced by differnt locic
10  *
11  *    Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
12  *
13  *  @Date 2005-09-15 : luz : created from custdbdatastore
14  */
15 /*
16  */
17
18 #ifndef TStdLogicDS_H
19 #define TStdLogicDS_H
20
21 // includes
22 #include "sysync.h"
23 #include "syncappbase.h"
24 #include "localengineds.h"
25
26 #ifdef MULTI_THREAD_DATASTORE
27 #include "platform_thread.h"
28 #endif
29
30 #if defined(CLIENT_USES_SERVER_DB)
31         #define USES_SERVER_DB 1
32         #define HAS_SERVER_DB 1
33 #else
34         #ifdef SERVER_SUPPORT
35         #define USES_SERVER_DB 1
36   #endif
37         #define HAS_SERVER_DB IS_SERVER
38 #endif
39
40 using namespace sysync;
41
42 namespace sysync {
43
44 // container for TSyncItem pointers
45 typedef std::list<sysync::TSyncItem *> TSyncItemPContainer; // contains data items
46
47
48 /// @brief standard logic datastore
49 /// - only called directly by TLocalEngineDS via logicXXXX virtuals.
50 /// - to perform actual access to implementation, this class calls its (mostly abstract)
51 ///   implXXXX virtuals.
52 class TStdLogicDS: public TLocalEngineDS
53 {
54   typedef TLocalEngineDS inherited;
55 private:
56   bool fWriteStarted; ///< set if write has started
57   #ifdef SYSYNC_CLIENT
58   bool fEoC; ///< end of changes
59   #if defined(CLIENT_USES_SERVER_DB) && !defined(SYSYNC_SERVER)
60   TSyncItemPContainer fItems; ///< list of data items, used to simulate maps in server DB
61   #endif
62   #endif
63   #ifdef SYSYNC_SERVER
64   TSyncItemPContainer fItems; ///< list of data items
65   uInt32 fNumRefOnlyItems;
66   #endif
67   // startSync/threading privates
68   bool fInitializing;
69   bool fStartInit;
70   bool fMultiThread; // copied flag from sessionConfig
71
72 protected:
73
74   /// @name dsSavedAdmin administrative data (anchors, timestamps, maps) as saved or to-be-saved
75   /// @Note These will be loaded and saved be derived classes
76   /// @Note Some of these will be updated from resp. @ref dsCurrentAdmin members at distinct events (suspend, session end, etc.)
77   /// @Note Some of these will be updated during the session, but in a way that does NOT affect the anchoring of current/last session
78   //
79   /// @{
80   // - TStdLogicDS is timestamp-based, so we save timestamps of the previous session
81   lineartime_t fPreviousSyncTime;   ///< time of previous sync (used to generate local anchor string representing previous sync)
82   /// @}
83
84   /// @name dsCurrentAdmin current session's admin data (anchors, timestamps, maps)
85   /// @Note These will be copied to @ref dsSavedAdmin members ONLY when a session completes successfully/suspends.
86   /// @Note Admin data is NEVER directly saved or loaded from these
87   /// @Note Derivates will update some of these at dssta_adminready with current time/anchor values
88   //
89   /// @{
90   // - TStdLogicDS is timestamp-based, so we get timestamp to anchor this session
91   lineartime_t fCurrentSyncTime;    ///< anchoring timestamp of this, currently running sync.
92   /// @}
93
94
95 private:
96   /// internally reset for re-use without re-creation
97   void InternalResetDataStore(void);
98 public:
99   /// constructor
100   TStdLogicDS(
101     TLocalDSConfig *aDSConfigP,
102     sysync::TSyncSession *aSessionP,
103     const char *aName,
104     long aCommonSyncCapMask=0);
105   virtual ~TStdLogicDS();
106
107 public:
108   /// @name dsProperty property and state querying methods
109   /// @{
110   /// check is datastore is completely started.
111   /// @param[in] aWait if set, call will not return until either started state is reached
112   ///   or cannot be reached within the maximally allowed request processing time left.
113   virtual bool isStarted(bool aWait);
114   /// @}
115
116
117 protected:
118   /// @name dsXXXX (usually abstract) virtuals defining the interface to derived datastore classes (implementation, api)
119   ///   These are usually designed such that they should always call inherited::dsXXX to let the entire chain
120   ///   of ancestors see the calls
121   /// @{
122   //
123   /// reset datastore to a re-usable, like new-created state.
124   virtual void dsResetDataStore(void) { InternalResetDataStore(); inherited::dsResetDataStore(); };
125   /// abort datastore (no reset yet, everything is just frozen as it is)
126   virtual void dsAbortDatastoreSync(TSyError aStatusCode, bool aLocalProblem);
127   /// inform logic of coming state change
128   virtual localstatus dsBeforeStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
129   /// inform logic of happened state change
130   virtual localstatus dsAfterStateChange(TLocalEngineDSState aOldState,TLocalEngineDSState aNewState);
131   #ifdef SYSYNC_SERVER
132   // - called when a item in the sync set changes its localID (due to local DB internals)
133   //   Datastore must make sure that possibly cached items get updated
134   virtual void dsLocalIdHasChanged(const char *aOldID, const char *aNewID);
135   #endif
136   /// @}
137
138   /// @name logicXXXX methods defining the interface to TLocalEngineDS.
139   ///   Only these will be called by TLocalEnginDS
140   /// @Note some of these are virtuals ONLY for being derived by superdatastore, NEVER by locic or other derivates
141   ///   We use the SUPERDS_VIRTUAL macro for these, which is empty in case we don't have superdatastores, then
142   ///   these can be non-virtual.
143   /// @{
144   //
145   /// called to make admin data ready
146   /// - might be called several times (auth retries at beginning of session)
147   virtual localstatus logicMakeAdminReady(cAppCharP aDataStoreURI, cAppCharP aRemoteDBID);
148   /// called to have all non-yet-generated sync commands as "to-be-resumed"
149   virtual void logicMarkOnlyUngeneratedForResume(void);
150   /// called to mark an already generated (but probably not sent or not yet statused) item
151   /// as "to-be-resumed", by localID or remoteID (latter only in server case).
152   /// @note This must be repeatable without side effects, as server must mark/save suspend state
153   ///       after every request (and not just at end of session)
154   virtual void logicMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteID, bool aUnSent);
155   /// called to mark an already sent item as "to-be-resent", e.g. due to temporary
156   /// error status conditions, by localID or remoteID (latter only in server case).
157   virtual void logicMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteID);
158   /// save status information required to possibly perform a resume (as passed to datastore with
159   /// markOnlyUngeneratedForResume(), markItemForResume() and markItemForResend())
160   /// (or, in case the session is really complete, make sure that no resume state is left)
161   /// @note Must also save tempGUIDs (for server) and pending/unconfirmed maps (for client)
162   virtual localstatus logicSaveResumeMarks(void);
163
164   /// called to process incoming item operation
165   /// @note Method must take ownership of syncitemP in all cases
166   virtual bool logicProcessRemoteItem(
167     TSyncItem *syncitemP,
168     TStatusCommand &aStatusCommand,
169     bool &aVisibleInSyncset, ///< on entry: tells if resulting item SHOULD be visible; on exit: set if processed item remains visible in the sync set.
170     string *aGUID=NULL ///< GUID is stored here if not NULL
171   );
172   /// called to read a specified item from the server DB (not restricted to set of conflicting items)
173   virtual bool logicRetrieveItemByID(
174     TSyncItem &aSyncItem, ///< item to be filled with data from server. Local or Remote ID must already be set
175     TStatusCommand &aStatusCommand ///< status, must be set on error or non-200-status
176   );
177
178   /// @}
179
180
181
182   /// @name implXXXX methods defining the interface to TStdLogicDS.
183   ///   Only these will be called by TLocalEngineDS
184   /// @Note some of these are virtuals ONLY for being derived by superdatastore, NEVER by locic or other derivates
185   ///   We use the SUPERDS_VIRTUAL macro for these, which is empty in case we don't have superdatastores, then
186   ///   these can be non-virtual.
187   /// @{
188   //
189   /// save status information required to possibly perform a resume (as passed to datastore with
190   /// markOnlyUngeneratedForResume() and markItemForResume())
191   /// (or, in case the session is really complete, make sure that no resume state is left)
192   /// @note Must also save tempGUIDs (for server) and pending/unconfirmed maps (for client)
193   virtual localstatus implSaveResumeMarks(void) = 0;
194   // - called to have all non-yet-generated sync commands as "to-be-resumed"
195   virtual void implMarkOnlyUngeneratedForResume(void) = 0;
196   /// called to mark an already generated (but probably not sent or not yet statused) item
197   /// as "to-be-resumed", by localID or remoteID (latter only in server case).
198   /// @note This must be repeatable without side effects, as server must mark/save suspend state
199   ///       after every request (and not just at end of session)
200   virtual void implMarkItemForResume(cAppCharP aLocalID, cAppCharP aRemoteID, bool aUnSent) = 0;
201   /// called to mark an already sent item as "to-be-resent", e.g. due to temporary
202   /// error status conditions, by localID or remoteID (latter only in server case).
203   virtual void implMarkItemForResend(cAppCharP aLocalID, cAppCharP aRemoteID) = 0;
204   /// sync login (into this database)
205   /// @note might be called several times (auth retries at beginning of session)
206   /// @note must update the following state variables
207   /// - in TLocalEngineDS: fLastRemoteAnchor, fLastLocalAnchor, fResumeAlertCode, fFirstTimeSync
208   ///   - for client: fPendingAddMaps
209   ///   - for server: fTempGUIDMap
210   /// - in TStdLogicDS: fPreviousSyncTime, fCurrentSyncTime
211   /// - in derived classes: whatever else belongs to dsSavedAdmin and dsCurrentAdmin state
212   virtual localstatus implMakeAdminReady(
213     const char *aDeviceID,    ///< @param[in] remote device URI (device ID)
214     const char *aDatabaseID,  ///< @param[in] database ID
215     const char *aRemoteDBID   ///< @param[in] database ID of remote device
216   ) = 0;
217   /// start data read
218   /// @note: fSlowSync and fRefreshOnly must be valid before calling this method
219   virtual localstatus implStartDataRead() = 0;
220   /// get item from DB
221   virtual localstatus implGetItem(
222     bool &aEof, ///< set if no more items
223     bool &aChanged, ///< if set on entry, only changed items will be reported, otherwise all will be returned and aChanged denotes if items has changed or not
224     TSyncItem* &aSyncItemP ///< will receive the item
225   ) = 0;
226   /// end of read
227   virtual localstatus implEndDataRead(void) = 0;
228   /// start of write
229   virtual localstatus implStartDataWrite(void) = 0;
230   /// Returns true when DB can track syncop changes (i.e. having the DB report
231   /// items as added again when stdlogic filters have decided they fell out of the syncset,
232   /// and has announced this to the DB using implReviewReadItem(). 
233   virtual bool implTracksSyncopChanges(void) { return false; }; // derived DB class needs to confirm true if   
234         /// review reported entry (allows post-processing such as map deleting)
235         /// MUST be called after implStartDataWrite, before any actual writing,
236         /// for each item obtained in implGetItem
237         virtual localstatus implReviewReadItem(
238           TSyncItem &aItem         ///< the item
239         ) = 0;
240         #ifdef SYSYNC_SERVER
241   /// called to set maps.
242   /// @note aLocalID or aRemoteID can be NULL - which signifies deletion of a map entry
243   /// @note that this might be needed for clients accessing a server-style database as well
244   virtual localstatus implProcessMap(cAppCharP aRemoteID, cAppCharP aLocalID) = 0;
245   #endif
246   /// called to read a specified item from the server DB (not restricted to set of conflicting items)
247   virtual bool implRetrieveItemByID(
248     TSyncItem &aSyncItem, ///< item to be filled with data from server. Local or Remote ID must already be set
249     TStatusCommand &aStatusCommand ///< status, must be set on error or non-200-status
250   ) = 0;
251   /// process item (according to operation: add/delete/replace/map)
252   virtual bool implProcessItem(
253     TSyncItem *aItemP,         ///< the item
254     TStatusCommand &aStatusCommand
255   ) = 0;
256   /// save end of session state
257   virtual localstatus implSaveEndOfSession(bool aUpdateAnchors) = 0;
258   /// end write sequence
259   virtual bool implEndDataWrite(void) = 0;
260   /// @}
261
262
263 private:
264   /// @name dsHelpers
265   ///   internal, private helper methods
266
267   #ifdef SYSYNC_CLIENT
268   /// called by dsBeforeStateChange to dssta_dataaccessstarted to make sure datastore is ready for being accessed.
269   virtual localstatus startDataAccessForClient(void);
270   #endif
271   #ifdef SYSYNC_SERVER
272   /// called by dsBeforeStateChange to dssta_dataaccessstarted to make sure datastore is ready for being accessed.
273   virtual localstatus startDataAccessForServer(void);
274   #endif
275
276   /// @}
277
278
279
280   #ifdef SYSYNC_SERVER
281   // - called to check if conflicting replace or delete command from server exists
282   virtual TSyncItem *getConflictingItemByRemoteID(TSyncItem *syncitemP);
283   // - called to check if content-matching item from server exists
284   virtual TSyncItem *getMatchingItem(TSyncItem *syncitemP, TEqualityMode aEqMode);
285   // - called to prevent item to be sent to client in subsequent logicGenerateSyncCommandsAsServer()
286   //   item in question should be an item that was returned by getConflictingItemByRemoteID() or getMatchingItem()
287   virtual void dontSendItemAsServer(TSyncItem *syncitemP);
288   // - called to have additional item sent to remote (DB takes ownership of item)
289   virtual void SendItemAsServer(TSyncItem *aSyncitemP);
290   // - end map operation (rollback if not aDoCommit)
291   virtual bool MapFinishAsServer(
292     bool aDoCommit,                // if not set, entire map operation must be undone
293     TStatusCommand &aStatusCommand // status, must be set on error or non-200-status
294   );
295   /// called to generate sync sub-commands as client for remote server
296   /// @return true if now finished for this datastore
297   virtual bool logicGenerateSyncCommandsAsServer(
298     TSmlCommandPContainer &aNextMessageCommands,
299     TSmlCommand * &aInterruptedCommandP,
300     const char *aLocalIDPrefix
301   );
302   /// called for servers when receiving map from client
303   /// @note aLocalID or aRemoteID can be NULL - which signifies deletion of a map entry
304   virtual localstatus logicProcessMap(cAppCharP aLocalID, cAppCharP aRemoteID);
305   #endif // SYSYNC_SERVER
306   
307   #ifdef SYSYNC_CLIENT
308   /// called to generate sync sub-commands as server for remote client
309   /// @return true if now finished for this datastore
310   virtual bool logicGenerateSyncCommandsAsClient(
311     TSmlCommandPContainer &aNextMessageCommands,
312     TSmlCommand * &aInterruptedCommandP,
313     const char *aLocalIDPrefix
314   );
315   #endif // SYSYNC_CLIENT
316   
317   // - determine if this is a first time sync situation
318   virtual bool isFirstTimeSync(void) { return fFirstTimeSync; };
319
320 protected:
321   // - called for SyncML 1.1 if remote wants number of changes.
322   //   Must return -1 no NOC value can be returned
323   //   NOTE: we implement it here only for server, as it is not really needed
324   //   for clients normally - if it is needed, client's agent must provide
325   //   it as CustDBDatastore has no own list it can use to count in client case.
326   virtual sInt32 getNumberOfChanges(void);
327
328 public:
329   // Simple custom DB access interface methods
330   // - returns true if database implementation can only update all fields of a record at once
331   virtual bool dsReplaceWritesAllDBFields(void) { return false; } // we assume DB is smart enough
332   #ifdef OBJECT_FILTERING
333   // - returns true if DB implementation can filter during database fetch
334   //   (otherwise, fetched items must be filtered after being read from DB)
335   virtual bool dsFilteredFetchesFromDB(bool aFilterChanged=false) { return false; } // assume unfiltered data from DB
336   #endif
337
338 private:
339   /// internal stdlogic: start writing if not already started
340   localstatus startDataWrite(void);
341   /// internal stdlogic: end writing if not already ended
342   localstatus endDataWrite(void);
343 public:
344   // - must be called before starting a thread. If returns false, starting a thread now
345   //   is not allowed and must be postponed.
346   virtual bool startingThread(void) { return true; };
347   // - must be called when a thread's activity has ended
348   //   BUT THE CALL MUST BE FROM THE ENDING THREAD, not the main thread!
349   virtual void endingThread(void) {};
350   // - should be called before doing DB accesses that might be locked (e.g. because another thread is using the DB resources)
351   virtual bool dbAccessLocked(void) { return false; };
352   // - Actual start sync actions in DB. If server supports threaded init, this will
353   //   be called in a sub-thread's context
354   localstatus performStartSync(void);
355   #ifdef MULTI_THREAD_DATASTORE
356     TStatusCommand fStartSyncStatus; // a thread-private status command to store status ocurring during threaded startSync()
357   #endif
358 private:
359   // - can be called to check if performStartSync() should be terminated
360   bool shouldExitStartSync(void);
361   #ifdef MULTI_THREAD_DATASTORE
362   bool threadedStartSync(void);
363   TThreadObject fStartSyncThread; // the wrapper object for the startSync thread
364   #endif
365 }; // TStdLogicDS
366
367
368 } // namespace sysync
369
370 #endif  // TStdLogicDS_H
371
372 // eof