Mimer SQL Documentation TOC PREV NEXT INDEX

Mimer SQL Developer Site


Real-Time Users Guide


Introduction

The Mimer SQL Real-Time API provides real-time access using a concept denoted database pointers. Database pointers are application handles that can point to data in a database. Once a database pointer is bound to one or several database values, real-time access is enabled.

There are four different kinds of database pointers:

Mimer SQL Real-Time Architecture

Mimer SQL Real-Time Architecture consists of three interacting parts, the database server, the database, and the Mimer Real-Time API as seen in the figure below:



The Mimer SQL Real-Time Architecture

The first part, the actual database, contains all data, both real-time and non real-time data. The database can be modelled the same way as any relational database. When a data element in the database is bound to a real-time database pointer, it is dynamically elevated to become real-time data, thus being swapped into main memory and made available for real-time access.

The second part, the Mimer SQL database server, contains all the non real-time database server functionality and has the same APIs and features as the standard Mimer SQL database servers. The server can be of any of the Mimer SQL database server types. The Mimer SQL database server is responsible for all non-real-time database access, database maintenance, database persistence, and to set up real-time connections and database pointers. It uses a standard client/server architecture and can be called from any application, both local and remote.

The third part, the Mimer SQL Real-Time API, contains all the real-time functionality. It is implemented as a library and is linked together with the real-time application. The API contains functions to connect and disconnect to/from the server, create, delete and use database pointers, and to perform flush operations of real-time data to persistent storage.

Since both the Mimer SQL Database Server and the Mimer SQL Real-Time API share the same database, data access synchronization is needed. In Mimer SQL Real-Time, this is automatically managed by the API and database server, such that predictable blocking of real-time operations are achieved.

The Concepts In Mimer SQL Real-Time API

The Mimer SQL Real-Time API introduces the following concepts:

The Mimer SQL Real-Time API Library

The Mimer SQL Real-Time API contains all the real-time functionality. It is dependent on the Mimer SQL database server during connect/disconnect, and during creation and deletions of database pointers. These functions are typically performed during the startup/shutdown phase of the system execution, and do not have real-time predictability.

On a high level, a typical execution-flow of a real-time application is as follows:

SYSTEM INITIALIZATION
  1. The application starts by creating a MimerRTDatabase handle for a specific real-time database server. See the section Mimer SQL Real-Time API Handles.
  2. One or several real-time database sessions are created. For this real-time database, any number of real-time database sessions can be established.
  3. A number of real-time tasks are started.
  4. Each real-time task attaches itself to the real-time database.
  5. Each task creates the database pointers it needs.
SYSTEM OPERATION
  1. Each task uses their respective database pointers to access the real-time database.
SYSTEM SHUTDOWN
  1. Each task unbinds their database pointers.
  2. Each task detaches from the database.
  3. Each task terminates.
  4. Any open real-time database sessions are closed.
  5. The real-time database handle is closed.

If soft real-time database access using SQL is needed by the application, any database access method, such as ADO.NET, ODBC, JDBC or Mimer SQL Micro C API, can be used. The Mimer SQL Real-Time API is based on the same structure of the syntax defined for the Mimer SQL Micro C API. For information on how to use these API's, see other chapters of this manual, and/or specific documentation for each API.

Summary Of The Mimer SQL Real-Time API Routines

Routines for system initialization and shutdown:

API Routine
Description
 MimerRTBeginDatabase
Creates a handle for a real-time database.
 MimerRTBeginDatabaseC
Creates a handle for a real-time database, using char interface.
 MimerRTEndDatabase
Ends a real-time database handle.
 MimerRTBeginSession
Creates a real-time session to a real-time database.
 MimerRTBeginSessionC
Creates a real-time session to a real-time database, using char interface.
 MimerRTEndSession
Ends a real-time session.
 MimerRTAttachTask
Attaches a real-time task to a real-time database.
 MimerRTDetachTask
Detaches a real-time task from a real-time database.
 MimerRTBindDbp
Submits an SQL-query to the database server, which creates a new database pointer and binds it to the data element pointed out by the query.
 MimerRTBindDbpC
Submits an SQL-query to the database server, which creates a new database pointer and binds it to the data element pointed out by the query. Uses the char interface.
 MimerRTUnbindDbp
Removes a database pointer.

Routines for real-time data access:

API Routine
Description
 MimerRTGetInt16
Reads a 16-bit integer from a database pointer.
 MimerRTSetInt16
Writes a 16-bit integer to a database pointer.
 MimerRTGetInt32
Reads a 32-bit integer from a database pointer.
 MimerRTSetInt32
Writes a 32-bit integer to a database pointer.
 MimerRTGetInt64
Reads a 64-bit integer from a database pointer.
 MimerRTSetInt64
Writes a 64-bit integer to a database pointer.
 MimerRTGetStringL
Reads a null-terminated Latin-1 character string from a database pointer.
 MimerRTSetStringL
Writes a null-terminated Latin-1 character string to a database pointer.
 MimerRTGetTimestampC
Reads a TIMESTAMP from a database pointer.
 MimerRTSetTimestampC
Writes a TIMESTAMP to a database pointer.
 MimerRTGetFloat
Reads a 32-bit floating point from a database pointer.
 MimerRTSetFloat
Writes a 32-bit floating point to a database pointer.
 MimerRTGetDouble
Reads a 64-bit floating point from a database pointer.
 MimerRTSetDouble
Writes a 64-bit floating point to a database pointer.

Routines for multirow/multicolumn data access:

API Routine
Description
 MimerRTGetMultiColumn
Reads a multicolumn database pointer from the database.
 MimerRTSetMultiColumn
Writes a multicolumn database pointer to the database.
 MimerRTSelectColumn
Selects the active column for multicolumn database pointers.
 MimerRTMoveReader
Changes record to read from for multirow log-reader.
 MimerRTMoveWriter
Changes record to write to for multirow log-reader.
 MimerRTDbpInfo
Retrieves information about a database pointer.

Routines for flushing of real-time data to persistent storage:

API Routine
Description
 MimerRTFlushDbp
Flushes a multirow database pointer to persistent storage.
 MimerRTFlushAll
Flushes all database pointers to persistent storage.

Data Types

Currently, the Mimer SQL Real-Time API supports the following C data types (C99) for real-time access:

SQL data type
C data type
Description
 SMALLINT
int16_t
A 16-bit integer.
 INTEGER
int32_t
A 32-bit integer.
 BIGINT
int64_t
A 64-bit integer.
 CHAR(n)
char[n]
A null terminated character-string of maximum length n.
 TIMESTAMP
char[]
A timestamp of format YYYY-MM-DD HH:MM:SS[.nnnnnn].
 REAL
float
A 32-bit floating point.
 FLOAT
double
A 64-bit floating point.

Mimer SQL Real-Time API Handles

The Mimer SQL Real-Time API consists of a set of handles used to connect to a database, and to create and use database pointers. The following handles are used:

In addition to these handles a real-time task must be attached to a specific real-time database server before any database pointer operations are allowed.

These handles have the following interrelationship:



Relationship of handles in Mimer SQL Real-Time API

As can be seen in the figure, the MimerRTDatabase is the top entity in the Mimer SQL Real-Time API.

When calling the MimerRTBeginDatabase, or MimerRTBeginDatabaseC, the client prepares the control structures for the real-time database server. These control structures manage real-time data access and synchronization. Each client can only create one MimerRTDatabase object, i.e. creating multiple MimerRTDatabase handles to the same or different databases are not possible.

Several real-time database sessions can be created under the real-time database, using the MimerRTBeginSession, or MimerRTBeginSessionC, call. Multiple real-time tasks can share a single real-time database session handle. When a session is set up, the application logs into the database server with a username and a password.

Before a real-time task can use a database pointer it needs to attach itself to the real-time database using the MimerRTAttachTask call. When a task is attached to a real-time database, it is granted real-time access to that real-time database and is attached to the internal real-time synchronization mechanisms.

Any task that is attached to a certain real-time database can use a real-time database session to create database pointers, using the MimerRTBindDbp, or MimerRTBindDbpC, API call. Multiple real-time tasks can share a single real-time session handle, and multiple real-time sessions can be created for a specific real-time database. It is however worth noting that as soon as a real-time database session is ended, all database pointers under it are dropped. Real-time sessions are ended using the MimerRTEndSession API call.

Please note that even though a database pointer can be shared by multiple tasks, it is not recommended, and can lead to unpredictable results.

Using One Or More Real-Time Database Sessions

In many real-time applications the available resources are limited, therefore the Mimer SQL Real-Time API is designed to use as little resources as possible. By allowing multiple tasks to share a session, the memory overhead for managing several sessions is removed. Sharing a database session has no impact at all on the predictability or performance of real-time operations like the get and set operations (for example, MimerRTGetInt32 and MimerRTSetInt32). If performance during startup or shutdown of the system is critical, using multiple database sessions might increase performance. However, the main reason for using multiple real-time database sessions is if one or more tasks require a different login to the database, for example to access sensitive data.

For applications where multiple, or all, tasks share a common real-time database session, Mimer SQL Real-Time API usage can be set up as follows:

For applications where all tasks within a real-time database uses additional real-time database sessions, Mimer SQL Real-Time API usage can be set up as follows:

Preparing And Optimizing The Database Server For Real-Time Use

In large, Mimer SQL Real-Time is designed so that real-time data and non real-time data can be modelled in the same database, and that data automatically becomes real-time data when used by real-time database pointers. While this is true, there are still some preparations and optimizations that can be performed on the server in order to optimize performance.

Turning Off Compression and Settting Fixed Table Format for Real-Time Data

For non-real-time data the Mimer SQL database server compresses data to reduce disk and memory usage. However, real-time data must not be compressed. This is partly due to that compression is a source of real-time unpredictably, and partly because that real-time data needs to be stored in a fixed position in memory. Using compression algorithms can result in that the exact location of a data element changes when data are decompressed. Similarly, non-real-time data are stored in tables with a variable table format, but real-time data must be stored in fixed format tables.

This means that all tables that contains real-time data must have its compression turned off and a fixed table format. This is performed using the following SQL statement:

 ALTER TABLE tablename SET COMPRESS OFF, FORMAT FIXED;
 

For example:

 CREATE TABLE rttable (pk INTEGER PRIMARY KEY, rtval INTEGER);
 ALTER TABLE rttable SET COMPRESS OFF, FORMAT FIXED;

Database Server Real-Time Data Resources

The Mimer SQL Real-Time server uses internal resources to manage database pointers and real-time tasks. When building a real-time application it is necessary to dimension the allocation of these resources to accommodate all database pointers and real-time tasks.

Win: The dimensioning of these resources is performed on the "Real-Time" tab in the server properties located in the Mimer Administrator tool.
UNIX: The dimensioning of these resources is performed in the multidefs file. The parameters called RealTimeElements and RealTimeThreads are defined as follows by default (Please note that currently on Linux, the Real-Time Threads parameter is not applicable since it by default is set to 'unlimited'):
 RealTimeElements   10000    # Max # of real-time data elements (4-10000000)
 RealTimeThreads    100      # Max # of client real-time threads (0-10000)
 

The following describes these resources more in detail:

For an exact description of how many server real-time elements that are used, the miminfo tool can be used. For more information about the real-time reports in miminfo see Using The MIMINFO Tool To Obtain Real-Time System Reports.

Optimizing The Database For Real-Time Performance

When a database pointer is bound to a data value, the data value is transformed into a real-time data value. This means that the following happens:

To reduce use of primary memory it might be beneficial to store database pointers that are related to each other in the same table. Scattering real-time data in many different tables might lead to many pages containing few or even single real-time data values. If this is unavoidable it might be preferable to locate these tables in small pages. The Mimer SQL Real-Time server supports three different page sizes,; 4 kb, 32 kb and 128 kb. To assign a certain page size to a table, the ALTER TABLE statement is used:

 ALTER TABLE tablename SET DATA PAGESIZE [ 4 | 32 | 128] K;
 

For example, the following code creates a table and allocates it in 4 kb pages:

 CREATE TABLE rttable (pk INTEGER PRIMARY KEY, rtval INTEGER);
 ALTER TABLE rttable SET DATA PAGESIZE 4 K;
 

For tables that are intended to store multirow database pointers, such as eventlog tables, setting an appropriate page size might influence flush performance, for information about flush, see Flushing of Real-Time Data.

For multirow database pointers where only few updates occurs between each flush are expected, selecting a smaller page size might improve flush performance, since the disk I/O will be of a smaller size. However, setting a small pagesize for a very large table increases the number of used server real-time elements.

For multirow database pointers where flushes occur seldom, maybe only at system shut down, and where flush performance is critical, selecting a large pagesize will result in fewer disk I/O, thus improving performance.

Real-Time Programming Examples

This section shows and explains a number of examples of how the Mimer SQL Real-Time API is used. In the examples, a generic notation of tasks is used. A task is a real-time operating system's equivalence to a thread. In any real implementation of these examples, the generic task notation is exchanged with actual task/thread model of the operating system.

The following schema is used in the following examples:

 create table RT_TABLE (
     SUBSYSTEM char(20) primary key,
     TEMP integer,
     HEATEFF integer);
 
 alter table RT_TABLE set compress off, format fixed;
 
 insert into RT_TABLE values('Probe1',24,null);
 insert into RT_TABLE values('Probe2',96,null);
Creating a real-time database for a database server

The following example shows how to begin and end a real-time database handle:

 #include "mimrtapi.h"
 
 // Handle to the real-time database
 
 MimerRTDatabase hrtdb;
 
 int32_t main(void) {
     int32_t err = 0;
 
     err = MimerRTBeginDatabase(L"SERVERNAME", 5, &hrtdb);
     if (err) {
         // Error creating database
         return err;
     }
 
     err = MimerRTEndDatabase(&hrtdb);
     if (err) {
         // Error ending database
         return err;
     }
 
 ...
 

In the above example, a real-time database handle for server SERVERNAME was created. The real-time database was dimensioned to handle five tasks.

Creating a session to the database server

The example shows how the real-time application connects to and disconnects from the Mimer SQL database server:

 #include "mimrtapi.h"
 
 MimerRTDatabase hrtdb;
 MimerRTSession hrtsess;
 
 // Assumes that the real-time database handle is created 
 
 int32_t task(void) {
     int32_t err = 0;
 
     err = MimerRTBeginSession(&hrtdb, L"SYSADM", L"passw", hrtsess);
     if (err) {
         // Error connecting to database (wrong credentials?)
         return err;
     }
 
     //Successfully connected, run RT-application
 
     err = MimerRTEndSession(&hrtsess);
     if (err) {
         // Error disconnecting to database
         return err;
     }
 
     // Successfully disconnected, terminate
     return 1;
 }
 

In this example, the real-time application connects to and disconnects from the server. The connect is normally performed in the initialization phase of the application. The disconnect is normally performed prior to shutting down the application.

The MimerRTBeginSession routine will establish a connection to the server. As input parameters it takes a server session handle, a real-time database handle, a database ident, and a password. Similarly, the MimerRTEndSession will end the connection to the server.

Binding and deleting a database pointer

The example below shows how to create a database pointer, binding it to a specified data element and finally deleting it.

 #include "mimrtapi.h"
 
 MimerRTDatabase hrtdb;
 MimerRTSession hrtsess;
 
 // Assumes that the real-time database and session are created
 
 TASK ioTask(void) {
     int32_t err = 0;
     MimerRTDbp dbp;
 
     // Attaching task to the real-time database
 
     err = MimerRTAttachTask(hrtdb);
     if (err) {
         // Error initializing task;
         return err;
     }
 
     rr = MimerRTBindDbp(hrtsess,
                     L"Select TEMP from RT_TABLE where SUBSYSTEM = 'Probe1'",
                     DBP_DEFAULT,
                     &dbp);
     if (err) {
         // Error binding the database pointer (invalid query??);
         return err;
     }
 
     // Successfully bound the database pointer
 
     while(!SHUTDOWN_SYSTEM) {
         // Task control loop
     }
 
     // Deleting the database pointer
 
     err = MimerRTUnbindDbp(&dbp);
     if (err) {
         // Error deleting pointer
         return err;
     }
 
     // Detaching task from the real-time database
 
     err = MimerRTDetachTask(hrtdb);
     if (err) {
         // Error detaching task
         return err;
     }
 
     // Assuming shutdown of database connection (see previous examples)
 }
 ...
 

In this example, the task attaches itself to the real-time database using the MimerRTAttachTask call. The real-time application then binds the MimerRTDbp database pointer dbp to the TEMPERATURE of Probe1 residing in the relation RT_TABLE. It is assumed that the real-time application already is connected to the server using the MimerRTBeginSession routine.

Note: The MimerRTBindDbp routine is capable of taking any SELECT statement or precompiled statement as long as the following criteria are met:

When the task is being shutdown, the MimerRTUnbindDbp routine is called. This routine de-allocates the database pointer, both locally and in the database server.

The last step of the task is to detach itself from the real-time database, this is performed using the MimerRTDetachTask routine.

A real-time task performing temperature control

In the example below, a real-time task is regulating a temperature using database pointers.

 #include "mimrtapi.h"
 
 MimerRTDatabase hrtdb;
 MimerRTSession hrtsess;
 
 // Assumes that the real-time database and session are created
 
 TASK tempReg(void) {
     int32_t err = 0;
     int32_t temperature, heaterEffect;
     MimerRTDbp tempDbp;
     MimerRTDbp heaterDbp;
 
     // Assuming that main function has started database session
     // Attach Task
 
     // Binding tempDbp to "Select TEMP from RT_TABLE where SUBSYSTEM='Probe1';
     // Binding heaterDbp to "Select HEATEFF from RT_TABLE where 
SUBSYSTEM='Probe1';
 
     while(!SHUTDOWN_SYSTEM) {
         // Retrieve the current temperature
 
         err = MimerRTGetInt32(tempDbp, &temperature);
         if (err) {
             return err;
         }
 
         // Execute the regulation algorithm
 
         heaterEffect = tempPID(temperature);
 
         // Write the new actuator-value
 
         err = MimerRTSetInt32(heaterDbp, heaterEffect);
         if (err) {
             return err;
         }
 
         waitForNextPeriod();
     }
     // Deleting tempDbp & heaterDbp
     // Detach Task
 }
 

In this example, a task containing an initialization part and a control part, controls a temperature using a heater. In the initialization part, two database pointers are bound to their respective data elements. Finally, in the control part, the temperature is periodically scanned using the MimerRTGetInt32 function, and the calculated actuator-value is written back to the database using the MimerRTSetInt32 function.

Multicolumn Database Pointers

So far database pointers accessing single individual data elements in the database have been covered. These database pointers are referred to as single column database pointers. Mimer SQL Real-Time also supports multicolumn database pointers. These pointers can bind more than one column in a record. These data values can then be read or updated either individually or as a group. All multicolumn database pointer accesses are atomic, which means that even if multiple columns are updated, this is performed as one atomic transaction. During the update of individual data elements in the multicolumn set, the values are cached in the local storage for the database pointer. The following figure shows the relationship between the local cache of the database pointer and the data in the database.



The local cache of a multicolumn database pointer

As can be seen in the figure, multicolumn database pointers use the same API as single column database pointers, but as opposed to singlecolumn pointers, these calls updates the local cache of the multirow database pointer instead of the database. Instead, the data is atomically read and written using the MimerRTGetMultiColumn and MimerRTSetMultiColumn API calls.

The multicolumn property needs to be explicitly stated during the bind operation using the DBP_MULTICOLUMN flag. Submitting a bind query that includes multiple columns while omitting this flag will result in an error. See MimerRTBindDbp.

Note: Even though it is valid to include the same column more than once in a multicolumn set, updating one or more instances of the column might yield undefined results.
Multicolumn database pointer write example

The following schema is used in the examples below:

 create table RT_MULTICOLTABLE (
     SUBSYSTEM char(20) primary key,
     TS timestamp,
     TEMP integer,
     PRESSURE integer);
  
 alter table RT_MULTICOLTABLE set compress off, format fixed;
 
 insert into RT_MULTICOLTABLE values('Oil',
                                      timestamp'2008-01-01 01:00:00.000001',
                                      24,4);
  insert into RT_MULTICOLTABLE values('Water,
                                      'timestamp'2008-01-01 01:00:00.000002',
                                      96,10);
 

In the following code, error handling has been omitted for readability purposes:

 TASK multicolWriter(void) {
     int32_t temperature, pressure;
     MimerRTDbp dbp;
 
     // Assumes that the real-time database and session are created
     // Attach Task
 
     MimerRTBindDbp(hrtsess,
     L"Select TS,TEMP,PRESSURE from RT_MULTICOLTABLE where SUBSYSTEM = 'Oil'",
         DBP_MULTICOLUMN,
         &dbp);
 
     while(!SHUTDOWN_SYSTEM) {
         temperature = readTempSensor();
         pressure = readPressureSensor();
 
         // Writing values to database pointer local storage
 
         MimerRTSetTimestamp(dbp, getCurrentTime());
         MimerRTSetInt32(dbp, temperature);
         MimerRTSetInt32(dbp, pressure);
 
         // Writing database pointer to the database
 
         MimerRTSetMultiColumn(dbp);
         waitForNextPeriod();
     }
 
     // Deleting dbp
     // Detach Task
 }
 

Multicolumn Database Pointer READ example

 TASK multicolReader(void) {
     int32_t temperature, pressure;
     char[40] time;
     MimerRTDbp dbp;
 
     // Assumes that the real-time database and session are created
     // Attach Task
 
     MimerRTBindDbp(hrtsess,
     L"Select TS,TEMP,PRESSURE from RT_MULTICOLTABLE where SUBSYSTEM = 'Oil'",
         DBP_MULTICOLUMN,
         &dbp);
 
     while(!SHUTDOWN_SYSTEM) {
 
         // Reading database pointer from the database
 
         MimerRTGetMultiColumn(dbp);
 
         // Reading values from the database pointer local storage
 
         MimerRTGetTimestampC(dbp, time);
         MimerRTGetInt32(dbp, &temperature);
         MimerRTGetInt32(dbp, &pressure);
 
         // Do some processing
 
         waitForNextPeriod();
     }
 
     // Deleting dbp
     // Detach Task
 }
 

The Active Column For Multicolumn Database Pointers

The multicolumn database pointer uses the notion of an active column when referring to which column in the multicolumn set that is currently selected for reading or writing (in the database pointers local storage). This mechanism is here described further.

Multicolumn database pointers are optimized for reading and writing the column in the local storage in sequential order as defined by the bind operation. Therefore it is, performance-wise, beneficial to enter a bind query that specifies the columns in the order they are intended to be used.

When a read or a write of a column in a multicolumn database pointer occurs, the active column will automatically set the next column as active. However, the API function MimerRTSelectColumn allows the user to change the active column, see the Real-Time API Specification for more information.

Multirow Database Pointers

Multirow database pointers are used to access data elements in one or more records (rows) of a table. Any number of records in a table can be selected. Data access is performed in a circular fashion, making a multirow database behave like a circular buffer where logs and streams of data can be stored and retrieved.

Multirow database pointers use the same API as singlerow and multicolumn database with the addition of the MimerRTMoveReader routine which is used to either reset the reader to the last written record, first record in the set or to move the reader backwards or forward in the multirow set. Note that this routine is used to move the reader while the writer(s) always writes in sequential order.

The multirow property needs to be explicitly stated during the bind operation using the DBP_MULTIROW flag while binding the pointer. Submitting a bind query that includes multiple rows while omitting this flag will result in an error.

Just as for any database pointer, multirow database pointers cannot be bound to the primary key of the relation.

There are two distinctly different versions of the multirow database pointer, the logging pointer and the static pointer.

Multirow Logging Database Pointers

The multirow logging database pointer is the semantically less restricted form of the multirow pointer. It emphasizes non-blocking execution before data persistence and consistency, and is suited for systems where the latest events of some kind are logged for viewing.

The semantics of the multirow logging database pointer are as follows:

Multirow Static Database Pointers

The multirow static database pointer is used in systems were you do not want readers and writers to automatically move to the next row after each operation. This functionality is useful if you have writers that continuously should update specific rows, or readers that should continuously read specific rows. For a multirow static database pointer, the individual reader position and the writer position is always the same.

When a multirow static database pointer is created, the writer/reader position is set to the first row in the set. The reader/writer position is then moved to the correct row by using the MimerRTMoveReader API call.

Multirow example

The following schema is used in the examples below:

 create table RT_EVENTTABLE (
     PK integer primary key,
     EVENTTIME timestamp,
     EVENT integer,
     EVENTVALUE integer,
     EVENTDESCR char(30));
 
 alter table RT_EVENTTABLE set compress off, format fixed;
 
 insert into RT_EVENTTABLE values(1,null,null,null,null);
 insert into RT_EVENTTABLE values(2,null,null,null,null);
 ...
 insert into RT_EVENTTABLE values(50,null,null,null,null);
 

In this example, a multirow/multicolumn logging database pointer is created, which is used to enter events to the database:

 TASK eventWriter(void) {
     int32_t event, eventValue;
     char eventDescr[30];
     MimerRTDbp dbpWrite;
 
     // Assuming that main function has started database session
     // Attach Task
 
     MimerRTBindDbp(hrtsess,
       L"Select EVENTTIME, EVENT, EVENTVALUE, EVENTDESCR from RT_EVENTTABLE",
       DBP_MULTIROW|DBP_MULTICOLUMN|DBP_LOGGINGPOLICY,
       &dbpWrite);
 
     while(!SHUTDOWN_SYSTEM) {
         WaitForEvent(&event, &eventValue, eventDescr);
 
         // Writing values to database pointer local storage
 
         MimerRTSetTimestampC(dbpWrite, getCurrentTime());
         MimerRTSetInt32(dbpWrite, event);
         MimerRTSetInt32(dbpWrite, eventValue);
         MimerRTSetStringL(dbpWrite, eventDescr);
 
         // Writing database pointer to the database
 
         MimerRTSetMultiColumn(dbpWrite);
     }
 
     // Deleting dbpWrite
     // Detach Task
 }
 

In this example, an event-reader reads the last 10 events:

 TASK eventReader(void) {
     int16_t i;
     int32_t event, eventValue;
     char eventDescr[30], timestamp[30];
     MimerRTDbp dbpRead;
 
     // Assuming that main function has started database session
     // Attach Task
 
     MimerRTBindDbp(hrtsess,
       L"Select EVENTTIME, EVENT, EVENTVALUE, EVENTDESCR from RT_EVENTTABLE",
       DBP_MULTIROW|DBP_MULTICOLUMN|DBP_LOGGINGPOLICY|DBP_BACKWARDSREADER,
       &dbpRead);
 
     while(!SHUTDOWN_SYSTEM){
                
         // Resetting the reader to point at the last written row
 
         MimerRTMoveReader(dbpRead, MOVEROW_LASTWRITTEN, 0);
 
         for(i = 0; i < 10; i++) {
             // Reading database pointer to the database
 
             MimerRTGetMultiColumn(dbpRead);
 
             // Reading values from database pointer local storage
 
             MimerRTGetTimestampC(dbpRead, timestamp);
             MimerRTSetInt32(dbpRead, &event);
             MimerRTSetInt32(dbpRead, &eventValue);
             MimerRTSetStringL(dbpRead, eventDescr);
 
             // Do some event processing here
         }
         WaitForNextPeriod();
     }
 
     // Deleting dbpRead
     // Detach Task
 }
 

Flushing of Real-Time Data

Since I/O operations to persistent storage (hard drive, flash-memory, etc.) often include unpredictable behavior, such as unknown response times, all real-time data in a Mimer SQL Real-Time database is stored in main memory. As soon as a database pointer is bound to a database value, the page which the value resides in is read to RAM and prohibited to be swapped out. When all database pointers to a certain page has been deleted, the page will automatically be flushed back to persistent storage.

However, in some cases, there is a need to manually flush real-time data to persistent storage during real-time operation. Mimer SQL Real-Time API allows you to perform such operations using the MimerRTFlushDbp and MimerRTFlushAll operations. The MimerRTFlushDbp operation flushes one multirow database pointer to persistent storage, while the MimerRTFlushAll flushes all real-time data.

It is worth noting that the MimerRTFlushAll flushes all real-time data in a database server, including data bound by other sessions and applications.

When a flush of real-time data is performed, the predictability of other real-time operations (i.e. all read and write operations) are not affected. The flush operation first creates a snapshot copy of the bufferpool page that the data resides in, and then uses that copy for the flush. During the I/O operation, all other real-time operations continue to use the original copy. It is worth noting that it is the database server which performs the flush, meaning that the real-time application calls the server and requests the flush to be performed.

In order for a user to perform a flush operation, sufficient privileges are needed. The MimerRTFlushDbp and MimerRTFlushAll require any of the following privileges:

Using The MIMINFO Tool To Obtain Real-Time System Reports

Mimer SQL Real-Time provides a tool, called miminfo, that can be used to obtain various reports on a running server. For a full documentation of miminfo, see the Mimer SQL System Management Handbook.

This section will discuss the real-time related reports that can be obtained.

Win: The Miminfo tool is found in the Mimer SQL Real-Time program folder on the Start menu.
To obtain the real-time report, simply click the "Real-Time Info" icon in the toolbar, or select Realtime in the View menu.
UNIX: When using the miminfo tool to obtain the real-time report, one of the -r or --realtime switches should be used:
 # miminfo -r
 # miminfo --realtime
 

An example of the real-time report is shown below:

 M I M E R / M I M I N F O
 Version 11.0.0A Aug 13 2017
 
 Mimer SQL real-time report
 ==========================
 No. of bound client single-row pointers   :          0
 No. of bound client multi-row pointers    :          1
 
 No. of single-row real-time elements      :          0
 No. of multi-row real-time elements       :          1
 No. of administration real-time elements  :          4
 Total no. of server real-time elements    :          5
 Max no. of server real-time elements      :      10000
 No. of allocated real-time tasks          :          0
 Max no. of real-time tasks                :        100
 Username        Channel   RT pointers
 ============ ==========   ===========
 RTTEST          4866052             1
 
 Total of 1 RTAPI session

Mimer
Mimer Information Technology AB
Voice: +46 18 780 92 00
Fax: +46 18 780 92 40
info@mimer.se
Mimer SQL Documentation TOC PREV NEXT INDEX