User Guide Persistence Client Library
User Guide Persistence Client Library
1. Introduction ....................................................................................... 1
1.1 Purpose........................................................................................................................................... 1
1.2 Revision History .............................................................................................................................. 1
1.3 Abbreviations & Terminology .......................................................................................................... 3
2. Persistence ........................................................................................ 4
2.1 Persistence Subsystem .................................................................................................................. 4
2.1.1 Persistence Components in System Context ........................................................................ 5
2.1.2 Persistence Components Overview ...................................................................................... 5
2.2 Persistence Client Library ............................................................................................................... 6
2.2.1 Responsibilities ..................................................................................................................... 6
2.2.2 Dependencies ....................................................................................................................... 6
2.2.3 Persistence Client Library License ........................................................................................ 6
2.2.4 Persistence Client Library Project Information ...................................................................... 6
Figures
1.1 Purpose
The scope of this document covers interface description, building the library, component testing and debugging.
The document covers also some basic persistence concepts used to implement Persistence Client Library.
2.2.1 Responsibilities
The responsibility of the Persistence Client library is:
Shared data management
Persistent data may be accessed by different applications
Local data management
Persistent data is accessible only by the "owned" application
Specific data management
Concept can be extended for custom solution for early, secure, factory settings a.s.o storages /
databases
Local and shared file management
Data can be stored in a file. The file can be accessed by different applications or only the "owned"
application
2.2.2 Dependencies
In order to provide more flexibility the storage mechanism for persistence data has been moved into a separate
component called Persistence Common Object.
Persistence Administration Service also uses this component to access persistent data.
• mnt-c
– cached file system partition
• mnt-wt
– write-through partition
• mnt-backup
– backup partition
• Green
– RCT
• Read-only/ read/write
• Access rights
• Storage (local/shared)
• Resource type (key/file)
• Blue
– Application user data
– Default data
– Configurable default data
• Magenta
– Links to shared application data
• Yellow
– Backup information
• Create backup
• Don‘t create backup
If an application needs access to the data shared by app1 in the sub group1 then this application needs to be
added to the specific group app1gp1.
The logical database ID is the resolution of the name of the group over the system.
Note:
The setup of users and running the different applications with a special is in the responsibility of the using
project.
PCL and/or PAS are not creating any user in the system.
To enhance access control also mandatory access control (e.g. SMACK) can be used.
When an application tries to read/write a resource the RCT is always invoked as it is described in the following
sequence:
Application wants to write data
o Query the resource table
o RCT contains information about the requested resource
Check configuration
key-value or file
Size does not exceed configured max size
correct permission (write to a read-only resource)
If the configuration matches, write data to configured location
o RCT does NOT contain information about the requested resource
Create entry about the resource in the RCT
Configure it as a local cached resource
write data
If there is no information about the requested resource, an application will nevertheless able to store this data
with the restriction that the resource will be stored in the local cached path.
Note:
Only the persistence administration service or the responsible application is allowed to change the resource
configuration table.
Persistence Client API Persistence lib (from client resource data base "input" Comment
table)
0xFF, "/pos/last pos", 0, 0 "/Data/mnt-c/Appl-1/cached.itz" "/Node/pos/last pos" local value (last
position)
0x84, "/links/last link", 2, 0 "/Data/mnt-wt/Appl-2/wt.itz" "/84/User/2/links/last link" local value (last link)
The resolution from the given API parameters to the key-value data or the file is done in done the following way:
The lbid parameter gives a hint which resource configuration table (RCT) to use
o First the RCT in the cached path will be queried
o If the resource can be found in the RCT the storage policy will be queried
o If storage policy is cached use the database in the cached path otherwise in the write through
path.
o 0xFFFF application local data, use the RCT in the application folder
o 0x0 public data, use RCT in the shared folder
o E.g. group 20 use the RCT in the group folder of group 20
Then the input "key" to the database will be generated using resourceId, user_no and seat_no
o User 0 and seat 0 ? it is NODE data ? input string is /Node/resourceID
o User 3 and seat 2 ?it is USER data bound to a SEAT? /User/3/Seat2/resourceID
pclInitLibrary("Navigation", shutdownReg);
/**
* Logical DB ID: 0xFF with user 1 and seat 1
* ==> local value accessible by all users (user 1, seat 1)
*/
ret = pclKeyReadData(0xFF, "pos/last_position", 1, 1, buffer, READ_SIZE);
memset(buffer, 0, READ_SIZE);
/**
* Logical DB ID: 0xFF with user 0 and seat 0
* ==> local value accessible by all users (user 1, seat 1)
*/
ret = pclKeyReadData(0xFF, "language/country_code", 1, 1, buffer, READ_SIZE);
/**
* Logical DB ID: 0x84 with user 2 and seat 1
* ==> shared user value accessible by A GROUP (user 2 and seat 1)
*
* ==> used for shared testing
*/
ret = pclKeyWriteData(0x84, "links/last_link2", 2, 1, (unsigned char*)"Test
notify shared data", strlen("Test notify shared data"));
pclDeinitLibrary();
Then provided unit tests located under tests/ persistence_client_library_test.c is also a good code reference how
to use the API.
return 1;
}
…
// Registration works only on group or public data
ret = pclKeyRegisterNotifyOnChange(0x20, "links/last_link2", 2/*user_no*/,
1/*seat_no*/, &myChangeCallback);
Sender Side:
During system runtime all modified persistence data (key-value items and files) will be cached if it is not
configured as a write-through. When the system is going to be shut down the modified key-value items and files
will be written back from cache to the non-volatile memory device.
// now trigger PCL to write back modified key-value and file data
rval = pclLifecycleSet(PCL_SHUTDOWN);
Attention:
In order to prevent the misuse of this shutdown scenario the call of pclLifecycleSet with
PCL_SHUTDOWN_CANEL is limited to 3 times per lifecycle.
Persistence has two different types of default data, the factory default data and the configurable default data.
In order to modify configurable default data use the define PCL_USER_DEFAULTDATA for the user_no
parameter. Configurable default data is user and seat independent.
The Persistence Client Library offers two sorts of functions for the Key-value and file interface to read and write
data, handle functions and non-handle functions. For the handle functions first the open function
(pclKeyHandleOpen) needs to be called, and then using the handle the corresponding read/write (e.g.
pclKeyHandleReadData) function can be called.
If requested to just read or write only once to a resource non-handle functions are also available (e.g.
pclKeyReadData).
A file will not be identified directly by a file system path when using for example the pclFileOpen function. The
logical database ID, the resource ID, the user ID and the seat ID will be translated into a path and a filename
within the file system hierarchy. The same is valid for a resource stored via the key-value API. The final resource
name in the database is a concatenation of the resourceID, the user ID and the seatID.
6.2 Datatype
The PCL does not support storing of any complex data structures or any other data types than unsigned char*.
It was a design decision not to support data type families like e.g. glib or Qt data types or other complex custom
data structures as they all can be stored using the unsigned char* data type. Serialization/deserialization or
casting must be done by the using application.
In order to keep the used storage back-end flexible Persistence Client Library provides a plugin interface. With
this interface it is possible to easily integrate storage different.
The plugin (shared object) will be loaded according the information in the configuration file, either it will be
loaded when the function pclInitLibrary will be called or when a plugin function will be called the first time. The
loading behavior is configured in the configuration file.
The configuration file providing the information about the available plugins is expected to be in the following
default location: "/etc/pclCustomLibConfigFile.cfg".
The default location and filename can be changed using the environment variable
"PERS_CLIENT_LIB_CUSTOM_LOAD".
For each key-value resource a different custom storage solution can be applied using the Persistence Resource
Configuration Table (RCT). The attribute storage type needs to be set to "custom" and the name of the plugin
shared object needs to be added to the attribute custom name.
The Persistence Common Object will be used as default storage plugin.
Example:
hwinfo /usr/local/lib/libhwinfoperscustom.so init async
secure /lib/libsecureperscustom.so od async
custom3 /usr/local/lib/libcustom3perscustom.so od sync
emergency /usr/local/lib/libemergencyperscustom.so init sync
This chapter provides all the information needed to build the component and run the test cases.
9.1 Dependencies
The client library has the following dependencies
Components
o automotive-dlt
http://projects.genivi.org/diagnostic-log-trace/
o Persistence Common Object (libpers_common.so)
http://git.projects.genivi.org/?p=persistence/persistence-common-object.git
Add "-- with_database=key-value-store" to the configure step
o dbus
o check
unit test framework for C
needed when configured with "--enable-tests" to run unit tests
Tools
o autotools
o libtool
The test framework “check” has been used to write unit tests which will be run automatically when the test binary
will be started. At the end a test report will be printed to the console showing first a summary about number of
tests that have been executed and how many tests have been passed or failed.
After the summary a test report will be generated showing the status of each test.
When a bug will be fixed a test will be written to verify the problem has been solved.
DTL (Diagnostic, Log and Trace) will be used by the Persistence Client Library to send status and error.
For details about DLT, please refer to the GENIVI DLT project page (http://projects.genivi.org/diagnostic-log-
trace/).
Run tests:
run persistency unit test "./persistence_client_library_test"
Expected results:
The expected result is to have 0 failures and 0 errors, see example output below:
./persistence_client_library_test
Running suite(s): Persistency client library
100%: Checks: 13, Failures: 0, Errors: 0
persistence_client_library_test.c:141:P:GetData:test_GetData:0: Passed
persistence_client_library_test.c:357:P:SetData:test_SetData:0: Passed
persistence_client_library_test.c:400:P:SetDataNoPRCT:test_SetDataNoPRCT:0:
Passed
persistence_client_library_test.c:434:P:GetDataSize:test_GetDataSize:0: Passed
persistence_client_library_test.c:478:P:DeleteData:test_DeleteData:0: Passed
persistence_client_library_test.c:236:P:GetDataHandle:test_GetDataHandle:0:
Passed
persistence_client_library_test.c:652:P:DataHandle:test_DataHandle:0: Passed
persistence_client_library_test.c:727:P:DataHandleOpen:test_DataHandleOpen:0:
Passed
persistence_client_library_test.c:578:P:DataFile:test_DataFile:0: Passed
persistence_client_library_test.c:604:P:DataFileRecovery:test_DataFileRecovery
:0: Passed
persistence_client_library_test.c:794:P:Cursor:test_Cursor:0: Passed
persistence_client_library_test.c:864:P:ReadDefault:test_ReadDefault:0: Passed
persistence_client_library_test.c:886:P:ReadConfDefault:test_ReadConfDefault:0
: Passed
10.2 Quickstart
Normally the default file and folder structure including the default data as well as the RCT and the database will
be setup by the Persistence Administration Service.
If a user wants to extend the provided test application or create an own test application it can be done without
using the PAS to extend the file and folder structure.
An example could be a navigation application likes to use the PCL it can be done in the following way:
Example Code:
int ret = 0;
unsigned char buffer[READ_SIZE] = {0};
unsigned int shutdownReg = PCL_SHUTDOWN_TYPE_FAST | PCL_SHUTDOWN_TYPE_NORMAL;
// initialize PCL
pclInitLibrary("navigation", shutdownReg);
// do something
pclDeinitLibrary();
Steps to proceed:
Use the PCL initialization function and provide the name of the application the PCL should use. The
example above uses the identifier "navigation"
Create a folder with the identifier name as used for the PCL init. Here the folder must be named
"navigation".
o In this example the path must look like /Data/mnt-c/navigation/
Copy the existing RCT and database from the folder lt-persistence_client_library_test provided in the
test data
o Copy RCT file "resource-table-cfg.itz" into /Data/mnt-c/navigation
o Copy the database "cached.itz" to /Data/mnt-c/navigation
Now you should be able to write and read data like shown in the example above.
o Note: As there is no entry for this resource in the RCT, the resource will be stored in the local
cached path.
If another application wants to use the PCL, e.g. a tuner application, just proceed step 1 to 3 using an
appropriate name (e.g. tuner) as application name and folder
11.7 SQLite
As there is a demand for more complex queries, e.g. for a media databases, support of other databases by the
GENIVI persistence subsystem must be considered.
SQLite is a popular choice as database engine in embedded system and due to this circumstance we need to
deal with this database within GENIVI.
As there are some concerns when using SQLite according flash lifetime a safe flash memory device usage must
be guaranteed.
If SQLite will be used on flash memory devices we can't predict how often data will be written to the device.
SQLite for example updates depending on the mode of operation the database for every access, also in read
only operation mode, because of read transactions. Due to their architecture SQLite is creating also a very high
read load on the file system also reduces the lifetime of the flash memory device.
Scenarios which are reducing flash lifetime:
Writing to the same erase sector too often.
o This problem is solved by wear leveling provided by the file system. File systems with both static
and dynamic wear leveling do a better job than ones with just dynamic wear leveling. Flash
devices typically have endurance between a few thousand cycles and 100,000 cycles per
sector. Wear leveling spreads the cycles uniformly across the sectors and thus keeps the
cycling within the endurance limit for a longer period, but can’t guarantee that this will work for
the lifetime of the car which is minimum 10 years.
Writing to the same sector too quickly.
o Here we are looking at the time between two erases of the same sector. This is related to the
previous issue, but not the same. Here again, wear leveling will help.
Reading from the file too often.
o Reading from the same location too often can cause read disturbance and loss of bits. This can
be solved by having a read cache in the file system.
Pro:
Access to the underlying file system is completely under the control of the VFS backend implementation
Cons:
Probably the a complex solution to implement
11.7.4 Miscellaneous
As data should be written sequentially to increase memory lifetime, enabling “write-Ahead Logging” in SQLite
should be considered.
Write-Ahead Logging.
The default method by which SQLite implements atomic commit and rollback is a rollback journal. Beginning with
version 3.7.0, a new "Write-Ahead Log" option (hereafter referred to as "WAL") is available.
For more details please refer to the following page: https://www.sqlite.org/wal.html
GENIVI proposed 3 level rules about the usability of the Persistence Client Library.