LAR Library: Table Management

LAR Library

Table Management

Typedefs

typedef struct table_t table_t
 Opaque type of a table instance.
 

Enumerations

enum  tabErrors_t { TAB_ERR_DELETED = 1 }
 Return codes specific to this module. More...
 

Functions

int tabOpen (const char *fname, table_t **t)
 Open an existing table. More...
 
int tabCreate (const char *fname, int recSize, table_t **t)
 Create a new table or reset an existing one. More...
 
void tabClose (table_t *t)
 Close a table_t instance. More...
 
int tabFlush (table_t *t)
 Force an update of the table file. More...
 
int tabRecSize (table_t *t)
 Return the record size for a table. More...
 
int tabGetStamp (table_t *t, uint32_t *stamp)
 Return the stamp value of the table. More...
 
int tabSetStamp (table_t *t, uint32_t stamp)
 Modify the stamp value of the table. More...
 
int tabGet (table_t *t, int recn, void *recp)
 Read an entry from the table. More...
 
int tabPut (table_t *t, int recn, const void *recp)
 Write or update an entry on the table. More...
 
int tabAppend (table_t *t, const void *recp)
 Append an entry to the table. More...
 
int tabSize (table_t *t)
 Return the total number of entries on the table. More...
 
int tabCount (table_t *t)
 Return the number of non-deleted entries on the table. More...
 
int tabDelete (table_t *t, int recn)
 Mark an entry as deleted. More...
 
int tabUnDelete (table_t *t, int recn)
 Remove the deleted mark of an entry. More...
 
int tabPack (const char *fname)
 Permanently remove from the table all entries marked as deleted. More...
 
int tabGoFirst (table_t *t)
 Move the current entry marker to the first (zero'th) element on the table. More...
 
int tabGetNext (table_t *t, void *recp)
 Read the current entry and move to the next. More...
 
int tabGetPrev (table_t *t, void *recp)
 Read the previous element. More...
 
int tabGoLast (table_t *t)
 Move to the last element on the table. More...
 
int tabFindNext (table_t *t, void *recp, const void *keyp, int(*cmpFn)(const void *recp, const void *keyp))
 Search incrementally the table for an entry. More...
 
int tabFind (table_t *t, void *recp, const void *keyp, int(*cmpFn)(const void *recp, const void *keyp))
 Search the table for an element. More...
 

Detailed Description

Rationale

Simple DBF-like tables are at the core of most applications (transactions done, supported AIDs/keys, etc). Providing a common API not only eases on development (no need to reinvent the wheel) but also makes easier to replace by a version that provides custom characteristics (caching, storage access) without needing to revise the caller application.

Introduction

This module implements a sequential storage of fixed-size records, in other words a table. This table is indexed by the position of each record, or entry, inside the table, with zero being the first one.

Each entry also includes a flag indicating if it was marked for deletion or not. New entries are always written to the end of the file, even if deleted entries exist. The user must manually call tabPack() to permanently remove all deleted entries from the file. If tabPack() is never called the file will grow indefinitely.

The table header has a field called stamp, a 32-bit unsigned integer value that can be modified by the user to control table versioning and state (no functions on this module, except for tabGetStamp() and tabSetStamp(), change this value). Upon creation the table receives a stamp value of zero.

This module does no control of table integrity (checksum, for example), if an application needs this level of integrity control, it must do so itself.

Some meta-data of the table (as number of elements) is kept in a memory cache and are only written with tabFlush() is called. This is done to (greatly) improve performance of table operations, specially during repeated add. Note that tabFlush() is internally called by tabClose(). See Caching below.

Multi-Threading

No synchronization is done on accesses to the same table_t instance. The caller must guarantee that the same instance is not accessed concurrently. Simultaneous accesses to separate instances are ok.

Caching

An implementation is allowed to cache operations in memory before committing to storage. To guarantee that all changes have been written, the user must call tabFlush().

The current version caches the contents of the table header. This is done to avoid re-writing the header when adding or deleting records and changing the stamp value, and causes significant performance improvements on Telium platform.

Enumeration Type Documentation

Return codes specific to this module.

Enumerator
TAB_ERR_DELETED 

Signal that the target entry is marked as deleted.

Function Documentation

int tabAppend ( table_t t,
const void *  recp 
)

Append an entry to the table.

This call is equivalent to tabPut(t, tabSize(t), recp) and has the same performance characteristics.

Parameters
tA valid table_t instance.
recpData to write to new entry.
Returns
BASE_ERR_OK if record was read correctly.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_INVALID_PARAMETER if recp is invalid.
See also
tabPut()
void tabClose ( table_t t)

Close a table_t instance.

Parameters
tA valid table_t instance.
int tabCount ( table_t t)

Return the number of non-deleted entries on the table.

This operation is O(1) and very quick, requiring no storage access.

Parameters
tA valid table_t instance.
Returns
The number non-deleted entries on the file.
BASE_ERR_INVALID_HANDLE if t is invalid.
int tabCreate ( const char *  fname,
int  recSize,
table_t **  t 
)

Create a new table or reset an existing one.

Parameters
fnameFile name of the table to open.
recSizeSize of each record on the table, in bytes. Must be a positive number. There is no other hard-coded restriction other than available memory and the limitations of the int type.
[out]tOn success, store the handle to the open table.
Returns
BASE_ERR_OK on success.
BASE_ERR_DATA_NOT_FOUND if fname was not found.
BASE_ERR_ACCESS if cannot access the file fname.
BASE_ERR_INVALID_PARAMETER if fname, recSize or t is invalid
int tabDelete ( table_t t,
int  recn 
)

Mark an entry as deleted.

This does not effectively remove the entry from the file, only mark it as deleted. The entry can be read with tabGet() and un-deleted with tabUnDelete(), but will not be returned as a result of any iteration or search function.

This operation is O(1) and requires at most two writes (one to the deleted flag of the record, another to the table header).

Parameters
tA valid table_t instance.
recnIndex of record to delete, in the range [0, tabSize(t) - 1].
Returns
BASE_ERR_OK if record was read correctly.
BASE_ERR_DATA_NOT_FOUND if recn is an invalid index.
BASE_ERR_INVALID_HANDLE if t is invalid.
See also
tabUnDelete() tabGet()
int tabFind ( table_t t,
void *  recp,
const void *  keyp,
int(*)(const void *recp, const void *keyp)  cmpFn 
)

Search the table for an element.

This is equivalent to a call to tabGoFirst() followed by a call to tabFindNext().

This operation is O(n).

Parameters
tA valid table_t instance.
[out]recpContents of the entry found. Modified even if entry was not found.
keypPointer to the key passed as second parameter to cmpFn.
cmpFnComparison function, see tabFindNext().
Returns
The index of the record read (>= 0) on success.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if no matching record was found.
BASE_ERR_INVALID_PARAMETER if any required parameter is NULL.
See also
tabFindNext()
tabGoFirst()
int tabFindNext ( table_t t,
void *  recp,
const void *  keyp,
int(*)(const void *recp, const void *keyp)  cmpFn 
)

Search incrementally the table for an entry.

Return the index of the next element recp, starting at the current table position, for which cmpFn(recp, keyp) is zero.

This is equivalent to iterating through the table using tabGetNext() until an entry that satisfies the cmpFn() condition is found.

This operation is O(n).

Parameters
tA valid table_t instance.
[out]recpContents of the entry found. Modified even if entry was not found.
keypPointer to the key passed as second parameter to cmpFn.
cmpFnComparison function, see the description above.
Returns
The index of the record read (>= 0) on success.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if no matching record was found.
BASE_ERR_INVALID_PARAMETER if any required parameter is NULL.
int tabFlush ( table_t t)

Force an update of the table file.

The implementation is allowed to cache certain operations for faster throughput, this call forces all pending changes to be actually written to storage.

Because of this, there is no guarantee that any change to the table is actually reflected on storage before this call.

Parameters
tA valid table_t instance.
Returns
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_RESOURCE_PB if could not commit changes.
int tabGet ( table_t t,
int  recn,
void *  recp 
)

Read an entry from the table.

The code to read a record and detect if it is marked as deleted:

1 err = tabGet(table, index, &record);
2 if (err == BASE_ERR_OK) {
3  // record was read and *NOT* marked as deleted
4 }
5 else if (err == TAB_ERR_DELETED) {
6  // record was read but *IS* marked as deleted
7 }
8 else {
9  // failed: could not read record
10 }

This operation is O(1), requiring only one read operation.

Parameters
tA valid table_t instance.
recnIndex of the entry to read, in the range [0, tabSize(t) - 1].
[out]recpWhere to store the entry data. Must have space for at least tabRecSize(t) bytes.
Returns
BASE_ERR_OK if record was read correctly.
TAB_ERR_DELETED if the record was read, but it is marked as deleted.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if recn is an invalid index.
BASE_ERR_INVALID_PARAMETER if recp is invalid.
int tabGetNext ( table_t t,
void *  recp 
)

Read the current entry and move to the next.

This call skips all entries marked as deleted.

Parameters
tA valid table_t instance.
[out]recpContents of the read entry. Not modified if no entry was read.
Returns
The index of the record read (>= 0) on success.
BASE_ERR_DATA_NOT_FOUND on EOF.
int tabGetPrev ( table_t t,
void *  recp 
)

Read the previous element.

This call skips all entries marked as deleted.

Parameters
tA valid table_t instance.
[out]recpContents of the read entry. Not modified if no entry was read.
Returns
The index of the record read (>= 0) on success.
BASE_ERR_DATA_NOT_FOUND on EOF.
int tabGetStamp ( table_t t,
uint32_t stamp 
)

Return the stamp value of the table.

This operation is very cheap, the stamp value is cached on memory and no file reads are actually performed.

Parameters
tA valid table_t instance.
[out]stampValue of the stamp field of this table.
Returns
BASE_ERR_OK if stamp was read correctly.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_INVALID_PARAMETER if stamp is an invalid pointer.
int tabGoFirst ( table_t t)

Move the current entry marker to the first (zero'th) element on the table.

The generic code to iterate through an entire table, start to finish, is:

1 tabGoFirst(t);
2 while (tabGetNext(t, recp) == BASE_ERR_OK) {
3  // use the value on recp
4 }
Parameters
tA valid table_t instance.
Returns
BASE_ERR_OK on success.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if t is empty.
See also
tabGetNext()
int tabGoLast ( table_t t)

Move to the last element on the table.

The generic code to iterate an entire table, end to start, is:

1 tabGoLast(t);
2 while (tabGetPrev(t, recp) == BASE_ERR_OK) {
3  // use the value on recp
4 }
Parameters
tA valid table_t instance.
Returns
BASE_ERR_OK on success.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if t is empty.
See also
tabGetPrev()
int tabOpen ( const char *  fname,
table_t **  t 
)

Open an existing table.

Parameters
fnameFile name of the table to open.
[out]tOn success, store the handle to the open table.
Returns
BASE_ERR_OK on success.
BASE_ERR_DATA_NOT_FOUND if fname was not found.
BASE_ERR_ACCESS if cannot access the file fname.
BASE_ERR_INVALID_PARAMETER if fname or t is invalid
int tabPack ( const char *  fname)

Permanently remove from the table all entries marked as deleted.

A side-effect of this call is that the record index of all entries may change (all entries after a deleted entry will "move up").

This operation is O(n) on the number of records on the file. Each record of the file is read and copied to a new temporary table, requiring one read and two writes per record. The original file is then replaced by the temporary one.

Parameters
fnameName of table file. Should not be currently open.
Returns
BASE_ERR_OK on success.
BASE_ERR_DATA_NOT_FOUND if fname is not found.
BASE_ERR_RESOURCE_PB on errors creating the temporary table or manipulating the file system.
int tabPut ( table_t t,
int  recn,
const void *  recp 
)

Write or update an entry on the table.

This operation is O(1), but requires two writes (one for the record itself, other for the table header).

Note that this call can, exceptionally, write an entry to one past the last existing entry of the table, which is equivalent to a call to tabAppend().

Calling tabPut() for a deleted entry does not change the deleted flag for it.

Parameters
tA valid table_t instance.
recnIndex of the entry to write, in the range [0, tabSize(t)].
recpData to write to entry.
Returns
BASE_ERR_OK if record was read correctly.
BASE_ERR_INVALID_HANDLE if t is invalid.
BASE_ERR_DATA_NOT_FOUND if recn is an invalid index.
BASE_ERR_INVALID_PARAMETER if recp is invalid.
int tabRecSize ( table_t t)

Return the record size for a table.

Parameters
tA valid table_t instance.
Returns
The size of each entry on this table in bytes.
BASE_ERR_INVALID_HANDLE if t is invalid.
int tabSetStamp ( table_t t,
uint32_t  stamp 
)

Modify the stamp value of the table.

This operation does one write to the header of the table.

Parameters
tA valid table_t instance.
stampValue of the stamp field to set.
Returns
BASE_ERR_OK if stamp was read correctly.
BASE_ERR_INVALID_HANDLE if t is invalid.
int tabSize ( table_t t)

Return the total number of entries on the table.

This operation is O(1) and very quick, requiring no storage access.

Parameters
tA valid table_t instance.
Returns
The total number of entries on the file, including the ones marked as deleted.
BASE_ERR_INVALID_HANDLE if t is invalid.
int tabUnDelete ( table_t t,
int  recn 
)

Remove the deleted mark of an entry.

This operation is O(1) and requires at most two writes (one to the deleted flag of the record, another to the table header).

Parameters
tA valid table_t instance.
recnIndex of record to un-delete, in the range [0, tabSize(t) - 1].
Returns
BASE_ERR_OK if record was read correctly.
BASE_ERR_DATA_NOT_FOUND if recn is an invalid index.
BASE_ERR_INVALID_HANDLE if t is invalid.
See also
tabDelete() tabGet()
Generated on Mon Mar 27 2017 15:42:53 for LAR Library by   doxygen 1.8.9.1