Data Model¶
Introduction¶
The Data Model component provides a lightweight, in-memory, indexed key/value store with change-tracking (dirty flags) and simple accessors. It is designed for embedded systems that need a compact representation of a set of typed data points, efficient reads/writes, and a mechanism to detect which values have changed so they can be synchronized or published by other subsystems.
Important: The Data Model does not provide event notification or callback
mechanisms when data changes. It only marks data points as dirty. If your
system requires active notifications or pub/sub behaviour you should compose
the data model with the Event Bus component (see
easy_embedded/service/event_bus/event_bus.rst) or another notification
mechanism to publish changes.
This document describes the component’s structure, runtime behaviour,
data flow, and the public data types and API. The primary implementation can
be found in the ez_data_model.h / ez_data_model.c pair and exposes functions
such as ezDataModel_Initialize, ezDataModel_SetDataPoint,
ezDataModel_GetDataPoint, ezDataModel_GetFirstDirty,
ezDataModel_ClearDirtyFlags, and ezDataModel_ClearAllDirtyFlags.
Component’s structure¶
The Data Model is composed of three logical parts:
A statically-provided array of
ezDataPoint_tentries that define the index and size of each data point.A contiguous memory buffer used to store the actual data bytes for all data points (the data model buffer).
The ezDataModel_t descriptor which references the array and buffer and provides helper operations.
classDiagram
class ezDataModel_t {
+ezDataPoint_t[] data_points
+DataBuffer data_model_buff
+size_t num_of_data_points
}
class ezDataPoint_t {
+uint32_t index
+size_t size
+void* data
+bool isDirty
}
class DataBuffer {
+uint8_t[] bytes
+size_t size
}
ezDataModel_t o-- ezDataPoint_t : manages
ezDataModel_t *-- DataBuffer : contains
Component’s behavior¶
External behaviour¶
Initialization: The application allocates an array of
ezDataPoint_t(each describing an index and size) and a contiguous buffer. It callsezDataModel_Initializepassing the ezDataModel_t descriptor, the points array, and the buffer. The initializer partitions the buffer and assigns each point’sdatapointer into that buffer.Setting values:
ezDataModel_SetDataPointcopies the caller’s bytes into the pre-assigned buffer area for the specified index and marks the pointisDirty = true.Reading values:
ezDataModel_GetDataPointreturns a pointer to the stored bytes and the data size. No copy is performed on read.Dirty scanning:
ezDataModel_GetFirstDirtyscans the points and returns the index of the first point withisDirty == true(orDATA_POINT_INVALIDwhen none are dirty).Clearing flags: The application can clear a single point’s dirty flag with
ezDataModel_ClearDirtyFlagsor clear all flags withezDataModel_ClearAllDirtyFlags.
Internal behaviour¶
Allocation: During initialization the component walks the provided
ezDataPoint_tarray and assigns regions of the contiguous buffer to each point in order; it asserts on size/ordering violations and ensures the buffer is large enough.Lookup: Data points are stored in index-sorted order and lookups use a binary search (see
ezDataModel_FindDataPointByIndex) to locate a point by index. This gives O(log N) lookup performance for reads/writes.Concurrency: The component is intentionally minimal and does not provide locking; the caller must ensure mutual exclusion if the data model is accessed from concurrent contexts.
Component invariants and failure modes¶
The
ezDataPoint_tarray must be sorted byindexand each entry must have a non-zerosize. Initialization asserts these invariants.If the buffer is too small for the provided points, initialization fails (assertion) and the data model must not be used.
Data Flow¶
The typical data flow is: the application writes into a data point, the data point is marked dirty, a synchronizer or publisher scans the data model for dirty points and reads their bytes to send or persist them, then clears the dirty flags.
flowchart LR
AppWrite[Application Write] -->|ezDataModel_SetDataPoint| DM[(Data Model Buffer)]
DM -->|isDirty=true| DirtyList[Dirty Scan]
DirtyList -->|ezDataModel_GetDataPoint| Publisher[Publisher / Sync]
Publisher -->|ezDataModel_ClearDirtyFlags| DM
Component’s data type¶
Key types defined by the component:
ezDataPoint_t: describes a single data point with the fields: -index: numeric identifier for the data point. -size: number of bytes allocated for the value. -data: pointer into the data model buffer where the bytes reside. -isDirty: boolean flag indicating whether the point has changed.ezDataModel_t: container struct holding: - the pointer to theezDataPoint_tarray, - the number of entries, - the contiguous buffer pointer and its size.Constants and APIs: -
DATA_POINT_INVALID: returned byezDataModel_GetFirstDirtywhenno dirty points are found.
Public API functions:
ezDataModel_Initialize,ezDataModel_SetDataPoint,ezDataModel_GetDataPoint,ezDataModel_GetFirstDirty,ezDataModel_ClearDirtyFlags, andezDataModel_ClearAllDirtyFlags.
Implementation notes¶
The design favors a static, deterministic memory layout (no dynamic allocations at runtime) and predictable lookup time via binary search.
The component intentionally keeps semantics simple so it can be composed with other services such as an event bus or a synchronizer that reacts to dirty data points.
See also: easy_embedded/service/data_model/ez_data_model.h and
easy_embedded/service/data_model/ez_data_model.c for API and implementation
details.