Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TDBStore.h Source File

TDBStore.h

00001 /*
00002  * Copyright (c) 2018 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef MBED_TDBSTORE_H
00018 #define MBED_TDBSTORE_H
00019 
00020 #include <stdint.h>
00021 #include <stdio.h>
00022 #include "features/storage/kvstore/include/KVStore.h"
00023 #include "features/storage/blockdevice/BlockDevice.h"
00024 #include "features/storage/blockdevice/BufferedBlockDevice.h"
00025 #include "PlatformMutex.h"
00026 #include "mbed_error.h"
00027 
00028 namespace mbed {
00029 
00030 /** TDBStore class
00031  *
00032  *  Lightweight Key Value storage over a block device
00033  */
00034 
00035 class TDBStore : public KVStore {
00036 public:
00037 
00038     static const uint32_t RESERVED_AREA_SIZE = 64;
00039 
00040     /**
00041      * @brief Class constructor
00042      *
00043      * @param[in]  bd                   Underlying block device. The BlockDevice
00044      *                                  can be any BlockDevice with flash characteristics.
00045      *                                  If using a BlockDevice without flash, such as SDBlockDevice,
00046      *                                  please add the FlashSimBlockDevice on top of it.
00047      *
00048      * @returns none
00049      */
00050     TDBStore(BlockDevice *bd);
00051 
00052     /**
00053      * @brief Class destructor
00054      *
00055      * @returns none
00056      */
00057     virtual ~TDBStore();
00058 
00059     /**
00060      * @brief Initialize TDBStore. If data exists, TDBStore will check the data integrity
00061      *        on initialize. If the integrity checks fails, the TDBStore will use GC to collect
00062      *        the available data and clean corrupted and erroneous records.
00063      *
00064      * @returns MBED_SUCCESS                        Success.
00065      * @returns Negative error code on failure.
00066      */
00067     virtual int init();
00068 
00069     /**
00070      * @brief Deinitialize TDBStore, release and free resources.
00071      *
00072      * @returns MBED_SUCCESS                        Success.
00073      */
00074     virtual int deinit();
00075 
00076 
00077     /**
00078      * @brief Reset TDBStore contents (clear all keys) and reserved data
00079      *
00080      * @returns MBED_SUCCESS                        Success.
00081      *          MBED_ERROR_NOT_READY                Not initialized.
00082      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00083      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00084      */
00085     virtual int reset();
00086 
00087     /**
00088      * @brief Set one TDBStore item, given key and value.
00089      *
00090      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00091      * @param[in]  buffer               Value data buffer.
00092      * @param[in]  size                 Value data size.
00093      * @param[in]  create_flags         Flag mask.
00094      *
00095      * @returns MBED_SUCCESS                        Success.
00096      *          MBED_ERROR_NOT_READY                Not initialized.
00097      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00098      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00099      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00100      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00101      *          MBED_ERROR_MEDIA_FULL               Not enough room on media.
00102      *          MBED_ERROR_WRITE_PROTECTED          Already stored with "write once" flag.
00103      */
00104     virtual int set(const char *key, const void *buffer, size_t size, uint32_t create_flags);
00105 
00106     /**
00107      * @brief Get one TDBStore item by given key.
00108      *
00109      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00110      * @param[in]  buffer               Value data buffer.
00111      * @param[in]  buffer_size          Value data buffer size.
00112      * @param[out] actual_size          Actual read size.
00113      * @param[in]  offset               Offset to read from in data.
00114      *
00115      * @returns MBED_SUCCESS                        Success.
00116      *          MBED_ERROR_NOT_READY                Not initialized.
00117      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00118      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00119      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00120      *          MBED_ERROR_INVALID_DATA_DETECTED    Data is corrupt.
00121      *          MBED_ERROR_ITEM_NOT_FOUND           No such key.
00122      */
00123     virtual int get(const char *key, void *buffer, size_t buffer_size, size_t *actual_size = NULL,
00124                     size_t offset = 0);
00125 
00126     /**
00127      * @brief Get information of a given key. The returned info contains size and flags
00128      *
00129      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00130      * @param[out] info                 Returned information structure.
00131      *
00132      * @returns MBED_SUCCESS                        Success.
00133      *          MBED_ERROR_NOT_READY                Not initialized.
00134      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00135      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00136      *          MBED_ERROR_INVALID_DATA_DETECTED    Data is corrupt.
00137      *          MBED_ERROR_ITEM_NOT_FOUND           No such key.
00138      */
00139     virtual int get_info(const char *key, info_t *info);
00140 
00141     /**
00142      * @brief Remove a TDBStore item by given key.
00143      *
00144      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00145      *
00146      * @returns MBED_SUCCESS                        Success.
00147      *          MBED_ERROR_NOT_READY                Not initialized.
00148      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00149      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00150      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00151      *          MBED_ERROR_MEDIA_FULL               Not enough room on media.
00152      *          MBED_ERROR_ITEM_NOT_FOUND           No such key.
00153      *          MBED_ERROR_WRITE_PROTECTED          Already stored with "write once" flag.
00154      */
00155     virtual int remove(const char *key);
00156 
00157 
00158     /**
00159      * @brief Start an incremental TDBStore set sequence. This operation is blocking other operations.
00160      *        Any get/set/remove/iterator operation will be blocked until set_finalize is called.
00161      *
00162      * @param[out] handle               Returned incremental set handle.
00163      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00164      * @param[in]  final_data_size      Final value data size.
00165      * @param[in]  create_flags         Flag mask.
00166      *
00167      * @returns MBED_SUCCESS                        Success.
00168      *          MBED_ERROR_NOT_READY                Not initialized.
00169      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00170      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00171      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00172      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00173      *          MBED_ERROR_MEDIA_FULL               Not enough room on media.
00174      *          MBED_ERROR_WRITE_PROTECTED          Already stored with "write once" flag.
00175      */
00176     virtual int set_start(set_handle_t *handle, const char *key, size_t final_data_size, uint32_t create_flags);
00177 
00178     /**
00179      * @brief Add data to incremental TDBStore set sequence. This operation is blocking other operations.
00180      *        Any get/set/remove operation will be blocked until set_finalize will be called.
00181      *
00182      * @param[in]  handle               Incremental set handle.
00183      * @param[in]  value_data           Value data to add.
00184      * @param[in]  data_size            Value data size.
00185      *
00186      * @returns MBED_SUCCESS                        Success.
00187      *          MBED_ERROR_NOT_READY                Not initialized.
00188      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00189      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00190      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00191      */
00192     virtual int set_add_data(set_handle_t handle, const void *value_data, size_t data_size);
00193 
00194     /**
00195      * @brief Finalize an incremental KVStore set sequence.
00196      *
00197      * @param[in]  handle               Incremental set handle.
00198      *
00199      * @returns MBED_SUCCESS                        Success.
00200      *          MBED_ERROR_NOT_READY                Not initialized.
00201      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00202      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00203      */
00204     virtual int set_finalize(set_handle_t handle);
00205 
00206     /**
00207      * @brief Start an iteration over KVStore keys.
00208      *        There are no issues with any other operations while iterator is open.
00209      *
00210      * @param[out] it                   Returned iterator handle.
00211      * @param[in]  prefix               Key prefix (null for all keys).
00212      *
00213      * @returns MBED_SUCCESS                        Success.
00214      *          MBED_ERROR_NOT_READY                Not initialized.
00215      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00216      */
00217     virtual int iterator_open(iterator_t *it, const char *prefix = NULL);
00218 
00219     /**
00220      * @brief Get next key in iteration.
00221      *        There are no issues with any other operations while iterator is open.
00222      *
00223      * @param[in]  it                   Iterator handle.
00224      * @param[in]  key                  Buffer for returned key.
00225      * @param[in]  key_size             Key buffer size.
00226      *
00227      * @returns MBED_SUCCESS                        Success.
00228      *          MBED_ERROR_NOT_READY                Not initialized.
00229      *          MBED_ERROR_READ_FAILED              Unable to read from block device.
00230      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00231      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00232      *          MBED_ERROR_INVALID_DATA_DETECTED    Data is corrupt.
00233      *          MBED_ERROR_ITEM_NOT_FOUND           No more keys found.
00234      */
00235     virtual int iterator_next(iterator_t it, char *key, size_t key_size);
00236 
00237     /**
00238      * @brief Close iteration.
00239      *
00240      * @param[in]  it                   Iterator handle.
00241      *
00242      * @returns MBED_SUCCESS                        Success.
00243      *          MBED_ERROR_NOT_READY                Not initialized.
00244      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00245      */
00246     virtual int iterator_close(iterator_t it);
00247 
00248     /**
00249      * @brief Set data in reserved area, which is a special location for special data, such as ROT.
00250      *        The data written to reserved area can't be overwritten.
00251      *
00252      * @param[in]  reserved_data        Reserved data buffer.
00253      * @param[in]  reserved_data_buf_size
00254      *                                  Reserved data buffer size.
00255      *
00256      * @returns MBED_SUCCESS                        Success.
00257      *          MBED_ERROR_NOT_READY                Not initialized.
00258      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00259      *          MBED_ERROR_WRITE_FAILED             Unable to write to media.
00260      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00261      *          MBED_ERROR_INVALID_SIZE             Invalid size given in function arguments.
00262      */
00263     virtual int reserved_data_set(const void *reserved_data, size_t reserved_data_buf_size);
00264 
00265     /**
00266      * @brief Get data from reserved area, which is a special location for special data, such as ROT.
00267      *
00268      * @param[in]  reserved_data        Reserved data buffer.
00269      * @param[in]  reserved_data_buf_size
00270      *                                  Reserved data buffer size.
00271      * @param[in]  actual_data_size     Return data size.
00272      *
00273      * @returns MBED_SUCCESS                        Success.
00274      *          MBED_ERROR_NOT_READY                Not initialized.
00275      *          MBED_ERROR_READ_FAILED              Unable to read from media.
00276      *          MBED_ERROR_INVALID_ARGUMENT         Invalid argument given in function arguments.
00277      *          MBED_ERROR_INVALID_DATA_DETECTED    Data is corrupt.
00278      *          MBED_ERROR_ITEM_NOT_FOUND           No reserved data was written.
00279      */
00280     virtual int reserved_data_get(void *reserved_data, size_t reserved_data_buf_size,
00281                                   size_t *actual_data_size = 0);
00282 
00283 #if !defined(DOXYGEN_ONLY)
00284 private:
00285 
00286     typedef struct {
00287         uint32_t address;
00288         size_t   size;
00289     } tdbstore_area_data_t;
00290 
00291     static const int _num_areas = 2;
00292     static const int _max_open_iterators = 16;
00293 
00294     PlatformMutex _mutex;
00295     PlatformMutex _inc_set_mutex;
00296     void *_ram_table;
00297     size_t _max_keys;
00298     size_t _num_keys;
00299     BlockDevice *_bd;
00300     BufferedBlockDevice *_buff_bd;
00301     uint32_t _free_space_offset;
00302     uint32_t _master_record_offset;
00303     uint32_t _master_record_size;
00304     bool _is_initialized;
00305     int _active_area;
00306     uint16_t _active_area_version;
00307     size_t _size;
00308     tdbstore_area_data_t _area_params[_num_areas];
00309     uint32_t _prog_size;
00310     uint8_t *_work_buf;
00311     char *_key_buf;
00312     bool _variant_bd_erase_unit_size;
00313     void *_inc_set_handle;
00314     void *_iterator_table[_max_open_iterators];
00315 
00316     /**
00317      * @brief Read a block from an area.
00318      *
00319      * @param[in]  area                   Area.
00320      * @param[in]  offset                 Offset in area.
00321      * @param[in]  size                   Number of bytes to read.
00322      * @param[in]  buf                    Output buffer.
00323      *
00324      * @returns 0 for success, nonzero for failure.
00325      */
00326     int read_area(uint8_t area, uint32_t offset, uint32_t size, void *buf);
00327 
00328     /**
00329      * @brief Write a block to an area.
00330      *
00331      * @param[in]  area                   Area.
00332      * @param[in]  offset                 Offset in area.
00333      * @param[in]  size                   Number of bytes to write.
00334      * @param[in]  buf                    Input buffer.
00335      *
00336      * @returns 0 for success, non-zero for failure.
00337      */
00338     int write_area(uint8_t area, uint32_t offset, uint32_t size, const void *buf);
00339 
00340     /**
00341      * @brief Reset an area (erase its start).
00342      *        This erases master record, but preserves the
00343      *        reserved area data.
00344      *
00345      * @param[in]  area                   Area.
00346      *
00347      * @returns 0 for success, nonzero for failure.
00348      */
00349     int reset_area(uint8_t area);
00350 
00351     /**
00352      * @brief Erase an erase unit.
00353      *
00354      * @param[in]  area                   Area.
00355      * @param[in]  offset                 Offset in area.
00356      *
00357      * @returns 0 for success, nonzero for failure.
00358      */
00359     int erase_erase_unit(uint8_t area, uint32_t offset);
00360 
00361     /**
00362      * @brief Calculate addresses and sizes of areas.
00363      */
00364     void calc_area_params();
00365 
00366     /**
00367      * @brief Read a TDBStore record from a given location.
00368      *
00369      * @param[in]  area                   Area.
00370      * @param[in]  offset                 Offset of record in area.
00371      * @param[out] key                    Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00372      * @param[out] data_buf               Data buffer.
00373      * @param[in]  data_buf_size          Data buffer size.
00374      * @param[out] actual_data_size       Actual data size.
00375      * @param[in]  data_offset            Offset in data.
00376      * @param[in]  copy_key               Copy key to user buffer.
00377      * @param[in]  copy_data              Copy data to user buffer.
00378      * @param[in]  check_expected_key     Check whether key belongs to this record.
00379      * @param[in]  calc_hash              Calculate hash (on key).
00380      * @param[out] hash                   Calculated hash.
00381      * @param[out] flags                  Record flags.
00382      * @param[out] next_offset            Offset of next record.
00383      *
00384      * @returns 0 for success, nonzero for failure.
00385      */
00386     int read_record(uint8_t area, uint32_t offset, char *key,
00387                     void *data_buf, uint32_t data_buf_size,
00388                     uint32_t &actual_data_size, size_t data_offset, bool copy_key,
00389                     bool copy_data, bool check_expected_key, bool calc_hash,
00390                     uint32_t &hash, uint32_t &flags, uint32_t &next_offset);
00391 
00392     /**
00393      * @brief Write a master record of a given area.
00394      *
00395      * @param[in]  area                   Area.
00396      * @param[in]  version                Area version.
00397      * @param[out] next_offset            Offset of next record.
00398      *
00399      * @returns 0 for success, nonzero for failure.
00400      */
00401     int write_master_record(uint8_t area, uint16_t version, uint32_t &next_offset);
00402 
00403     /**
00404      * @brief Copy a record from one area to the opposite one.
00405      *
00406      * @param[in]  from_area              Area to copy record from.
00407      * @param[in]  from_offset            Offset in source area.
00408      * @param[in]  to_offset              Offset in destination area.
00409      * @param[out] to_next_offset         Offset of next record in destination area.
00410      *
00411      * @returns 0 for success, nonzero for failure.
00412      */
00413     int copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset,
00414                     uint32_t &to_next_offset);
00415 
00416     /**
00417      * @brief Garbage collection (compact all records from active area to the standby one).
00418      *
00419      * @returns 0 for success, nonzero for failure.
00420      */
00421     int garbage_collection();
00422 
00423     /**
00424      * @brief Return record size given key and data size.
00425      *
00426      * @param[in]  key                    Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00427      * @param[in]  data_size              Data size.
00428      *
00429      * @returns record size.
00430      */
00431     uint32_t record_size(const char *key, uint32_t data_size);
00432 
00433     /**
00434      * @brief Find a record given key
00435      *
00436      * @param[in]  area                   Area.
00437      * @param[in]  key                    Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00438      * @param[out] offset                 Offset of record.
00439      * @param[out] ram_table_ind          Index in RAM table (target one if not found).
00440      * @param[out] hash                   Calculated key hash.
00441      *
00442      * @returns 0 for success, nonzero for failure.
00443      */
00444     int find_record(uint8_t area, const char *key, uint32_t &offset,
00445                     uint32_t &ram_table_ind, uint32_t &hash);
00446     /**
00447      * @brief Actual logics of get API (also covers all other get APIs).
00448      *
00449      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00450      * @param[in]  copy_data            Copy data to user buffer.
00451      * @param[in]  data_buf             Buffer to store data on.
00452      * @param[in]  data_buf_size        Data buffer size (bytes).
00453      * @param[out] actual_data_size     Actual data size (bytes).
00454      * @param[out] flags                Flags.
00455      *
00456      * @returns 0 for success, nonzero for failure.
00457      */
00458     int do_get(const char *key, bool copy_data,
00459                void *data_buf, uint32_t data_buf_size, uint32_t &actual_data_size,
00460                uint32_t &flags);
00461 
00462     /**
00463      * @brief Actual logics of set API (covers also the remove API).
00464      *
00465      * @param[in]  key                  Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
00466      * @param[in]  data_buf             Data buffer.
00467      * @param[in]  data_buf_size        Data buffer size (bytes).
00468      * @param[in]  flags                Flags.
00469      *
00470      * @returns 0 for success, nonzero for failure.
00471      */
00472     int do_set(const char *key, const void *data_buf, uint32_t data_buf_size, uint32_t flags);
00473 
00474     /**
00475      * @brief Build RAM table and update _free_space_offset (scanning all the records in the area).
00476      *
00477      * @returns 0 for success, nonzero for failure.
00478      */
00479     int build_ram_table();
00480 
00481     /**
00482      * @brief Increment maximum number of keys and reallocate RAM table accordingly.
00483      *
00484      * @param[out] ram_table             Updated RAM table.
00485      *
00486      * @returns 0 for success, nonzero for failure.
00487      */
00488     int increment_max_keys(void **ram_table = 0);
00489 
00490     /**
00491      * @brief Calculate offset from start of erase unit.
00492      *
00493      * @param[in]  area                  Area.
00494      * @param[in]  offset                Offset in area.
00495      * @param[out] offset_from_start     Offset from start of erase unit.
00496      * @param[out] dist_to_end           Distance to end of erase unit.
00497      *
00498      * @returns offset in erase unit.
00499      */
00500     void offset_in_erase_unit(uint8_t area, uint32_t offset, uint32_t &offset_from_start,
00501                               uint32_t &dist_to_end);
00502 
00503     /**
00504      * @brief Before writing a record, check whether you are crossing an erase unit.
00505      *        If you do, check if it's erased, and erase it if not.
00506      *
00507      * @param[in]  area                  Area.
00508      * @param[in]  offset                Offset in area.
00509      * @param[in]  size                  Write size.
00510      * @param[in]  force_check           Force checking.
00511      *
00512      * @returns 0 for success, nonzero for failure.
00513      */
00514     int check_erase_before_write(uint8_t area, uint32_t offset, uint32_t size,
00515                                  bool force_check = false);
00516 
00517     /**
00518      * @brief Get data from reserved area - worker function.
00519      *        This verifies that reserved data on both areas have
00520      *        correct checksums. If given pointer is not NULL, also
00521      *        write the reserved data to buffer. If checksums are not
00522      *        valid, return error code, and don't write anything to any
00523      *        pointers.
00524      *
00525      * @param[out] reserved_data        Reserved data buffer (NULL to return nothing).
00526      * @param[in]  reserved_data_buf_size
00527      *                                  Reserved data buffer size.
00528      * @param[out] actual_data_size     If not NULL, return actual data size.
00529      * @param[out] copy_trailer         If not NULL, copy the trailer content to given buffer.
00530      *
00531      * @returns 0 on success or a negative error code on failure
00532      */
00533     int do_reserved_data_get(void *reserved_data, size_t reserved_data_buf_size,
00534                              size_t *actual_data_size = 0, void *copy_trailer = 0);
00535 
00536     /**
00537      * @brief Update all iterators after adding or deleting of keys.
00538      *
00539      * @param[in]  added                True if added, false if deleted.
00540      * @param[in]  ram_table_ind        RAM table index.
00541      *
00542      * @returns none
00543      */
00544     void update_all_iterators(bool added, uint32_t ram_table_ind);
00545 
00546 #endif
00547 
00548 };
00549 /** @}*/
00550 
00551 } // namespace mbed
00552 
00553 #endif