RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT > Class Template Reference

Template class for restoring an aggregate classe. More...

#include "rdm_time_series_restore_aggregate.h"

Inheritance diagram for RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >:
Inheritance graph
Collaboration diagram for RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >:
Collaboration graph

Public Member Functions

RDM_RETCODE init (RDM_DB db)
Initialize this object. More...
void reset (void)
Reset this object. More...
template<class SOURCE_VALUE_T >
RDM_RETCODE put_value (SOURCE_VALUE_T *source_value, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving a data value. More...
template<class SOURCE_STATS_T >
RDM_RETCODE put_stats (SOURCE_STATS_T *source_stats, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving statistics. More...
template<class SOURCE_RANGE_T >
RDM_RETCODE put_range (SOURCE_RANGE_T *source_range, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving ranges. More...
- Public Member Functions inherited from RDM::TIME_SERIES::custom< NEXT >
RDM_RETCODE init (RDM_DB db)
Initialize this object. More...
void reset (void)
Reset this object. More...
RDM_RETCODE flush_value (uint32_t threshold=1, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Flush this object. More...
RDM_RETCODE flush_stats (uint32_t threshold=1, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Flush this object. More...
RDM_RETCODE flush_range (uint32_t threshold=1, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Flush this object. More...
template<class SOURCE_VALUE_T >
RDM_RETCODE put_value (SOURCE_VALUE_T *source_value, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving a data value. More...
template<class SOURCE_STATS_T >
RDM_RETCODE put_stats (SOURCE_STATS_T *source_stats, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving statistics. More...
template<class SOURCE_RANGE_T >
RDM_RETCODE put_range (SOURCE_RANGE_T *source_range, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving ranges. More...

Additional Inherited Members

- Protected Member Functions inherited from RDM::TIME_SERIES::custom< NEXT >
uint32_t init_tables_to_write_lock (RDM_TABLE_ID *tables)
IDs of the tables where rows are inserted. More...
uint32_t init_tables_to_read_lock (RDM_TABLE_ID *tables)
IDs of the tables where rows are read. More...
void unput (void)
Undo a previous put operation. More...
void unflush (void)
Undo a previous flush operation. More...
- Static Protected Member Functions inherited from RDM::TIME_SERIES::custom< NEXT >
constexpr static int number_of_tables_to_write_lock (void)
Number of tables where rows are inserted. More...
constexpr static int number_of_tables_to_read_lock (void)
Number of tables where rows are read. More...

Detailed Description

template<class TIME_STAMP_KEY_T, RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT>
class RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >

Template class for restoring an aggregate classe.

This template class can be used to restore the state of an aggregate class.

Before we explain exactly how this class works, let's consider the following scenario:

split <insert_row <TABLE_SOURCE>
stats <32, AGGREGATE, insert_row <TABLE_AGGREGATE>>> ts;

When data is fed into the above class chain using ts.put_data(), the data will be inserted into the SOURCE table, and for every 32 rows inserted into the first table, a row with statistics will be inserted into the AGGREGATE table. However, if the program where this code is deployed is shut down and restarted, any rows left over in the aggregation (the stats class) after the last statistics has been inserted will not get counted towards any statistics.

Calling ts.flush_value() before shutdown can force statistics to be generated for the left over data. However, this is not always desireable or possible. For example, the RDM Fast Fourier Transform (FFT) APIs classes are not able to honor a flush. The same is the case for the downsample class.

This class can remedy this. It is able to feed the missing data into the aggregation class (stats) when started up. If set up correctly, it will look up the last row from the AGGREGATE table and feed all the rows from the SOURCE table that have a timestamp greater than the timestamps in the AGGREGATE table into the stats class.

For this to work correctly, the above class chain has to be arranged slightly differently. The order of the two classes in the split has to be reversed. This class can then be inserted between the split and the stats class as follows:

split <restore_aggregate<UINT64_t,
KEY_SOURCE_TIME_STAMP_CURRENT,
KEY_AGGREGATE_TIME_STAMP_LAST,
stats <32, AGGREGATE,
insert_row <TABLE_AGGREGATE>>>
insert_row <TABLE_SOURCE>> ts;

This class can be used to restore the state for any aggregate class where it is sufficient to just feed some of the last original data to restore the state. For this to work, timestamp has to increase in value over time and the source and aggregate data must both be present.

It is even possible to restore the state for a chain of aggregate classes as long as there is access to the original data and the final aggregated data. Classes that do certain transformations can also be in the mix.

Template Parameters
TIME_STAMP_KEY_T The type for the timestamp keys specified next. The type for SOURCE and the TARGET time stamps are required to be the same.
SOURCE_TIME_STAMP_KEY The key ID to look up the timestamp for the SOURCE table. The key must be a key for the current or the last timestamp.
AGGREGATE_TIME_STAMP_KEY The key ID to look up the timestamp for the AGGREGATE table. The key must be a key for the current or the last timestamp.
NEXT The class in the chain to receive data
Examples
time_series_restore_aggregate.cpp.

Member Function Documentation

init()

template<class TIME_STAMP_KEY_T , RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT >
RDM_RETCODE RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >::init ( RDM_DB db )
inline

Initialize this object.

Call this method before sending it any data values, ranges, or statistics.

Return values
sOKAY Normal, successful return.
eINVARG Invalid argument.
eDBNOTOPEN Database not open.
eCURSORDB Cursor is associated with a different database.
ePRECOMMITTED A precommitted transaction must be committed or rolled back before further operations on this database are allowed.
Parameters
db [IN] Use this database for chained classes that need to insert rows
127 {
129
130if (rc == sOKAY)
131 {
132 restored_aggregate = false;
133 restore_aggregate::db = db;
134 }
135
136return rc;
137 }

References sOKAY.

put_range()

template<class TIME_STAMP_KEY_T , RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT >
template<class SOURCE_RANGE_T >
RDM_RETCODE RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >::put_range ( SOURCE_RANGE_T * source_range,
RDM::DB::TRANSACTIONAL_T transactional = RDM::DB::NOT_TRANSACTIONAL
)
inline

Template method for receiving ranges.

Receive one range and process it accordingly.

The type for the value provided is required to have columns for 'time_stamp_first', 'time_stamp_last', and 'value_range' with appropriate types. The column 'value_range' must be an array that is able to hold a static number of elements. Such a type can be generated using rdm-compile with a schema including a table similar to this:

CREATE TABLE range
(
value_range DOUBLE ARRAY [32] NOT NULL,
time_stamp_first UINT64 NOT NULL,
time_stamp_last UINT64 PRIMARY KEY
);

This operation can be specified as being transactional. However, if the caller always rolls back the transaction in the case of a failure, there is no need to specify single operations to be transactional.

Template Parameters
SOURCE_RANGE_T The actual type of the range received.
Return values
sOKAY Normal, successful return.
eNOSTARTUPDATE An update operation was attempted when no rdm_dbStartUpdate() is active.
eNOTLOCKED Attempt to access a table for reading or update without proper locks.
eCURSORDB Cursor is associated with a different database.
eDBNOTOPEN Database not open.
ePRECOMMITTED A precommitted transaction must be committed or rolled back before further operations on this database are allowed.
eDUPLICATE Attempt to insert a duplicate value as a unique/primary key.
eREADONLY Database is read-only and cannot be updated.
eREFINTEGRITY Integrity constraint violation.
eROWLIMIT Table row limit reached.
eINVARG Invalid argument.
Parameters
[in] source_range The source range sent to this class
transactional [IN] Is the put required to be transactional
428 {
429RDM_RETCODE rc = sOKAY;
430
431if (restored_aggregate == false)
432 {
433RDM_CURSOR cursor = NULL;
434 rc = rdm_dbGetRowsByKey (db, AGGREGATE_TIME_STAMP_KEY, &cursor);
435
436if (rc == sOKAY)
437 {
438 rc = rdm_cursorMoveToLast (cursor);
439if (rc == sENDOFCURSOR)
440 {
441 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
442 }
443else if (rc == sOKAY)
444 {
445 TIME_STAMP_KEY_T key;
446
447 rc = rdm_cursorReadKey (cursor, AGGREGATE_TIME_STAMP_KEY, &key, sizeof (key), NULL);
448
449if (rc == sOKAY)
450 {
451 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
452 }
453if (rc == sOKAY)
454 {
455 rc = rdm_cursorMoveToKey (cursor, SOURCE_TIME_STAMP_KEY, &key, sizeof (key));
456 }
457 }
458
459if (rc == sOKAY)
460 {
461 rc = rdm_cursorMoveToNext (cursor);
462 }
463
464while (rc == sOKAY)
465 {
466 SOURCE_RANGE_T source_range;
467 rc = rdm_cursorReadRow (cursor, &source_range, sizeof (source_range), NULL);
468if (rc == sOKAY)
469 {
470 rc = custom <NEXT>::put_range (&source_range);
471 }
472if (rc == sOKAY)
473 {
474 rc = rdm_cursorMoveToNext (cursor);
475 }
476 }
477if (rc == sENDOFCURSOR)
478 {
479 rc = sOKAY;
480 }
481
482rdm_cursorFree (cursor);
483 }
484
485if (rc == sOKAY)
486 {
487 restored_aggregate = true;
488 }
489 }
490
491if (rc == sOKAY)
492 {
493 rc = custom <NEXT>::put_range (source_range);
494 }
495
496return rc;
497 }

References rdm_cursorFree(), rdm_cursorMoveToKey(), rdm_cursorMoveToLast(), rdm_cursorMoveToNext(), rdm_cursorReadKey(), rdm_cursorReadRow(), rdm_dbGetRowsByKey(), sENDOFCURSOR, and sOKAY.

Here is the call graph for this function:

put_stats()

template<class TIME_STAMP_KEY_T , RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT >
template<class SOURCE_STATS_T >
RDM_RETCODE RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >::put_stats ( SOURCE_STATS_T * source_stats,
RDM::DB::TRANSACTIONAL_T transactional = RDM::DB::NOT_TRANSACTIONAL
)
inline

Template method for receiving statistics.

Receive one statistic and process it accordingly.

The type for the value provided is required to have columns for 'time_stamp_first', 'time_stamp_last', 'n', 'value_sum', and 'value_sum2' with appropriate types. Such a type can be generated using rdm-compile with a schema including a table similar to this:

CREATE TABLE stats
(
time_stamp_first UINT64 NOT NULL,
time_stamp_last UINT64 PRIMARY KEY,
n UINT64 NOT NULL,
value_sum DOUBLE NOT NULL,
value_sum2 DOUBLE NOT NULL
);

This operation can be specified as being transactional. However, if the caller always rolls back the transaction in the case of a failure, there is no need to specify single operations to be transactional.

Template Parameters
SOURCE_STATS_T The actual type of the statistic received.
Return values
sOKAY Normal, successful return.
eNOSTARTUPDATE An update operation was attempted when no rdm_dbStartUpdate() is active.
eNOTLOCKED Attempt to access a table for reading or update without proper locks.
eCURSORDB Cursor is associated with a different database.
eDBNOTOPEN Database not open.
ePRECOMMITTED A precommitted transaction must be committed or rolled back before further operations on this database are allowed.
eDUPLICATE Attempt to insert a duplicate value as a unique/primary key.
eREADONLY Database is read-only and cannot be updated.
eREFINTEGRITY Integrity constraint violation.
eROWLIMIT Table row limit reached.
eINVARG Invalid argument.
Parameters
[in] source_stats The source statistics sent to this class
transactional [IN] Is the put required to be transactional
312 {
313RDM_RETCODE rc = sOKAY;
314
315if (restored_aggregate == false)
316 {
317RDM_CURSOR cursor = NULL;
318 rc = rdm_dbGetRowsByKey (db, AGGREGATE_TIME_STAMP_KEY, &cursor);
319
320if (rc == sOKAY)
321 {
322 rc = rdm_cursorMoveToLast (cursor);
323if (rc == sENDOFCURSOR)
324 {
325 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
326 }
327else if (rc == sOKAY)
328 {
329 TIME_STAMP_KEY_T key;
330
331 rc = rdm_cursorReadKey (cursor, AGGREGATE_TIME_STAMP_KEY, &key, sizeof (key), NULL);
332
333if (rc == sOKAY)
334 {
335 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
336 }
337if (rc == sOKAY)
338 {
339 rc = rdm_cursorMoveToKey (cursor, SOURCE_TIME_STAMP_KEY, &key, sizeof (key));
340 }
341 }
342
343if (rc == sOKAY)
344 {
345 rc = rdm_cursorMoveToNext (cursor);
346 }
347
348while (rc == sOKAY)
349 {
350 SOURCE_STATS_T source_stats;
351 rc = rdm_cursorReadRow (cursor, &source_stats, sizeof (source_stats), NULL);
352if (rc == sOKAY)
353 {
354 rc = custom <NEXT>::put_stats (&source_stats);
355 }
356if (rc == sOKAY)
357 {
358 rc = rdm_cursorMoveToNext (cursor);
359 }
360 }
361if (rc == sENDOFCURSOR)
362 {
363 rc = sOKAY;
364 }
365
366rdm_cursorFree (cursor);
367 }
368
369if (rc == sOKAY)
370 {
371 restored_aggregate = true;
372 }
373 }
374
375if (rc == sOKAY)
376 {
377 rc = custom <NEXT>::put_stats (source_stats);
378 }
379
380return rc;
381 }

References rdm_cursorFree(), rdm_cursorMoveToKey(), rdm_cursorMoveToLast(), rdm_cursorMoveToNext(), rdm_cursorReadKey(), rdm_cursorReadRow(), rdm_dbGetRowsByKey(), sENDOFCURSOR, and sOKAY.

Here is the call graph for this function:

put_value()

template<class TIME_STAMP_KEY_T , RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT >
template<class SOURCE_VALUE_T >
RDM_RETCODE RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >::put_value ( SOURCE_VALUE_T * source_value,
RDM::DB::TRANSACTIONAL_T transactional = RDM::DB::NOT_TRANSACTIONAL
)
inline

Template method for receiving a data value.

Receive one data value and process it accordingly.

The type for the value provided is required to have columns for 'time_stamp_current' and 'value_current' with appropriate types. Such a type can be generated using rdm-compile with a schema including a table similar to this:

CREATE TABLE measurement
(
time_stamp_current UINT64 PRIMARY KEY,
value_current DOUBLE NOT NULL
);

This operation can be specified as being transactional. However, if the caller always rolls back the transaction in the case of a failure, there is no need to specify single operations to be transactional.

Template Parameters
SOURCE_VALUE_T The actual type of the source values received
Return values
sOKAY Normal, successful return.
eNOSTARTUPDATE An update operation was attempted when no rdm_dbStartUpdate() is active.
eNOTLOCKED Attempt to access a table for reading or update without proper locks.
eCURSORDB Cursor is associated with a different database.
eDBNOTOPEN Database not open.
ePRECOMMITTED A precommitted transaction must be committed or rolled back before further operations on this database are allowed.
eDUPLICATE Attempt to insert a duplicate value as a unique/primary key.
eREADONLY Database is read-only and cannot be updated.
eREFINTEGRITY Integrity constraint violation.
eROWLIMIT Table row limit reached.
eINVARG Invalid argument.
Parameters
[in] source_value The source value sent to this class
transactional [IN] Is the put required to be transactional
196 {
197RDM_RETCODE rc = sOKAY;
198
199if (restored_aggregate == false)
200 {
201RDM_CURSOR cursor = NULL;
202 rc = rdm_dbGetRowsByKey (db, AGGREGATE_TIME_STAMP_KEY, &cursor);
203
204if (rc == sOKAY)
205 {
206 rc = rdm_cursorMoveToLast (cursor);
207if (rc == sENDOFCURSOR)
208 {
209 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
210 }
211else if (rc == sOKAY)
212 {
213 TIME_STAMP_KEY_T key;
214
215 rc = rdm_cursorReadKey (cursor, AGGREGATE_TIME_STAMP_KEY, &key, sizeof (key), NULL);
216
217if (rc == sOKAY)
218 {
219 rc = rdm_dbGetRowsByKey (db, SOURCE_TIME_STAMP_KEY, &cursor);
220 }
221if (rc == sOKAY)
222 {
223 rc = rdm_cursorMoveToKey (cursor, SOURCE_TIME_STAMP_KEY, &key, sizeof (key));
224 }
225 }
226
227if (rc == sOKAY)
228 {
229 rc = rdm_cursorMoveToNext (cursor);
230 }
231
232while (rc == sOKAY)
233 {
234 SOURCE_VALUE_T source_value;
235 rc = rdm_cursorReadRow (cursor, &source_value, sizeof (source_value), NULL);
236if (rc == sOKAY)
237 {
238 rc = custom <NEXT>::put_value (&source_value);
239 }
240if (rc == sOKAY)
241 {
242 rc = rdm_cursorMoveToNext (cursor);
243 }
244 }
245if (rc == sENDOFCURSOR)
246 {
247 rc = sOKAY;
248 }
249
250rdm_cursorFree (cursor);
251 }
252
253if (rc == sOKAY)
254 {
255 restored_aggregate = true;
256 }
257 }
258
259if (rc == sOKAY)
260 {
261 rc = custom <NEXT>::put_value (source_value);
262 }
263
264return rc;
265 }

References rdm_cursorFree(), rdm_cursorMoveToKey(), rdm_cursorMoveToLast(), rdm_cursorMoveToNext(), rdm_cursorReadKey(), rdm_cursorReadRow(), rdm_dbGetRowsByKey(), sENDOFCURSOR, and sOKAY.

Here is the call graph for this function:

reset()

template<class TIME_STAMP_KEY_T , RDM_KEY_ID SOURCE_TIME_STAMP_KEY, RDM_KEY_ID AGGREGATE_TIME_STAMP_KEY, class NEXT >
void RDM::TIME_SERIES::restore_aggregate< TIME_STAMP_KEY_T, SOURCE_TIME_STAMP_KEY, AGGREGATE_TIME_STAMP_KEY, NEXT >::reset ( void )
inline

Reset this object.

Calling this method to discard all internally kept data values, ranges, and statistics that have not yet been persisted and start over from scratch.

Any alternative implementation of this method in a sub class would call this method to reset the next class.

149 {
151 restored_aggregate = false;
152 }

The documentation for this class was generated from the following file:
RDM_RETCODE put_value(SOURCE_VALUE_T *source_value, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving a data value.
Definition: rdm_time_series_custom.h:330
RDM_RETCODE rdm_cursorMoveToNext(RDM_CURSOR cursor)
Position a cursor to the next row in the collection.
friend class stats
Definition: rdm_time_series_custom.h:63
struct RDM_CURSOR_S * RDM_CURSOR
Definition: rdmtypes.h:306
RDM_RETCODE rdm_cursorReadRow(RDM_CURSOR cursor, void *colValues, size_t bytesIn, size_t *bytesOut)
Read all columns from a row.
RDM_RETCODE rdm_dbGetRowsByKey(RDM_DB db, RDM_KEY_ID keyId, RDM_CURSOR *pCursor)
Associate an RDM_CURSOR with a row set based on a key.
RDM_RETCODE put_range(SOURCE_RANGE_T *source_range, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving ranges.
Definition: rdm_time_series_custom.h:436
RDM_RETCODE init(RDM_DB db)
Initialize this object.
Definition: rdm_time_series_custom.h:159
@ sOKAY
Definition: rdmretcodetypes.h:97
RDM_RETCODE rdm_cursorFree(RDM_CURSOR cursor)
Free an RDM_CURSOR.
RDM_RETCODE rdm_cursorReadKey(RDM_CURSOR cursor, RDM_KEY_ID keyId, void *keyValue, size_t bytesIn, size_t *bytesOut)
Read the columns for a key from a table row.
RDM_RETCODE rdm_cursorMoveToKey(RDM_CURSOR cursor, RDM_KEY_ID keyId, const void *keyValue, size_t bytesIn)
Position a cursor based on a key value.
RDM_RETCODE rdm_cursorMoveToLast(RDM_CURSOR cursor)
Position a cursor to the last row in the collection.
void reset(void)
Reset this object.
Definition: rdm_time_series_custom.h:174
@ sENDOFCURSOR
Definition: rdmretcodetypes.h:58
friend class split
Definition: rdm_time_series_custom.h:58
RDM_RETCODE put_stats(SOURCE_STATS_T *source_stats, RDM::DB::TRANSACTIONAL_T transactional=RDM::DB::NOT_TRANSACTIONAL)
Template method for receiving statistics.
Definition: rdm_time_series_custom.h:383
RDM_RETCODE
RDM status and error return codes.
Definition: rdmretcodetypes.h:43