Skip to content

KVStore Example - Global API #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Nov 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.build
.mbed
projectfiles
*.py*
153 changes: 152 additions & 1 deletion README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1 +1,152 @@
# mbed-os-example-kvstore
# Getting started with the Mbed OS Key Value Store Global API

This example demonstrates how to use the Mbed OS Key Value Storage Global API.

KVStore is a key-value storage based API over a block device.
Mbed-OS provides several KVStore implementation options, that can be optimized to
the specific application requirements and target hardware:
- TDBStore - Default implementation of the KVStore API. It provides static wear-leveling and quick access for when you have a small number of KV pairs.
- FileSystemStore - Class that provides a key-value store API on top of a POSIX-like file system API.
- SecureStore - Class that provides encryption, authentication and rollback protection on top of the KVStore API. It requires two KVStore implementations, one that provides the storage for the KV pairs and one providing storage for the CMACs that protect KV pairs stored in the KVStore.

KVStore Global APIs use Mbed-OS [KVStore configuration](#kvstore-configuration) json file to define the selected KVStore implementation option of the above.

You can find more information about Mbed OS Key Value Store Design and other related items in the [kvstore design documentation](https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/features/storage/KVStore/KVStore_design.md).

**Table of contents:**

1. [Scenario](#scenario)
2. [Hardware Requirements](#hardware-requirements)
3. [Usage](#usage)
- [Import the example](#import-the-example)
- [Compile the example](#compile-the-example)
- [Run the example](#run-the-example)
- [Troubleshooting](#troubleshooting)
4. [Default Global KVStore Configuration](#kvstore-configuration)

## Scenario

The example sets several key/value pairs, some are defined as 'dummy' and some as 'real'. The example demonstrates several possible scenarios that set, get, search and remove specific keys, and iterate all keys.

The example contains an [mbed_app.json](./mbed_app.json) configuration file that demonstrates how to set KVStore configuration for a specific target (K64F) that may override the [default configuration](#kvstore-configuration).

## Hardware requirements

KVStore general API may use several types of key/value storage classes, according to the configuration, that run on top of an underlying Block Device. Each type has different HW requirements for the underlying Block Device.
1. TDB_INTERNAL - may run on top of flash Block Device only (typically internal flash)
2. TDB_EXTERNAL - requires external flash for the key/value storage and typically internal flash for its replay protection storage.
3. TDB_EXTERNAL_NO_RBP - requires external flash for the key/value storage
4. FILESYSTEM - may use either flash or SD card for the key/value storage and typically internal flash for its replay protection storage.
5. FILESYSTEM_NO_RBP - may use either flash or SD card for the key/value storage

## Usage

#### Import the example

Make sure you have an Mbed development environment set up. [Get started with Mbed OS](https://os.mbed.com/docs/latest/tutorials/your-first-program.html)
to set everything up.

From the command-line, import the example:

```
mbed import mbed-os-example-kvstore
cd mbed-os-example-kvstore
```

#### Compile the example

Invoke `mbed compile`, and specify the name of your platform and your favorite
toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5:

```
mbed compile -m K64F -t ARM
```

Your PC may take a few moments to compile your code. At the end, you'll see a
result similar to:

```
[snip]
+--------------------------+-------+-------+-------+
| Module | .text | .data | .bss |
+--------------------------+-------+-------+-------+
| [fill] | 235 | 4 | 345 |
| [lib]/c.a | 31247 | 2472 | 89 |
| [lib]/gcc.a | 3112 | 0 | 0 |
| [lib]/misc | 204 | 4 | 28 |
| [lib]/nosys.a | 32 | 0 | 0 |
| main.o | 1719 | 0 | 0 |
| mbed-os/cmsis | 1029 | 0 | 84 |
| mbed-os/components | 4161 | 0 | 48 |
| mbed-os/drivers | 1487 | 0 | 100 |
| mbed-os/features | 42061 | 4 | 1426 |
| mbed-os/hal | 2043 | 4 | 68 |
| mbed-os/platform | 3095 | 260 | 134 |
| mbed-os/rtos | 7804 | 168 | 5969 |
| mbed-os/targets | 15561 | 12 | 413 |
| Subtotals |113790 | 2928 | 8704 |
+--------------------------+-------+-------+-------+
Total Static RAM memory (data + bss): 11632(+0) bytes
Total Flash memory (text + data): 116718(+0) bytes

Image: ./BUILD/K82F/GCC_ARM/kvstore.bin
```

#### Run the example

1. Connect your Mbed Enabled device to the computer over USB.
1. Copy the binary file to the Mbed Enabled device.
1. Press the reset button to start the program.
1. Open the UART of the board in your favorite UART viewing program. For
example, `screen /dev/ttyACM0`.

**Note:** The default serial port baud rate is 115200 bit/s.
You may open serial term with:
```
mbed sterm -b 115200 -r
```

Expected output:

```
--- Mbed OS KVStore static API example ---
kv_reset
kv_reset -> 0
kv_set first dummy key
kv_set -> 0
kv_get_info of first key
kv_get_info -> 0
kv_get_info key: /kv/dummy_key1
kv_get_info info - size: 31, flags: 0
kv_get first key
kv_get -> 0
kv_get key: /kv/dummy_key1
kv_get value: kvstore_dummy_value_hello_world
kv_set second dummy key
kv_set -> 0
kv_set third key with Confidentiality, Integrity and Replay Protection flags
kv_set -> 0
kv_set Set 'Real' Key 1
kv_set -> 0
kv_set Set 'Real' Key 2 with flag write-once
kv_set -> 0
Removing 'Dummy' Keys
1) Removing dummy_key1
2) Removing dummy_key2
3) Removing dummy_auth_enc_key
Remaining with 'Real' Keys:
1) real_wo_key
2) real_key1
kv_remove write-once file - should fail!
kv_remove -> 274
kv_reset format kvstore (including write-once)
kv_reset -> 0
```

#### Troubleshooting

If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html)
for suggestions on what could be wrong and how to fix it.

## KVStore Configuration
The Global KVStore API options can be set up in the higher level Mbes-OS KVSTore retargetting layer [json configuration](https://github.com/ARMmbed/mbed-os/blob/master/features/storage/kvstore/conf/mbed_lib.json)
143 changes: 143 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/* Copyright (c) 2018 Arm Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mbed.h"
#include <stdio.h>
#include <string.h>
#include "KVStore.h"
#include "kvstore_global_api.h"

using namespace mbed;

#define EXAMPLE_KV_VALUE_LENGTH 64
#define EXAMPLE_KV_KEY_LENGTH 32
#define err_code(res) MBED_GET_ERROR_CODE(res)

void kv_store_global_api_example();

int main()
{
/* KV Store Static API Example */
kv_store_global_api_example();
}

void kv_store_global_api_example()
{
char kv_value_in[EXAMPLE_KV_VALUE_LENGTH] = {"kvstore_dummy_value_hello_world"};
char kv_key_in[EXAMPLE_KV_KEY_LENGTH] = {"/kv/dummy_key1"};
char kv_key_out[EXAMPLE_KV_KEY_LENGTH] = {0};
size_t actual_size = 0;

/* key information container */
kv_info_t info;

/* kv store iterator */
kv_iterator_t kvstore_it;

int i_ind = 0;

printf("--- Mbed OS KVStore static API example ---\n");

int res = MBED_ERROR_NOT_READY;

/* Start By Resetting the KV Storage */
printf("kv_reset\n");
res = kv_reset("/kv/");
printf("kv_reset -> %d\n", err_code(res));

/* Set First 'Dummy' Key/Value pair with unprotected clear value data */
printf("kv_set first dummy key\n");
res = kv_set(kv_key_in, kv_value_in, strlen(kv_value_in), 0);
printf("kv_set -> %d\n", err_code(res));

/* Read the KV Pair you've just set */
/* Start by getting key's information */
printf("kv_get_info of first key\n");
res = kv_get_info(kv_key_in, &info);
printf("kv_get_info -> %d\n", err_code(res));
printf("kv_get_info key: %s\n", kv_key_in);
printf("kv_get_info info - size: %u, flags: %lu\n", info.size, info.flags);

/* Now that you know the data value size of this key,
* allocate a buffer with matching size and get the value data */
printf("kv_get first key\n");
char *kv_first_value_out = new char[info.size+1];
memset(kv_first_value_out, 0, info.size+1);
res = kv_get(kv_key_in, kv_first_value_out, info.size, &actual_size);
printf("kv_get -> %d\n", err_code(res));
printf("kv_get key: %s\n", kv_key_in);
printf("kv_get value: %s\n", kv_first_value_out);
delete[] kv_first_value_out;

/* Lets set some more 'Dummy' and 'Real' KV pairs */
/* Set 'Dummy' Key2 */
printf("kv_set second dummy key \n");
res = kv_set("/kv/dummy_key2", "dummy_value2", strlen("dummy_value2"), 0);
printf("kv_set -> %d\n", err_code(res));

/* Set an authenticated-encrypted 'Dummy' key with Replay protection */
printf("kv_set third key with Confidentiality, Integrity and Replay Protection flags\n");
res = kv_set("/kv/dummy_auth_enc_key", "auth_enc_value", strlen("auth_enc_value"),
KV_REQUIRE_CONFIDENTIALITY_FLAG|KV_REQUIRE_INTEGRITY_FLAG|KV_REQUIRE_REPLAY_PROTECTION_FLAG);
printf("kv_set -> %d\n", err_code(res));

/* Set 2 non-dummy 'Real' KV pairs */
/* Set 'Real' Key 1 */
printf("kv_set Set 'Real' Key 1\n");
res = kv_set("/kv/real_key1", "real_value1", strlen("real_value1"), 0);
printf("kv_set -> %d\n", err_code(res));
/* Set 'Real' Write-Once Key2 for a key that you do not want to be removed */
printf("kv_set Set 'Real' Key 2 with flag write-once\n");
res = kv_set("/kv/real_wo_key", "real_wo_value", strlen("real_wo_value"), KV_WRITE_ONCE_FLAG);
printf("kv_set -> %d\n", err_code(res));

/* Now lets remove all of the 'Dummy' Keys and remain with the 'Real' ones */
printf("Removing 'Dummy' Keys\n");
/* Iterate and remove Keys that start with prefix 'dummy' */
res = kv_iterator_open(&kvstore_it, "dummy");
memset(kv_key_out, 0, EXAMPLE_KV_KEY_LENGTH);
while (kv_iterator_next(kvstore_it, kv_key_out, EXAMPLE_KV_KEY_LENGTH) != MBED_ERROR_ITEM_NOT_FOUND) {
i_ind++;
printf("%d) Removing %s\n", i_ind, kv_key_out);
kv_remove(kv_key_out);
memset(kv_key_out, 0, EXAMPLE_KV_KEY_LENGTH);
}
res = kv_iterator_close(kvstore_it);
printf("Remaining with 'Real' Keys:\n");
/* Iterate on all remaining Keys */
res = kv_iterator_open(&kvstore_it, NULL);
memset(kv_key_out, 0, EXAMPLE_KV_KEY_LENGTH);
i_ind = 0;
while (kv_iterator_next(kvstore_it, kv_key_out, EXAMPLE_KV_KEY_LENGTH) != MBED_ERROR_ITEM_NOT_FOUND) {
i_ind++;
printf("%d) %s\n", i_ind, kv_key_out);
memset(kv_key_out, 0, EXAMPLE_KV_KEY_LENGTH);
}
res = kv_iterator_close(kvstore_it);

/* Try to remove write-once Key - should fail */
printf("kv_remove write-once file - should fail!\n");
res = kv_remove("/kv/real_wo_key");
printf("kv_remove -> %d\n", err_code(res));

/* Finally, reset will format kvstore and remove All Keys (including write-once keys) */
printf("kv_reset format kvstore (including write-once)\n");
res = kv_reset("/kv/");
printf("kv_reset -> %d\n", err_code(res));

return;
}
1 change: 1 addition & 0 deletions mbed-os.lib
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/davidsaada/mbed-os/#a6a5788d1add64282cd0b50dec8f5b9e2b831cd6
12 changes: 12 additions & 0 deletions mbed_app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"target_overrides": {
"K64F": {
"storage.storage_type": "TDB_INTERNAL"
},
"*": {
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"platform.stdio-convert-newlines": 1
}
}
}