@@ -68,7 +68,8 @@ typedef struct {
6868
6969typedef enum {
7070 TDBSTORE_AREA_STATE_NONE = 0 ,
71- TDBSTORE_AREA_STATE_EMPTY,
71+ TDBSTORE_AREA_STATE_ERASED,
72+ TDBSTORE_AREA_STATE_INVALID,
7273 TDBSTORE_AREA_STATE_VALID,
7374} area_state_e;
7475
@@ -848,6 +849,7 @@ int TDBStore::garbage_collection()
848849 int ret;
849850 size_t ind;
850851
852+ // Reset the standby area
851853 ret = reset_area (1 - _active_area);
852854 if (ret) {
853855 return ret;
@@ -883,12 +885,6 @@ int TDBStore::garbage_collection()
883885 return ret;
884886 }
885887
886- // Now reset standby area
887- ret = reset_area (1 - _active_area);
888- if (ret) {
889- return ret;
890- }
891-
892888 return MBED_SUCCESS;
893889}
894890
@@ -985,7 +981,7 @@ int TDBStore::init()
985981 uint32_t next_offset;
986982 uint32_t flags, hash;
987983 uint32_t actual_data_size;
988- int os_ret, ret = MBED_SUCCESS, reserved_ret ;
984+ int os_ret, ret = MBED_SUCCESS;
989985 uint16_t versions[_num_areas];
990986
991987 _mutex.lock ();
@@ -1053,13 +1049,9 @@ int TDBStore::init()
10531049 MBED_ERROR (ret, " TDBSTORE: Unable to read record at init" );
10541050 }
10551051
1056- // Master record may be either corrupt or erased - either way erase it
1057- // (this will do nothing if already erased)
1052+ // Master record may be either corrupt or erased
10581053 if (ret == MBED_ERROR_INVALID_DATA_DETECTED) {
1059- if (reset_area (area)) {
1060- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to reset area at init" );
1061- }
1062- area_state[area] = TDBSTORE_AREA_STATE_EMPTY;
1054+ area_state[area] = TDBSTORE_AREA_STATE_INVALID;
10631055 continue ;
10641056 }
10651057
@@ -1074,9 +1066,11 @@ int TDBStore::init()
10741066 }
10751067
10761068 // In case we have two empty areas, arbitrarily use area 0 as the active one.
1077- if ((area_state[0 ] == TDBSTORE_AREA_STATE_EMPTY) && (area_state[1 ] == TDBSTORE_AREA_STATE_EMPTY)) {
1069+ if ((area_state[0 ] == TDBSTORE_AREA_STATE_INVALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_INVALID)) {
1070+ reset_area (0 );
10781071 _active_area = 0 ;
10791072 _active_area_version = 1 ;
1073+ area_state[0 ] = TDBSTORE_AREA_STATE_ERASED;
10801074 ret = write_master_record (_active_area, _active_area_version, _free_space_offset);
10811075 if (ret) {
10821076 MBED_ERROR (ret, " TDBSTORE: Unable to write master record at init" );
@@ -1086,58 +1080,31 @@ int TDBStore::init()
10861080 }
10871081
10881082 // In case we have two valid areas, choose the one having the higher version (or 0
1089- // in case of wrap around). Reset the other one.
1083+ // in case of wrap around).
10901084 if ((area_state[0 ] == TDBSTORE_AREA_STATE_VALID) && (area_state[1 ] == TDBSTORE_AREA_STATE_VALID)) {
10911085 if ((versions[0 ] > versions[1 ]) || (!versions[0 ])) {
10921086 _active_area = 0 ;
10931087 } else {
10941088 _active_area = 1 ;
10951089 }
10961090 _active_area_version = versions[_active_area];
1097- ret = reset_area (1 - _active_area);
1098- if (ret) {
1099- MBED_ERROR (ret, " TDBSTORE: Unable to reset area at init" );
1100- }
11011091 }
11021092
11031093 // Currently set free space offset pointer to the end of free space.
11041094 // Ram table build process needs it, but will update it.
11051095 _free_space_offset = _size;
11061096 ret = build_ram_table ();
11071097
1098+ // build_ram_table() scans all keys, until invalid data found.
1099+ // Therefore INVALID_DATA is not considered error.
11081100 if ((ret != MBED_SUCCESS) && (ret != MBED_ERROR_INVALID_DATA_DETECTED)) {
1109- MBED_ERROR (ret, " TDBSTORE: Unable to build RAM table at init" );
1110- }
1111-
1112- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED) && (_free_space_offset < _size)) {
1113- // Space after last valid record may be erased, hence "corrupt". Now check if it really is erased.
1114- bool erased;
1115- if (is_erase_unit_erased (_active_area, _free_space_offset, erased)) {
1116- MBED_ERROR (MBED_ERROR_READ_FAILED, " TDBSTORE: Unable to check whether erase unit is erased at init" );
1117- }
1118- if (erased) {
1119- // Erased - all good
1120- ret = MBED_SUCCESS;
1121- }
1122- }
1123-
1124- // If we either have a corrupt record somewhere
1125- // perform garbage collection to salvage all preceding records.
1126- if ((ret == MBED_ERROR_INVALID_DATA_DETECTED)) {
1127- ret = garbage_collection ();
1128- if (ret) {
1129- MBED_ERROR (ret, " TDBSTORE: Unable to perform GC at init" );
1130- }
1131- os_ret = _buff_bd->sync ();
1132- if (os_ret) {
1133- MBED_ERROR (MBED_ERROR_WRITE_FAILED, " TDBSTORE: Unable to sync BD at init" );
1134- }
1101+ goto fail;
11351102 }
11361103
11371104end:
11381105 _is_initialized = true ;
11391106 _mutex.unlock ();
1140- return ret ;
1107+ return MBED_SUCCESS ;
11411108fail:
11421109 delete[] ram_table;
11431110 delete _buff_bd;
@@ -1367,6 +1334,13 @@ int TDBStore::reserved_data_set(const void *reserved_data, size_t reserved_data_
13671334 trailer.data_size = reserved_data_buf_size;
13681335 trailer.crc = calc_crc (initial_crc, reserved_data_buf_size, reserved_data);
13691336
1337+ // Erase the header of non-active area, just to make sure that we can write to it
1338+ // In case garbage collection has not yet been run, the area can be un-erased
1339+ ret = reset_area (1 - _active_area);
1340+ if (ret) {
1341+ goto end;
1342+ }
1343+
13701344 /*
13711345 * Write to both areas
13721346 * Both must success, as they are required to be erased when TDBStore initializes
@@ -1470,35 +1444,10 @@ void TDBStore::offset_in_erase_unit(uint8_t area, uint32_t offset,
14701444 dist_to_end = _buff_bd->get_erase_size (agg_offset) - offset_from_start;
14711445}
14721446
1473- int TDBStore::is_erase_unit_erased (uint8_t area, uint32_t offset, bool &erased)
1474- {
1475- uint32_t offset_from_start, dist;
1476- offset_in_erase_unit (area, offset, offset_from_start, dist);
1477- uint8_t buf[sizeof (record_header_t )], blanks[sizeof (record_header_t )];
1478- memset (blanks, _buff_bd->get_erase_value (), sizeof (blanks));
1479-
1480- while (dist) {
1481- uint32_t chunk = std::min (dist, (uint32_t ) sizeof (buf));
1482- int ret = read_area (area, offset, chunk, buf);
1483- if (ret) {
1484- return MBED_ERROR_READ_FAILED;
1485- }
1486- if (memcmp (buf, blanks, chunk)) {
1487- erased = false ;
1488- return MBED_SUCCESS;
1489- }
1490- offset += chunk;
1491- dist -= chunk;
1492- }
1493- erased = true ;
1494- return MBED_SUCCESS;
1495- }
1496-
14971447int TDBStore::check_erase_before_write (uint8_t area, uint32_t offset, uint32_t size, bool force_check)
14981448{
14991449 // In order to save init time, we don't check that the entire area is erased.
15001450 // Instead, whenever reaching an erase unit start erase it.
1501-
15021451 while (size) {
15031452 uint32_t dist, offset_from_start;
15041453 int ret;
@@ -1516,4 +1465,3 @@ int TDBStore::check_erase_before_write(uint8_t area, uint32_t offset, uint32_t s
15161465 }
15171466 return MBED_SUCCESS;
15181467}
1519-
0 commit comments