Skip to content
This repository was archived by the owner on Mar 4, 2023. It is now read-only.

Commit e3c3dd5

Browse files
committed
added eventcursor documentation
1 parent 3b97a6d commit e3c3dd5

File tree

6 files changed

+460
-94
lines changed

6 files changed

+460
-94
lines changed

doc/datastore.dox

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ notify you in case a dataset has been changed.
1212
caller of those methods are responsible for deleting the objects after the operations have been
1313
completed. This of course only applies to pointer classes, as gadgets are used as value types.
1414

15-
@sa DataTypeStore, CachingDataTypeStore, DataStoreModel
15+
@sa DataTypeStore, CachingDataTypeStore, DataStoreModel, EventCursor
1616
*/
1717

1818
/*!

doc/eventcursor.dox

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
/*!
2+
@class QtDataSync::EventCursor
3+
4+
The EventCursor class provides a simple interface to walk through all the changes that have been
5+
done on the internal data set. Unlike the DataStore, which presents the actual data but does give
6+
no guarantees on completeness of change events, this class can be used to deterministically
7+
handle all changes in chronological order.
8+
9+
@note By default, a datasync instance does not create an eventlog. Enable it via the
10+
Setup::eventLoggingMode property
11+
12+
@attention This class does **not** hold any data itself, only what was changed, when it happend
13+
and whether it was changed or deleted. This means if the same dataset is changed multiple times
14+
in a row, you will get as many change events as it was changed, but you can only ever read the
15+
most recent dataset from the current datastore.
16+
17+
@sa DataStore, Setup::eventLoggingMode, EventCursor::skipObsolete
18+
*/
19+
20+
/*!
21+
@property QtDataSync::EventCursor::valid
22+
23+
@default{`false`}
24+
25+
This can be used to check if an eventcursor returned from one of the static functions is actually
26+
valid.
27+
28+
@note A once valid eventcursor will only ever advance forward to another valid position and thus
29+
cannot become invalid
30+
31+
@accessors{
32+
@readAc{isValid()}
33+
@constantAc
34+
}
35+
36+
@sa EventCursor::first, EventCursor::last, EventCursor::create, EventCursor::load
37+
*/
38+
39+
/*!
40+
@property QtDataSync::EventCursor::setupName
41+
42+
@default{`QtDataSync::DefaultSetup`}
43+
44+
The setup name is the name that was passed to the Setup::create method to create the datasync
45+
instance this cursor is refering to.
46+
47+
@accessors{
48+
@readAc{setupName()}
49+
@constantAc
50+
}
51+
52+
@sa QtDataSync::DefaultSetup, Setup::create
53+
*/
54+
55+
/*!
56+
@property QtDataSync::EventCursor::index
57+
58+
@default{`0`}
59+
60+
This index is unqiue and can uniquely identify an event. They are automatically generate and
61+
are strictly ascending, meaning that newer events will always have a higher index compared to an
62+
older event.
63+
64+
@accessors{
65+
@readAc{index()}
66+
@notifyAc{indexChanged()}
67+
}
68+
69+
@sa EventCursor::create, EventCursor::key
70+
*/
71+
72+
/*!
73+
@property QtDataSync::EventCursor::key
74+
75+
@default{<i>empty</i>}
76+
77+
This key contains both, the name of the class and the id of the dataset that was changed.
78+
79+
@accessors{
80+
@readAc{key()}
81+
@notifyAc{keyChanged()}
82+
}
83+
84+
@sa QtDataSync::ObjectKey, EventCursor::wasRemoved
85+
*/
86+
87+
/*!
88+
@property QtDataSync::EventCursor::wasRemoved
89+
90+
@default{`false`}
91+
92+
If a change event created a new dataset or modified an existing one, than this property is set to
93+
false. If an existing dataset was deleted it is set to true.
94+
95+
@accessors{
96+
@readAc{wasRemoved()}
97+
@notifyAc{wasRemovedChanged()}
98+
}
99+
100+
@sa EventCursor::key
101+
*/
102+
103+
/*!
104+
@property QtDataSync::EventCursor::timestamp
105+
106+
@default{<i>invalid</i>}
107+
108+
Timestamps are generated internally based on the current local time and then converted to UTC
109+
the moment a dataset was changed. This property loads the UTC variant and converts it back to the
110+
current local time, which means this property **always** returns the time converter to the
111+
current local time. If you need UTC timestamps, convert it back. The timestamp contains the date
112+
and time with milliseconds precision.
113+
114+
@accessors{
115+
@readAc{timestamp()}
116+
@notifyAc{timestampChanged()}
117+
}
118+
119+
@sa EventCursor::key, EventCursor::index
120+
*/
121+
122+
/*!
123+
@property QtDataSync::EventCursor::skipObsolete
124+
125+
@default{`true`}
126+
127+
If skipping obsolete entries is enabled, the cursor will automatically skip multiple change
128+
events on the same dataset and only consider the most recent ones. If set to false, all entries
129+
are used instead.
130+
131+
A simple example. Consider the following chain of events:
132+
@code
133+
001 [MyType:Id1] change <- cursor positioned here
134+
002 [MyType:Id2] change
135+
003 [MyType:Id1] delete
136+
004 [MyType:Id3] delete
137+
005 [MyType:Id1] change
138+
@endcode
139+
140+
If this property is set to true, calling next() will move it to `002`. Calling next again will
141+
make it skip `003` and move to `004` instead, because there is a newer change event for the same
142+
dataset (`005`). Calling next one more time then moves to `005`. If this property had been
143+
disabled, entry `003` would not have been skipped, event though the change that was done has
144+
already been succeeded by a newer one.
145+
146+
@note This property *only** affects the next(), hasNext() and autoScanLog() methods. It is
147+
still possible to create a cursor on an obsolete event via create()
148+
149+
@accessors{
150+
@readAc{skipObsolete()}
151+
@writeAc{setSkipObsolete()}
152+
@notifyAc{skipObsoleteChanged()}
153+
}
154+
155+
@sa EventCursor::next, EventCursor::hasNext, EventCursor::autoScanLog, EventCursor::create,
156+
EventCursor::index
157+
*/
158+
159+
/*!
160+
@fn QtDataSync::EventCursor::isEventLogActive
161+
162+
@param setupName The name of the setup to check for an active log
163+
164+
Eventlogging must be explicitly enabled when creating a setup. In case you do not know at the
165+
point of using the cursor whether the log is actually available, you can use this method to
166+
check
167+
168+
@attention In case the log is not enabled, all creation methods to obtain a cursor will fail and
169+
instead return invalid cursors
170+
171+
@sa Setup::eventLoggingMode, EventCursor::valid
172+
*/
173+
174+
/*!
175+
@fn QtDataSync::EventCursor::first(QObject*)
176+
177+
@param parent The parent object to set as parent of the event cursor
178+
@returns A valid eventcursor, positioned on the oldest available change, or an invalid cursor
179+
if no changes exist
180+
@throws EventCursorException Thrown if access to the underlying database failed
181+
182+
If no setup name is specified, the cursor is created for the default setup name
183+
184+
@sa EventCursor::last, EventCursor::create, EventCursor::load, EventCursor::valid,
185+
EventCursor::isEventLogActive
186+
*/
187+
188+
/*!
189+
@fn QtDataSync::EventCursor::first(const QString &, QObject*)
190+
@param setupName The name of the setup to create the cursor for
191+
@copydetails EventCursor::first(QObject*)
192+
*/
193+
194+
/*!
195+
@fn QtDataSync::EventCursor::last(QObject*)
196+
197+
@param parent The parent object to set as parent of the event cursor
198+
@returns A valid eventcursor, positioned on the newest available change, or an invalid cursor
199+
if no changes exist
200+
@throws EventCursorException Thrown if access to the underlying database failed
201+
202+
If no setup name is specified, the cursor is created for the default setup name
203+
204+
@sa EventCursor::first, EventCursor::create, EventCursor::load, EventCursor::valid,
205+
EventCursor::isEventLogActive
206+
*/
207+
208+
/*!
209+
@fn QtDataSync::EventCursor::last(const QString &, QObject*)
210+
@param setupName The name of the setup to create the cursor for
211+
@copydetails EventCursor::last(QObject*)
212+
*/
213+
214+
/*!
215+
@fn QtDataSync::EventCursor::create(quint64, QObject*)
216+
217+
@param index The index of the change event to position the cursor on
218+
@param parent The parent object to set as parent of the event cursor
219+
@returns A valid eventcursor, positioned on the given index, or an invalid cursor
220+
if no changes exist for that index
221+
@throws EventCursorException Thrown if access to the underlying database failed
222+
223+
If no setup name is specified, the cursor is created for the default setup name
224+
225+
@sa EventCursor::first, EventCursor::last, EventCursor::load, EventCursor::valid,
226+
EventCursor::isEventLogActive
227+
*/
228+
229+
/*!
230+
@fn QtDataSync::EventCursor::create(quint64, const QString &, QObject*)
231+
@param setupName The name of the setup to create the cursor for
232+
@copydetails EventCursor::create(quint64, QObject*)
233+
*/
234+
235+
/*!
236+
@fn QtDataSync::EventCursor::load(const QByteArray &, QObject*)
237+
238+
@param data The data to create the cursor from
239+
@param parent The parent object to set as parent of the event cursor
240+
@returns A valid eventcursor, positioned on the index part of the data, or an invalid cursor
241+
if no changes exist for that index
242+
@throws EventCursorException Thrown if access to the underlying database failed
243+
244+
If no setup name is specified, the cursor is created for the default setup name. The following
245+
properties are restored from the data:
246+
247+
- EventCursor::index
248+
- EventCursor::skipObsolete
249+
250+
Use save() to save the data of an existing cursor so you can later load it again using this
251+
method.
252+
253+
@note The index is only set in case the returned cursor is valid. For an invalid cursor, only the
254+
skipObsolete property will be set.
255+
256+
@sa EventCursor::first, EventCursor::last, EventCursor::create, EventCursor::valid,
257+
EventCursor::isEventLogActive, EventCursor::save, EventCursor::skipObsolete
258+
*/
259+
260+
/*!
261+
@fn QtDataSync::EventCursor::load(const QByteArray &, const QString &, QObject*)
262+
@param setupName The name of the setup to create the cursor for
263+
@copydetails EventCursor::load(const QByteArray &, QObject*)
264+
*/
265+
266+
/*!
267+
@fn QtDataSync::EventCursor::save
268+
269+
@returns Encoded data of the current cursor that can be used to recreate it.
270+
271+
The following properties are encoded into the data:
272+
273+
- EventCursor::index
274+
- EventCursor::skipObsolete
275+
276+
@sa EventCursor::load
277+
*/
278+
279+
/*!
280+
@fn QtDataSync::EventCursor::hasNext
281+
282+
@returns True if there is at least one newer change event currently available, false if not
283+
@throws EventCursorException Thrown if access to the underlying database failed
284+
285+
This method does not change the position or general state of the current cursor. This method
286+
honors the value of skipObsolete
287+
288+
@sa EventCursor::next, EventCursor::valid, EventCursor::skipObsolete
289+
*/
290+
291+
/*!
292+
@fn QtDataSync::EventCursor::next
293+
294+
@returns True if the cursor was able to advance to a new change event, false if not
295+
@throws EventCursorException Thrown if access to the underlying database failed
296+
297+
In case there was a new change event, after calling this method the cursor is now positioned on
298+
that newer record and in case it was previously valid now still is valid and true is returned. If
299+
however there was no new change event to advance to, the cursor stayes **unchanged** and false is
300+
returned. This means the cursor is **not** set to be invalid if this method fails, only the
301+
return value or the index can be used to check if the next operation actually did anything.
302+
303+
This method honors the value of skipObsolete
304+
305+
@sa EventCursor::hasNext, EventCursor::autoScanLog, EventCursor::skipObsolete
306+
*/
307+
308+
/*!
309+
@fn QtDataSync::EventCursor::autoScanLog()
310+
311+
@throws EventCursorException Thrown if access to the underlying database failed
312+
313+
This method basically just calles next() in a loop to walk through all existing change events
314+
until it reaches the current one. After that happend, the cursor will now react on changes to
315+
the events in the database and automatically advance forward as soon as a new event was logged
316+
there.
317+
318+
This method honors the value of skipObsolete
319+
320+
@sa EventCursor::hasNext, EventCursor::next, EventCursor::skipObsolete, EventCursor::indexChanged
321+
*/
322+
323+
/*!
324+
@fn QtDataSync::EventCursor::autoScanLog(std::function<bool(const EventCursor *)>, bool)
325+
326+
@param function The callback to be called for each event visited
327+
@param scanCurrent Specify if the event currently pointed should be passed to the function before
328+
advancing to the next one
329+
@throws EventCursorException Thrown if access to the underlying database failed
330+
331+
This method basically just calles next() in a loop to walk through all existing change events
332+
until it reaches the current one. After that happend, the cursor will now react on changes to
333+
the events in the database and automatically advance forward as soon as a new event was logged
334+
there.
335+
336+
For every event visited that way, the function callback is called once with this cursor passed
337+
to it. The method can return true to continue the loop or false to end it.
338+
339+
This method honors the value of skipObsolete
340+
341+
@sa EventCursor::hasNext, EventCursor::next, EventCursor::skipObsolete, EventCursor::indexChanged
342+
*/
343+
344+
/*!
345+
@fn QtDataSync::EventCursor::autoScanLog(QObject *, std::function<bool(const EventCursor *)>, bool)
346+
@param scope The object scope to limit the callback to. Only call as long as the scope still exists
347+
@copydetails QtDataSync::EventCursor::autoScanLog(std::function<bool(const EventCursor *)>, bool)
348+
*/
349+
350+
/*!
351+
@fn QtDataSync::EventCursor::clearEventLog
352+
353+
@param offset The number of events to keep before the current one
354+
@throws EventCursorException Thrown if access to the underlying database failed
355+
356+
When called, all events that are older than the one currently pointed to are deleted. You can
357+
additionally keep entries by specifing an offset. If the offset is for example 5, there will be
358+
5 entries left that are older than the current one after the cleanup.
359+
360+
@note This method does **not** the value of skipObsolete
361+
362+
@sa EventCursor::index
363+
*/
364+
365+
/*!
366+
@fn QtDataSync::EventCursor::eventLogChanged
367+
368+
This signal does **not** mean that the event the current cursor is pointing to has changed. It
369+
only notifies you that there are new events that have been added to the underlying event log.
370+
This signal is used by autoScanLog() to automatically advance through new events.
371+
372+
@sa EventCursor::autoScanLog, EventCursor::indexChanged
373+
*/

0 commit comments

Comments
 (0)