Overview
The thin client (IoT edge client) is intended for resource-constrained devices that do not have sufficient memory to host the full eXtremeDB runtime. It integrates these small data collection points with the eXtremeDB Active Replication Fabric architecture. Applications are not linked with the eXtremeDB core runtime libraries; instead, they rely on a lightweight edge client library.
The client implementation is intentionally simple. It allows data to be inserted into a local "database" (the edge database) using a native eXtremeDB API similar to that of the main database, and then offloads this data from the device by sending it to a main eXtremeDB instance. Internally, the edge database is organized as a ring buffer: user transactions append data sequentially at the head of the buffer, while the
mco_edge_sync()function transmits data to the main eXtremeDB instance and, upon receiving acknowledgments, advances the tail, freeing space for new data and transactions.A minimal working application can run with a buffer size of 1 KB, a code size (for example, the
.textsection) of about 8 KB, and a maximum stack usage of 512 bytes.Unlike a non-edge client applications that must be built with the exact same transaction manager, and architecture as the server or gateway it connects to, the edge client automatically adapts to the main instance configuration at runtime . That includes:
- Transaction manager (MURSIW / MVCC)
- Architecture (x32 / x64)
- Page size
- Endianness (big / little endian)
This allows a single edge application to create multiple edge database instances targeting different server configurations. For example, one edge instance may send data to an x32 + MURSIW + page size = 256 server, while another targets an x64 + MVCC + page size = 512 server.
Programming Edge Client Applications
Schema
The edge client database schema is described using the familiar eXtremeDB Data Definition Language (DDL). The schema for an edge application is similar to a standard schema and is processed by the mcocomp schema compiler. Some restrictions apply:
- The schema must begin with an iot edge declaration. Similar to the regular device/client, each device must have a unique agent ID. The edge client ID can be set either in the schema or at runtime via parameters-whatever is more convenient. If the ID is defined in the schema it can can be overridden at runtime.
- All classes must use the uptable modifier. Other modifiers (persistent, local, distributed, compact, atomic, nonatomic, downtable, and transient) are not supported.
- All classes must be fixed-size. Variable-length fields such as string, nstring, sequences, vector<TYPE>, and blob are not allowed. Arrays and structures, including nested ones, are allowed.
- Classes cannot have indexes, including list, autoid, oid, and auto_oid.
- The following features are also not supported: events, initial values, direct structs, TTL, calculators, and XML/JSON method generation.
The schema example below illustrates the concept:
declare database mindb; iot edge 1000; uptable class Sensor { unsigned<4> sensor_id; unsigned<4> controller_id; unsigned<8> ts; double value; };When subsequently processed by the DDL compiler, the familiar database access API-consisting of _new(), _put(), and _get() methods-is generated. This API can be used by the edge client-based application to insert data into the local database:
MCO_RET Sensor_new ( mco_trans_h t, /*OUT*/ Sensor *handle ); MCO_RET Sensor_sensor_id_get ( Sensor *handle, /*OUT*/ mco_uint4 *result ); MCO_RET Sensor_sensor_id_put ( Sensor *handle, mco_uint4 value ); MCO_RET Sensor_controller_id_get ( Sensor *handle, /*OUT*/ mco_uint4 *result ); MCO_RET Sensor_controller_id_put ( Sensor *handle, mco_uint4 value ); MCO_RET Sensor_ts_get ( Sensor *handle, /*OUT*/ mco_uint8 *result ); MCO_RET Sensor_ts_put ( Sensor *handle, mco_uint8 value ); MCO_RET Sensor_value_get ( Sensor *handle, /*OUT*/ double *result ); MCO_RET Sensor_value_put ( Sensor *handle, double value ); MCO_RET Sensor_fixed_get ( Sensor *handle_, Sensor_fixed *dst_ ); MCO_RET Sensor_fixed_put ( Sensor *handle_, const Sensor_fixed *src_ );
For more details on the available functions and usage patterns, see the Edge Database API documentation.