-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathCacheAndPersist.h
350 lines (312 loc) · 13.9 KB
/
CacheAndPersist.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <cstddef>
#include <cstdint>
#include <json/json.h>
#include <streambuf>
#include <string>
// max buffer to be allocated for a read buffer
// this matches the Max Send Size on the AWS IoT channel
constexpr size_t MAX_DATA_RD_SIZE = 131072;
// file size assigned for an invalid data type
constexpr size_t INVALID_FILE_SIZE = (size_t)-1;
namespace Aws
{
namespace IoTFleetWise
{
enum class ErrorCode
{
SUCCESS = 0,
MEMORY_FULL,
EMPTY,
FILESYSTEM_ERROR,
INVALID_DATATYPE,
INVALID_DATA
};
enum class DataType
{
EDGE_TO_CLOUD_PAYLOAD = 0,
PAYLOAD_METADATA,
COLLECTION_SCHEME_LIST,
DECODER_MANIFEST,
DEFAULT_DATA_TYPE,
#ifdef FWE_FEATURE_LAST_KNOWN_STATE
STATE_TEMPLATE_LIST,
STATE_TEMPLATE_LIST_METADATA,
#endif
};
/**
* @brief Class that implements the persistency interface. Handles storage/retrieval for non-volatile memory(NVM).
*
* Bootstrap config will specify the partition on the flash memory as well as the max partition size.
* Underlying storage mechanism writes data to a file.
* Multiple components using this library e.g. CollectionScheme Manager, Payload Manager are operating on its separate
* files hence are thread safe.
*/
// coverity[cert_dcl60_cpp_violation] false positive - class only defined once
// coverity[autosar_cpp14_m3_2_2_violation] false positive - class only defined once
// coverity[misra_cpp_2008_rule_3_2_2_violation] false positive - class only defined once
class CacheAndPersist
{
public:
CacheAndPersist() = default;
/**
* @brief Constructor
* @param partitionPath Partition allocated for the NV storage (from config file)
* @param maxPartitionSize Partition size should not exceed this.
*/
CacheAndPersist( const std::string &partitionPath, size_t maxPartitionSize );
/**
* @brief Destructor - writes metadata from memory to the JSON file and cleans up the directory.
*/
virtual ~CacheAndPersist();
CacheAndPersist( const CacheAndPersist & ) = delete;
CacheAndPersist &operator=( const CacheAndPersist & ) = delete;
CacheAndPersist( CacheAndPersist && ) = delete;
CacheAndPersist &operator=( CacheAndPersist && ) = delete;
/**
* @brief Writes to the non volatile memory(NVM) from buffer based on datatype and filename.
*
* @param bufPtr buffer location that contains the data to be written
* @param size size of the data to be written
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename specifies file for the data to be written to, only valid for edge to cloud payload
*
* @return ErrorCode SUCCESS if the write is successful,
* MEMORY_FULL if the partition size is reached,
* INVALID_DATA if the buffer ptr is NULL,
* INVALID_DATATYPE if filename is empty,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
virtual ErrorCode write( const uint8_t *bufPtr,
size_t size,
DataType dataType,
const std::string &filename = std::string() );
/**
* @brief Writes to the non volatile memory(NVM) from stream based on datatype and filename
*
* @param streambuf data stream to write the data from
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename full name of the file to store
*
* @return ErrorCode SUCCESS if the write is successful,
* MEMORY_FULL if the partition size is reached,
* INVALID_DATA if the buffer ptr is NULL,
* INVALID_DATATYPE if filename is empty,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
ErrorCode write( std::streambuf &streambuf, DataType dataType, const std::string &filename = std::string() );
/**
* @brief Adds new file metadata to existing JSON object.
*
* @param metadata JSON object of the file metadata to persist
*/
void addMetadata( const Json::Value &metadata );
/**
* @brief Gets the size of data based on the datatype.
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename filename to get size for
*
* @return size of the persisted data of specified type.
*/
virtual size_t getSize( DataType dataType, const std::string &filename = std::string() );
/**
* @brief Gets the size of metadata object transformed into string stored in memory.
*
* @return size of the metadata.
*/
size_t getMetadataSize();
/**
* @brief Reads the persisted data of specified datatype in a pre-allocated buffer.
*
* @param readBufPtr pointer to a buffer location where data should be read
* @param size size to be read
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename specifies file for the data to read, only valid for edge to cloud payload
*
* @return ErrorCode SUCCESS if the read is successful,
* EMPTY if there was no data to read,
* MEMORY_FULL if provided size is bigger than max size used by persistency library,
* INVALID_DATATYPE if provided datatype has no associated file,
* INVALID_DATA if the buffer ptr is NULL or the actual size differs from the provided,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
virtual ErrorCode read( uint8_t *const readBufPtr,
size_t size,
DataType dataType,
const std::string &filename = std::string() );
/**
* @brief Reads the persisted data of specified datatype in a file stream
*
* @param fileStream the file stream that will point to the file being requested
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename specifies file for the data to read, only valid for edge to cloud payload
*
* @return ErrorCode SUCCESS if the read is successful,
* INVALID_DATATYPE if provided datatype has no associated file,
*/
virtual ErrorCode read( std::ifstream &fileStream, DataType dataType, const std::string &filename = std::string() );
/**
* @brief Deletes persisted data for the specified data type and filename.
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
* @param filename specifies file for the data to delete, only valid for edge to cloud payload
*
* @return ErrorCode SUCCESS if the delete is successful or file does not exist,
* INVALID_DATATYPE if provided datatype does not have associated filename,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
ErrorCode erase( DataType dataType, const std::string &filename = std::string() );
/**
* @brief Deletes persisted metadata.
*
* @return ErrorCode SUCCESS if the delete is successful,
* EMPTY if there was no data to erase,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
void clearMetadata();
/**
* @brief Returns a text representation of the error for better readable logging
* @param err the error code to convert to string
* @return never a nullptr, "UNKNOWN" in case of unknown string representation
*
*/
static const char *getErrorString( ErrorCode err );
/**
* @brief Returns metadata JSON object stored in memory
*/
Json::Value getMetadata();
/**
* @brief Initializes the library by checking if the files exist and creating if necessary
*
* @return true if successful, else false.
*/
bool init();
private:
// Define File names for the components using the lib
static constexpr const char *DECODER_MANIFEST_FILE = "DecoderManifest.bin";
static constexpr const char *COLLECTION_SCHEME_LIST_FILE = "CollectionSchemeList.bin";
#ifdef FWE_FEATURE_LAST_KNOWN_STATE
static constexpr const char *STATE_TEMPLATE_LIST_FILE = "StateTemplateList.bin";
static constexpr const char *STATE_TEMPLATE_LIST_METADATA_FILE = "StateTemplateListMetadata.json";
#endif
static constexpr const char *PAYLOAD_METADATA_FILE = "PayloadMetadata.json";
// Folder to isolate persistency workspace
static constexpr const char *PERSISTENCY_WORKSPACE = "FWE_Persistency/";
// Folder for payload files
static constexpr const char *COLLECTED_DATA_FOLDER = "CollectedData/";
// Deprecated files to clean
static constexpr const char *DEPRECATED_COLLECTED_DATA_FILE = "CollectedData.bin";
static constexpr const char *METADATA_SCHEME_VERSION = "1.0.0";
// Estimate size of metadata: expected average for Proto payload is 100, for Ion 200-250
static constexpr size_t ESTIMATED_METADATA_SIZE_PER_FILE = 400;
std::string mPersistencyPath;
std::string mPersistencyWorkspace;
std::string mDecoderManifestFile;
std::string mCollectionSchemeListFile;
#ifdef FWE_FEATURE_LAST_KNOWN_STATE
std::string mStateTemplateListFile;
std::string mStateTemplateListMetadataFile;
#endif
std::string mPayloadMetadataFile;
std::string mCollectedDataPath;
std::uintmax_t mMaxPersistencePartitionSize;
Json::Value mPersistedMetadata;
/**
* @brief Writes JSON object from memory to the JSON file.
*
* @param metadata JSON object with new metadata to persist
*
* @return true if write operation succeeded
*/
bool writeMetadata( Json::Value &metadata );
/**
* @brief Returns filename for the specific datatype
*
* @param dataType specifies if the data is an edge to cloud payload, collectionScheme list, etc.
*
* @return filename defined for the datatype
*/
std::string getFileName( DataType dataType );
/**
* @brief Gets the size of all persisted data, incl. decoder manifest, collection scheme, metadata, and all
* payloads.
*
* @return size of all persisted data.
*/
std::uintmax_t getTotalSize();
/**
* @brief Writes to the non volatile memory(NVM) to the given path from buffer.
*
* @param bufPtr buffer location that contains the data to be written
* @param size size of the data to be written
* @param path filename to write data
*
* @return ErrorCode SUCCESS if the write is successful,
* MEMORY_FULL if the partition size is reached,
* INVALID_DATA if the buffer ptr is NULL,
* INVALID_DATATYPE if filename is empty
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
ErrorCode write( const uint8_t *bufPtr, size_t size, std::string &path );
/**
* @brief Reads the persisted data from specified path in a pre-allocated buffer.
*
* @param readBufPtr pointer to a buffer location where data should be read
* @param size size to be read
* @param path file to read data from
*
* @return ErrorCode SUCCESS if the read is successful,
* EMPTY if there was no data to read,
* MEMORY_FULL if provided size is bigger than max size used by persistency library,
* INVALID_DATA if the buffer ptr is NULL or the actual size differs from the provided,
* INVALID_DATATYPE if filename is empty,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
ErrorCode read( uint8_t *const readBufPtr, size_t size, std::string &path ) const;
/**
* @brief Reads the persisted metadata from JSON file in a JSON object.
*
* @param metadata JSON object to store persisted metadata
*
* @return ErrorCode SUCCESS if the read is successful,
* EMPTY if there was no data to read,
* INVALID_DATA if the buffer ptr is NULL,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
ErrorCode readMetadata( Json::Value &metadata );
/**
* @brief Deletes specified file
* @param path path to the file to delete.
*
* @return ErrorCode SUCCESS if the delete is successful or file does not exist,
* INVALID_DATATYPE if filename is empty,
* FILESYSTEM_ERROR in case of any file I/O errors.
*/
static ErrorCode erase( std::string &path );
/**
* @brief Gets the size of data store in the file
* @param path path to the file where the data is stored
*
* @return size of the persisted data in the file.
*/
static size_t getSize( const std::string &path );
/**
* @brief Deletes all files from the persistency folder that do not have associated metadata or are not reserved for
* collection schemes and decoder manifest.
*
* @return ErrorCode SUCCESS if cleanup was completed,
* FILESYSTEM_ERROR in case of any file I/O errors or if directory does not exist.
*/
ErrorCode cleanupPersistedData();
/**
* @brief This function is called when component is initialised. It deletes all files, including deprecated, that
* were written by FWE to the root persistency folder.
*
* @return ErrorCode SUCCESS if cleanup was completed,
* FILESYSTEM_ERROR in case of any file I/O errors or if directory does not exist.
*/
ErrorCode cleanupDeprecatedFiles();
};
} // namespace IoTFleetWise
} // namespace Aws