Entire-Metadata: .entire/metadata/fb87247f-2a75-407e-b336-cbc8c20ba5a6 Entire-Session: fb87247f-2a75-407e-b336-cbc8c20ba5a6 Entire-Strategy: manual-commit
800 lines
28 KiB
C
800 lines
28 KiB
C
/*
|
|
* (c) Copyright, Real-Time Innovations, 2002-2026.
|
|
* All rights reserved.
|
|
* No duplications, whole or partial, manual or electronic, may be made
|
|
* without express written permission. Any such copies, or
|
|
* revisions thereof, must display this notice unaltered.
|
|
* This code contains trade secrets of Real-Time Innovations, Inc.
|
|
*/
|
|
|
|
#ifndef reda_database_h
|
|
#define reda_database_h
|
|
|
|
#include "osapi/osapi_type.h"
|
|
#include "reda/reda_worker.h"
|
|
#include "reda/reda_fastBuffer.h"
|
|
#include "reda/reda_orderedDataType.h"
|
|
#include "reda/reda_table.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Doxygen file & module documentation ==================================*/
|
|
/*e \file
|
|
|
|
\brief Defines the REDADatabase
|
|
*/
|
|
|
|
/*e \defgroup REDADatabaseClass REDADatabase
|
|
\ingroup REDAModule
|
|
|
|
@brief structure that aggregates REDATables and
|
|
provides easier table management.
|
|
|
|
The Database provides an additional level of safety in case
|
|
Tables are added and removed. When using the Database, the application
|
|
should not use direct pointers to Tables but should use the safe
|
|
table-references the Database provides.
|
|
|
|
\image html Database_Public.jpg "Overview of REDADatabase"
|
|
|
|
More specifically, in case a Database is used, the Database supersedes
|
|
all the methods on the Table as follows:
|
|
\verbatim
|
|
REDADatabase_createTable supersedes REDATable_new
|
|
REDADatabase_bindCursor supersedes REDATable_bindCursor
|
|
REDADatabase_cleanup supersedes REDATable_cleanup AND
|
|
REDATable_delete
|
|
\endverbatim
|
|
|
|
An application can have one or more database and a database can hold
|
|
any number of tables of different types.
|
|
Typically, the life-cycle of a database is as follows.
|
|
|
|
\code
|
|
|
|
//create a new database
|
|
database = REDADatabase_new(....)
|
|
|
|
//add tables to the database
|
|
if (!REDADatabase_createTable(database, tableReference,...)) {
|
|
// table creation failed
|
|
}
|
|
|
|
//bind cursors to the table
|
|
REDACursor cursor;
|
|
if (!REDADatabase_bindCursor(database, &cursor,
|
|
tableReference, worker)) {
|
|
// binding a cursor is not possible
|
|
}
|
|
|
|
//now the cursor can be used SAFELY to read and modify
|
|
//the table; safety is guaranteed even if the table itself
|
|
//is subsequently removed and cleaned-up
|
|
|
|
//regularly you need to give the database a chance to
|
|
//reclaim resources
|
|
REDADatabase_cleanup(database, NULL, worker);
|
|
//This will reclaim resources on all tables, and even
|
|
//delete the tables themselves if it's safe to do so
|
|
|
|
//etc...create/use/remove tables and cleanup regularly
|
|
|
|
//Eventually...when the database itself needs to be deleted
|
|
//(deleting a database is fundamentally unsafe: it's the
|
|
// responsability of the application to make sure that
|
|
// essentially nobody will use any resources associated
|
|
// with the database)
|
|
REDADatabase_cleanup(database, &canBeDeleted, worker);
|
|
if (canBeDeleted) {
|
|
REDADatabase_delete(database, worker);
|
|
}
|
|
|
|
\endcode
|
|
|
|
In addition the Database provides support for the common use-case where
|
|
several workers need to access a Table efficiently through pre-allocated
|
|
Cursors.
|
|
|
|
\image html DatabaseWithCursorPerWorker.jpg "Using the CursorPerWorker
|
|
facility"
|
|
|
|
In this case, the methods createCursorPerWorker, deleteCursorPerWorker and
|
|
assertAndStartCursor supersede the methods bindCursor and Cursor_start.
|
|
A bound cursor will be kept in worker-specific storage, so that the Worker
|
|
can easily reuse a previoudly bound Cursor.
|
|
The prototypical use-case is as follows:
|
|
|
|
\code
|
|
|
|
//add a tables to the database
|
|
if (!REDADatabase_createTable(database, &tableReference,...)) {
|
|
// table creation failed
|
|
}
|
|
|
|
//provide a cursor to all current & future workers
|
|
cursorPerWorker =
|
|
REDADatabase_createCursorPerWorker(database, &tableReference);
|
|
|
|
//When a cursor needs to access a table, it does the following
|
|
//This call is very efficient unless the worker has never used this
|
|
//cursorPerWorker, in which case a new cursor is automatically created
|
|
//and bound to the Table
|
|
if (REDACursorPerWorker_assertAndStartCursor(cursorPerWorker, &cursor,
|
|
worker))
|
|
{
|
|
//access the table using the cursor
|
|
//goto....assert....lock....
|
|
REDACursor_finish(cursor);
|
|
}
|
|
|
|
//eventually, the CursorPerWorker needs to be destroyed
|
|
REDADatabase_destroyCursorPerWorker(database, cursorPerWorker);
|
|
|
|
//now: nobody is allowed to access this cursorPerWorker!
|
|
|
|
\endcode
|
|
|
|
@see REDADatabase_new REDADatabase_createTable
|
|
REDADatabase_createCursorPerWorker
|
|
*/
|
|
|
|
/* forward declare to appease the compiler. */
|
|
struct REDADatabase;
|
|
struct REDACursorPerWorker;
|
|
struct REDAWeakReference;
|
|
struct REDACursor;
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
@brief Structure to configure detailed Database properties
|
|
*/
|
|
struct REDADatabaseProperty {
|
|
/*e hint for memory management of table: resources are allocated
|
|
in chunks that have enough space to store tableAllocationChunk
|
|
tables */
|
|
struct REDAFastBufferPoolGrowthProperty growth;
|
|
|
|
/*e maximum skiplist level for all tables in the database */
|
|
RTI_UINT8 skiplistLevelMax;
|
|
|
|
/*e initial number of total records across all tables
|
|
for which resources are allocated at the database level;
|
|
the resources will grow as needed by doubling */
|
|
int totalRecordCountInitial;
|
|
|
|
/*e Initial number of weak references.
|
|
|
|
Each database has a collection of weak references to records of the
|
|
tables it contains. This paramater specifies the initial size of the
|
|
collection. The actual initial value used may be larger than the one
|
|
specified here if the specified initial value would not allow the
|
|
number of weak references to grow to the specified maximum. */
|
|
int weakReferenceCountInitial;
|
|
|
|
/*e
|
|
* Maximum number of weak references.
|
|
*
|
|
* Each database has a collection of weak references to records of the
|
|
* tables it contains. This paramater specifies the maximum size of the
|
|
* collection. The special constant
|
|
* REDA_DATABASE_WEAKREF_COUNT_MAX_UNLIMITED can be used to indicate that
|
|
* the collection should grow indefinitely as needed.
|
|
*/
|
|
int weakReferenceCountMax;
|
|
};
|
|
|
|
/*e
|
|
* \ingroup REDADatabaseClass
|
|
* @brief Used as the maximum level for a skiplist in a database.
|
|
*
|
|
* Seems like there would be little penalty if we were to use
|
|
* REDA_SKIPLIST_LEVEL_MAX_UPPER_LIMIT as the probability of higher
|
|
* level nodes is negligible whenever sizing arrays we are
|
|
* using REDA_SKIPLIST_FORWARD_POINTERS_MAX anyway. However this can save in
|
|
* the number of fast-buffer pools needed to manage the different
|
|
* level nodes. Experimentally seven works well up to 1000 nodes. 2^7
|
|
* is 128 so there would be about 8 iterations. We have tables but
|
|
* still this may be too limiting. A better scheme may be to re-use
|
|
* the same fast-buffer pools at several levels, e.g. size it to
|
|
* accommodate the largest level in the set and install teh same pool
|
|
* for all. Good pool sizes to minimize overhead may be: 1, 2, 3, 4,
|
|
* 6, 9, 16, 32. Eight pools cover all levels and the average number of
|
|
* pointers wasted per node is about 1/32!!
|
|
*
|
|
* 1*p(l=5) + 2*p(l=7) + 1*p(l=8) + 6*p(l=10)+5*p(l=11)+... + 15*p(l=17)+...
|
|
*
|
|
* = (1/32-1/64) + 2/128-1/256 + 6/1024-1/2048-1/4096... + 15/2^17 - 1/2^18
|
|
* -...
|
|
* ~< 1/64 + 1/64 + 1/128 + 1/8128
|
|
* ~= 1/32
|
|
*/
|
|
#define REDA_DATABASE_SKIPLIST_LEVEL_MAX (7)
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
@brief Database initial total record count.
|
|
*/
|
|
#define REDA_DATABASE_TOTAL_RECORD_COUNT_INITIAL (128)
|
|
|
|
/*e
|
|
* \ingroup REDADatabaseClass
|
|
* @brief Database initial weak reference count.
|
|
*
|
|
* This initial value will be adjusted upwards as necessary to allow the
|
|
* number of weak references to grow to the maximum.
|
|
*/
|
|
#define REDA_DATABASE_WEAKREF_COUNT_INITIAL (1)
|
|
|
|
/*e
|
|
* \ingroup REDADatabaseClass
|
|
* @brief Database unlimited weak reference count.
|
|
*
|
|
* This value indicates that the number of weak references can grow without
|
|
* limit. In can be used to indicate that there is not a maximum number of weak
|
|
* references.
|
|
*/
|
|
#define REDA_DATABASE_WEAKREF_COUNT_MAX_UNLIMITED (-1)
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
@brief Default property of database.
|
|
*/
|
|
#define REDA_DATABASE_PROPERTY_DEFAULT \
|
|
{ REDA_FAST_BUFFER_POOL_GROWTH_PROPERTY_DEFAULT, \
|
|
REDA_DATABASE_SKIPLIST_LEVEL_MAX, \
|
|
REDA_DATABASE_TOTAL_RECORD_COUNT_INITIAL, \
|
|
REDA_DATABASE_WEAKREF_COUNT_INITIAL, \
|
|
REDA_DATABASE_WEAKREF_COUNT_MAX_UNLIMITED }
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Create new database to hold tables.
|
|
|
|
@post On success, a valid empty database is returned
|
|
|
|
@param workerFactory \b In. This manager must stay in existence as
|
|
long as the Database is in existence.
|
|
|
|
@param adminEA \b In. The EA the database will use for administrative
|
|
purposes. The level of this EA must be such that the EA can be entered
|
|
from within any table- or record-level EAs.
|
|
|
|
@param property \b In. Contains optional detailed configuration properties
|
|
for the database. If NULL is passed, defaults are used. The structure
|
|
can be deleted after the creation of the database returns.
|
|
|
|
@param worker \b In.
|
|
|
|
@return Pointer to the database on success. NULL on failure.
|
|
|
|
@mtsafety safe.
|
|
|
|
@see REDADatabase_createTable REDAWorkerFactory_new
|
|
*/
|
|
extern REDADllExport struct REDADatabase *REDADatabase_new(
|
|
struct REDAWorkerFactory *workerFactory,
|
|
struct REDAExclusiveArea *adminEA,
|
|
const struct REDADatabaseProperty *property,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Get the property of a database.
|
|
|
|
@param property \b In. After this method returns, this will contains
|
|
detailed configuration properties for the database.
|
|
|
|
@param worker \b In.
|
|
|
|
@mtsafety safe.
|
|
*/
|
|
extern REDADllExport void REDADatabase_getProperty(
|
|
struct REDADatabase *me,
|
|
struct REDADatabaseProperty *property,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
@brief get the WorkerFactory that this database uses.
|
|
@pre database instantiated
|
|
|
|
@see REDADatabase_new
|
|
*/
|
|
extern REDADllExport struct REDAWorkerFactory *REDADatabase_getWorkerFactory(
|
|
struct REDADatabase *me);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Deletes a REDADatabase.
|
|
|
|
It is the responsability of the application that uses the database
|
|
to ensure that, after the call to REDADatabase_delete is made, no
|
|
other methods are invoked on the database and no weak-references
|
|
to records in tables of the database are used.
|
|
|
|
@pre A valid (undeleted) Database for which the databaseCanBeDeleted
|
|
parameter returned on invoking REDADatabase_cleanup is RTI_TRUE; this
|
|
means that all user tables in the Database have been removed and are
|
|
cleaned up completely.
|
|
|
|
@post The database is deleted.
|
|
|
|
@param worker \b In. The worker that does the delete; can be any worker
|
|
|
|
@mtsafety UNSAFE (it's the responsability of the caller that only one
|
|
thread calls this at most once).
|
|
|
|
@see REDADatabase_new REDADatabase_cleanup
|
|
*/
|
|
extern REDADllExport RTIBool
|
|
REDADatabase_delete(struct REDADatabase *me, struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Cleaning up will invoke the cleanup method on all tables in
|
|
the database and on the internal structures.
|
|
This reclaims unused resource in the database and its tables
|
|
in a thread-safe manner: any thread can call cleanup at any
|
|
time.
|
|
|
|
@pre A valid (undeleted) Database
|
|
|
|
@post All database resources that can be safely deleted have
|
|
been freed to the heap or returned to their pools
|
|
|
|
@param databaseCanBeDeleted \b Out. Means the database is
|
|
currently in a state where it could be deleted (all tables
|
|
have been removed and cleanup has been allowed to run
|
|
sufficiently for a complete cleanup) Optional parameter.
|
|
@param worker \b In. The worker that does the cleanup
|
|
|
|
@mtsafety safe: any worker can call this; workers could call
|
|
it concurrently although that is not a useful use-case; typically
|
|
one reaper-thread will occasionally perform clean-up
|
|
|
|
@see REDADatabase_delete
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_cleanup(
|
|
struct REDADatabase *me,
|
|
RTIBool *databaseCanBeDeleted,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Create a new table in the database.
|
|
|
|
@param tableReference \b Out. On success, this will contain
|
|
a reference to the new table
|
|
|
|
@param tableName \b In. An optional name of the table. Maximum length is
|
|
REDA_TABLE_NAME_MAX_LENGTH. Can be NULL.
|
|
|
|
@param keyType \b in. Defines the type of keys used to identify the
|
|
records in the the table. Must have been initialized with
|
|
REDAOrderedDataType_define. The relevant contents will be copied
|
|
into the table; this structure can be deleted after the Table has
|
|
been created.
|
|
|
|
@param readOnlyAreaType \b in. Defines the type of data in the read-only
|
|
area of the records. Must have been initialized with
|
|
REDAOrderedDataType_define or can be NULL in case the Table should not
|
|
have records with a readOnlyArea.
|
|
The relevant contents will be copied into the table; this structure
|
|
can be deleted after the Table has been created.
|
|
|
|
@param readWriteAreaType \b in. Defines the type of data in the read-write
|
|
area of the records. Must have been initialized with
|
|
REDAOrderedDataType_define OR can be NULL in case the Table should not
|
|
have records with a readWriteArea.
|
|
The relevant contents will be copied into the table; this structure can
|
|
be deleted after the Table has been created.
|
|
|
|
@param hashDefinition \b in. Defines the hashing that will be used
|
|
on the key. See the documentation for REDAHashedSkiplist and REDAHash
|
|
for more information.
|
|
The relevant contents will be copied into the table; this structure
|
|
can be deleted after the Table has been created. In case this parameter
|
|
is NULL, no hashing will be used.
|
|
|
|
@param tableEA \b in. The table-level exclusive area. It is necessary
|
|
that a worker can enter the adminEA of the table, the adminEA of the
|
|
weak-reference manager and the record EA's from within the tableEA.
|
|
|
|
@param tableFinalizeFnc \b In. A function to be notified that the
|
|
table is physically removed from memory and nobody is able to access
|
|
it anymore. See REDATableFinalizeFunction for details. It is called
|
|
in the context of REDADatabase_cleanup.
|
|
This parameter may be NULL if no finalization function is desired.
|
|
|
|
@param tableFinalizeParam \b In. Parameter to pass to tableFinalizeFnc.
|
|
|
|
@param recordFinalizeFnc \b in. Used to notify application when a
|
|
record is about the be physically removed and nobody can access its
|
|
contents. See REDARecordFinalizeFunction for details. It is called
|
|
in the context of REDADatabase_cleanup.
|
|
May be NULL to indicate there is no notification is needed.
|
|
|
|
@param recordFinalizeParam \b in. Additional parameter to pass to
|
|
recordFinalizeFnc.
|
|
|
|
@param growthPropertyIn. Directive for how the table should grow.
|
|
|
|
@param tableUserData \b in. Table provides storage space for one
|
|
pointer, which can be retrieved safely through REDACursor_getTableUserData.
|
|
The table only provides safe read-only access; this pointer or the
|
|
structure it points cannot be modified without additional protection
|
|
on top of the Table.
|
|
|
|
@param worker \b in. Worker used for table-creation only.
|
|
|
|
@return RTI_TRUE on success, RTI_FALSE on failure
|
|
|
|
@mtsafety safe
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_createTable(
|
|
struct REDADatabase *me,
|
|
struct REDAWeakReference *tableReference,
|
|
const char *tableName,
|
|
struct REDAOrderedDataType *keyType,
|
|
struct REDAOrderedDataType *readOnlyAreaType,
|
|
struct REDAOrderedDataType *readWriteAreaType,
|
|
const struct REDAHashDefinition *hashDefinition,
|
|
struct REDAExclusiveArea *tableEA,
|
|
REDATableFinalizeFunction tableFinalizeFnc,
|
|
void *tableFinalizeParam,
|
|
REDATableRecordFinalizeFunction recordFinalizeFnc,
|
|
void *recordFinalizeParam,
|
|
const struct REDAFastBufferPoolGrowthProperty *growthPropertyIn,
|
|
void *tableUserData,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Bind a cursor to a previously created table in the database and a
|
|
worker. REDACursor is the mechanism that is used to interact with a
|
|
table.
|
|
|
|
Once bound, the cursor is exclusively attached to the table and must
|
|
be called only by the thread whose worker the cursor is bound to.
|
|
|
|
REDADatabase will ensure that a table is not deleted while there are
|
|
any cursors bound to it and makes, therefore, the use of cursors
|
|
thread-safe even in the present of other threads that remove tables.
|
|
|
|
@pre REDACursor not currently bound to any table
|
|
@post The REDACursor is now bound to a table and a worker.
|
|
|
|
@param database \b In.
|
|
|
|
@param cursor \b InOut. A cursor that is not bound to any tables. This
|
|
paramater must point to valid storage and cannot be NULL.
|
|
|
|
@param tableReference In. Reference to a previously-created table in the
|
|
database (see REDADatabase_createTable)
|
|
|
|
@param worker In. The identify of "thread" that will be accessing
|
|
the table using the cursor.
|
|
|
|
@return RTI_TRUE if successful or RTI_FALSE otherwise.
|
|
|
|
@mtsafety safe.
|
|
|
|
@see REDADatabase_bindCursor REDACursor REDADatabase_createTable
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_bindCursor(
|
|
struct REDADatabase *me,
|
|
struct REDACursor *cursor,
|
|
struct REDAWeakReference *tableReference,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
@param tableReference \b In. Reference to the table to which the
|
|
cursor-per-worker will be bound as the workers need them
|
|
|
|
@return cursor-per-worker created for the table. NULL on failure.
|
|
|
|
@see REDACursorPerWorker_assertAndStartCursor
|
|
REDADatabase_destroyCursorPerWorker
|
|
*/
|
|
extern REDADllExport struct REDACursorPerWorker *
|
|
REDADatabase_createCursorPerWorker(
|
|
struct REDADatabase *me,
|
|
struct REDAWeakReference *tableReference);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@param cursorPerWorker \b InOut.The cursorPerWorker that will
|
|
be destroyed. May be NULL, in which case noop.
|
|
@param worker \b In. The worker of the calling thread, cannot be NULL.
|
|
|
|
@see REDACursorPerWorker_assertAndStartCursor
|
|
REDADatabase_createCursorPerWorker
|
|
*/
|
|
extern REDADllExport void REDADatabase_destroyCursorPerWorker(
|
|
struct REDADatabase *me,
|
|
struct REDACursorPerWorker *cursorPerWorker,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \defgroup REDACursorPerWorkerClass REDACursorPerWorker
|
|
\ingroup REDADatabaseClass
|
|
@brief A factory for the cursors that are bound to a table in the database.
|
|
*/
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDACursorPerWorkerClass
|
|
|
|
@brief Return a cursor bound to the worker (and to the table defined
|
|
when the CursorPerWorker was created).
|
|
|
|
This call can be slow if the worker has never asserted a cursor before
|
|
from this CursorPerWorker. In this case it involves memory allocation and
|
|
binding a Cursor to a table.
|
|
However, in all other cases, this call is very fast: it takes
|
|
an already bound cursor out of worker-specific storage.
|
|
|
|
@param cursorPerWorker \b In.
|
|
@param cursorPtr \b Out. The cursor bound to this worker will be
|
|
returned here
|
|
@param failReasonPtr \b Out. Optional, in case you want to find why
|
|
this failed.
|
|
@param worker \b In. The worker that should make this call: the
|
|
cursor will be bound to this worker and this worker's worker-
|
|
specific storage will be used to store the bound cursor
|
|
|
|
@return RTI_TRUE on success, RTI_FALSE on failure
|
|
|
|
@see REDADatabase_createCursorPerWorker
|
|
REDADatabase_destroyCursorPerWorker
|
|
*/
|
|
extern REDADllExport RTIBool REDACursorPerWorker_assertAndStartCursorFnc(
|
|
struct REDACursorPerWorker *me,
|
|
struct REDACursor **cursorPtr,
|
|
int *failReasonPtr,
|
|
struct REDAWorker *worker);
|
|
|
|
/* ----------------------------------------------------------------- */
|
|
/*e \ingroup REDACursorPerWorkerClass
|
|
|
|
@brief Return a cursor bound to the worker (and to the table defined
|
|
when the CursorPerWorker was created).
|
|
|
|
This call can be slow
|
|
if the worker has never asserted a cursor before from this
|
|
CursorPerWorker. In this case it involves memory allocation and
|
|
binding a Cursor to a table.
|
|
However, in all other cases, this call is very fast: it takes
|
|
an already bound cursor out of worker-specific storage.
|
|
|
|
@behavior May be macroed for performance
|
|
@param cursorPerWorker \b In.
|
|
@param cursorPtr \b Out. The cursor bound to this worker will be
|
|
returned here
|
|
@param worker \b In. The worker that should make this call: the
|
|
cursor will be bound to this worker and this worker's worker-
|
|
specific storage will be used to store the bound cursor
|
|
|
|
@return content of cursorPtr as a convenience
|
|
*/
|
|
extern REDADllExport struct REDACursor *REDACursorPerWorker_assertCursor(
|
|
struct REDACursorPerWorker *me,
|
|
struct REDACursor **cursorPtr,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDACursorPerWorkerClass
|
|
@brief Get, bind, and start a cursor to a table in a lazy manner.
|
|
|
|
A recurring usage pattern with multiple cursors in a function is as follows:
|
|
<OL>
|
|
<LI>Get and start cursor A on the database
|
|
<LI>Get and start cursor B on the database
|
|
<LI>Do stuff in table A
|
|
<LI>Do stuff in table B
|
|
<LI>finish B
|
|
<LI>finish A
|
|
</OL>
|
|
All the while, we must pop out and finish every started cursor on exception.
|
|
As a good coding practice, concept of "stack of cursors" you pop out of
|
|
is useful.
|
|
|
|
@behavior May be macroed for performance
|
|
|
|
@pre Preconditions for REDADatabase_getCursorLazy and
|
|
REDACursor_startSafe jointly apply.
|
|
|
|
@post post conditions for REDADatabase_getCursorLazy and
|
|
REDACursor_startSafe jointly apply.
|
|
|
|
@param cursorPtr \b Out. Point to the cursor in question. API is somewhat
|
|
cumbersome for macroization.
|
|
|
|
@param failReasonPtr \b Out. See failStatus param for REDACursor_startSafe.
|
|
|
|
@param safeCursorStack \b InOut. an array of pointers to cursors
|
|
all in one of the "active" states. In other words \c cursors[0] is
|
|
of type \c (REDACursor *). On succesful \e cursor will be added to
|
|
the array, that is, cursors[*current]= cursor.
|
|
|
|
@param currentIndex \b Inout. Pointer to an integer containing the number
|
|
of pointer to cursors currently in the \e cursors array. On
|
|
succesful return *current will be incremeted to account for the new
|
|
pointer to cursor in the array.
|
|
|
|
@param tableReference \b In. Reference to a previously-created table
|
|
in the database.
|
|
|
|
@param workerStorageId \b In. Storage id that is either new to the
|
|
worker, or lese has been used to store a cursor bound to that table
|
|
and worker.
|
|
|
|
@param worker \b In. The identify of "thread" that will use the cursor
|
|
to access the table.
|
|
|
|
@return Cursor the cursor living inside worker-specific storage. On success,
|
|
it will be be bound to that table and worker.
|
|
|
|
@see REDACursor_finishSafe
|
|
*/
|
|
RTIBool REDACursorPerWorker_assertAndStartCursorSafe(
|
|
struct REDACursorPerWorker *me,
|
|
struct REDACursor **cursorPtr,
|
|
int *failReasonPtr,
|
|
struct REDACursor *safeCursorStack,
|
|
int *currentIndex,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
* @brief Find table by table name in database.
|
|
*
|
|
* @param tableReference \b Out. On success, this will contain a reference to
|
|
* the new table. Can be NULL if you do not need to obtain weak reference to
|
|
* table.
|
|
*
|
|
* @param tableName \b In. Name of the table to be searched.
|
|
*
|
|
* @param worker \b In. Worker used for finding table only.
|
|
*
|
|
* @return RTI_TRUE on success, RTI_FALSE on failure.
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_findTable(
|
|
struct REDADatabase *me,
|
|
struct REDAWeakReference *tableReference,
|
|
const char *tableName,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
* @brief Print out the name of all tables in database.
|
|
*
|
|
* @param database \b In. The database.
|
|
*
|
|
* @param worker \b In. Worker used for listing table only.
|
|
*
|
|
* @return RTI_TRUE on success, RTI_FALSE on failure.
|
|
*/
|
|
extern REDADllExport RTIBool
|
|
REDADatabase_listTables(struct REDADatabase *me, struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
* @brief Print out the records for a table in database.
|
|
*
|
|
* @param database \b In. The database.
|
|
* @param tableReferenceIn \b In. If not null, WR used to look up the table
|
|
* to print.
|
|
* @param tableNameIn \b In. If not null, table name used to look up the table
|
|
* to print.
|
|
* @param useCompactPrintFormat \b In. Determines if tue compat print format
|
|
* is used.
|
|
* @param printAdminArea \b In. Determines if the admin area is printed.
|
|
* @param worker \b In. Worker used for listing table only.
|
|
*
|
|
* @return RTI_TRUE on success, RTI_FALSE on failure.
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_listRecords(
|
|
struct REDADatabase *database,
|
|
const struct REDAWeakReference *tableReference,
|
|
const char *tableName,
|
|
RTIBool useCompactPrintFormat,
|
|
RTIBool printAdminArea,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
@brief Creates a new exclusiveArea
|
|
The EA will be created with "UNNAMED_EA" name. It is mainly used for testing.
|
|
|
|
@post exclusiveArea is a properly initialized exclusiveArea with
|
|
referenceCount 0
|
|
|
|
@param database \b InOut. this
|
|
@param level \b In. The level of this EA; for deadlock-prevention. This
|
|
level must be > 0.
|
|
@param worker \b In.
|
|
|
|
@return NULL on failure. Pointer to the newly created exclusive area on
|
|
success.
|
|
|
|
@mtsafety safe
|
|
|
|
@see REDADatabase_destroyExclusiveArea
|
|
*/
|
|
extern REDADllExport struct REDAExclusiveArea *REDADatabase_createExclusiveArea(
|
|
struct REDADatabase *database,
|
|
int level,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
*
|
|
* @brief Creates a new exclusiveArea
|
|
*
|
|
* @post exclusiveArea is a properly initialized exclusiveArea with
|
|
* referenceCount 0
|
|
*
|
|
* @param database \b InOut. this
|
|
* @param level \b In. The level of this EA; for deadlock-prevention. This
|
|
* level must be > 0.
|
|
* @param name \b In. The name of the new EA.
|
|
* @param worker \b In.
|
|
*
|
|
* @return NULL on failure. Pointer to the newly created exclusive area on
|
|
* success.
|
|
*
|
|
* @mtsafety safe
|
|
*
|
|
* @see REDADatabase_destroyExclusiveArea
|
|
*/
|
|
extern REDADllExport struct REDAExclusiveArea *
|
|
REDADatabase_createExclusiveAreaEx(
|
|
struct REDADatabase *database,
|
|
int level,
|
|
const char *name,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
*
|
|
* Destroy an EA created by REDADatabase_createExclusiveArea.
|
|
*
|
|
* @param database \b InOut. The REDADatabase object.
|
|
* @param ea \b InOut. The ExclusiveArea that should be destroyed.
|
|
* @param worker \b In. The Worker.
|
|
*
|
|
* @mtsafety Safe with regards to the manager. The EA must be destroyed only
|
|
* once. A destroyed EA cannot be used for asserting a new record and both
|
|
* operations cannot be called concurrently.
|
|
* The physical destruction of the EA will be done in the database clean up.
|
|
*
|
|
* @see REDADatabase_createExclusiveArea
|
|
*/
|
|
extern REDADllExport void REDADatabase_destroyExclusiveArea(
|
|
struct REDADatabase *database,
|
|
struct REDAExclusiveArea *ea,
|
|
struct REDAWorker *worker);
|
|
|
|
/*e \ingroup REDADatabaseClass
|
|
|
|
Remove a table without requiring a cursor.
|
|
|
|
@param database \b InOut. this
|
|
@param tableReference \b InOut. Weak reference to the table to be removed
|
|
@param worker \b In.
|
|
*/
|
|
extern REDADllExport RTIBool REDADatabase_removeTable(
|
|
struct REDADatabase *database,
|
|
struct REDAWeakReference *tableReference,
|
|
struct REDAWorker *worker);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif /* __cplusplus */
|
|
|
|
#include "reda/reda_database_impl.h"
|
|
|
|
#endif /* reda_database_h */
|