From efe90849ca74956b8b04a4943629a0b13c5f3ae8 Mon Sep 17 00:00:00 2001 From: Ed Gamble Date: Fri, 25 Jan 2019 11:09:45 -0800 Subject: [PATCH] CORE-207: BRFileService error handling (part #1, on fileServiceSave). Update BREthereumEWM and BRWalletManager for fileService error handling. --- BRWalletManager.c | 63 +++++++++++++++----------- ethereum/ewm/BREthereumEWM.c | 77 +++++++++++++++++-------------- support/BRFileService.c | 88 +++++++++++++++++++++--------------- support/BRFileService.h | 31 +++++++++++-- 4 files changed, 161 insertions(+), 98 deletions(-) diff --git a/BRWalletManager.c b/BRWalletManager.c index 4d7a39e53..3101cfa8e 100644 --- a/BRWalletManager.c +++ b/BRWalletManager.c @@ -357,6 +357,17 @@ bwmFileServiceErrorHandler (BRFileServiceContext context, /// /// MARK: Wallet Manager /// +static BRWalletManager +bwmCreateErrorHandler (BRWalletManager bwm, int fileService, const char* reason) { + if (NULL != bwm) free (bwm); + if (fileService) + _peer_log ("bread: on ewmCreate: FileService Error: %s", reason); + else + _peer_log ("bread: on ewmCreate: Error: %s", reason); + + return NULL; +} + extern BRWalletManager BRWalletManagerNew (BRWalletManagerClient client, BRMasterPubKey mpk, @@ -364,7 +375,7 @@ BRWalletManagerNew (BRWalletManagerClient client, uint32_t earliestKeyTime, const char *baseStoragePath) { BRWalletManager manager = malloc (sizeof (struct BRWalletManagerStruct)); - if (NULL == manager) return NULL; + if (NULL == manager) return bwmCreateErrorHandler (NULL, 0, "allocate"); // manager->walletForkId = fork; manager->client = client; @@ -379,37 +390,37 @@ BRWalletManagerNew (BRWalletManagerClient client, manager->fileService = fileServiceCreate (baseStoragePath, networkName, currencyName, manager, bwmFileServiceErrorHandler); - if (NULL == manager->fileService) { free (manager); return NULL; } + if (NULL == manager->fileService) return bwmCreateErrorHandler (manager, 1, "create"); /// Transaction - fileServiceDefineType (manager->fileService, fileServiceTypeTransactions, - (BRFileServiceContext) manager, - WALLET_MANAGER_TRANSACTION_VERSION_1, - fileServiceTypeTransactionV1Identifier, - fileServiceTypeTransactionV1Reader, - fileServiceTypeTransactionV1Writer); - fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypeTransactions, - WALLET_MANAGER_TRANSACTION_VERSION_1); + if (1 != fileServiceDefineType (manager->fileService, fileServiceTypeTransactions, WALLET_MANAGER_TRANSACTION_VERSION_1, + (BRFileServiceContext) manager, + fileServiceTypeTransactionV1Identifier, + fileServiceTypeTransactionV1Reader, + fileServiceTypeTransactionV1Writer) || + 1 != fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypeTransactions, + WALLET_MANAGER_TRANSACTION_VERSION_1)) + return bwmCreateErrorHandler (manager, 1, fileServiceTypeTransactions); /// Block - fileServiceDefineType (manager->fileService, fileServiceTypeBlocks, - (BRFileServiceContext) manager, - WALLET_MANAGER_BLOCK_VERSION_1, - fileServiceTypeBlockV1Identifier, - fileServiceTypeBlockV1Reader, - fileServiceTypeBlockV1Writer); - fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypeBlocks, - WALLET_MANAGER_BLOCK_VERSION_1); + if (1 != fileServiceDefineType (manager->fileService, fileServiceTypeBlocks, WALLET_MANAGER_BLOCK_VERSION_1, + (BRFileServiceContext) manager, + fileServiceTypeBlockV1Identifier, + fileServiceTypeBlockV1Reader, + fileServiceTypeBlockV1Writer) || + 1 != fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypeBlocks, + WALLET_MANAGER_BLOCK_VERSION_1)) + return bwmCreateErrorHandler (manager, 1, fileServiceTypeBlocks); /// Peer - fileServiceDefineType (manager->fileService, fileServiceTypePeers, - (BRFileServiceContext) manager, - WALLET_MANAGER_PEER_VERSION_1, - fileServiceTypePeerV1Identifier, - fileServiceTypePeerV1Reader, - fileServiceTypePeerV1Writer); - fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypePeers, - WALLET_MANAGER_PEER_VERSION_1); + if (1 != fileServiceDefineType (manager->fileService, fileServiceTypePeers, WALLET_MANAGER_PEER_VERSION_1, + (BRFileServiceContext) manager, + fileServiceTypePeerV1Identifier, + fileServiceTypePeerV1Reader, + fileServiceTypePeerV1Writer) || + 1 != fileServiceDefineCurrentVersion (manager->fileService, fileServiceTypePeers, + WALLET_MANAGER_PEER_VERSION_1)) + return bwmCreateErrorHandler (manager, 1, fileServiceTypePeers); /// Load transactions for the wallet manager. BRArrayOf(BRTransaction*) transactions = initialTransactionsLoad(manager); diff --git a/ethereum/ewm/BREthereumEWM.c b/ethereum/ewm/BREthereumEWM.c index 560b67de9..db516a191 100644 --- a/ethereum/ewm/BREthereumEWM.c +++ b/ethereum/ewm/BREthereumEWM.c @@ -342,6 +342,16 @@ ewmFileServiceErrorHandler (BRFileServiceContext context, /// /// MARK: Ethereum Wallet Manager /// +static BREthereumEWM +ewmCreateErrorHandler (BREthereumEWM ewm, int fileService, const char* reason) { + if (NULL != ewm) free (ewm); + if (fileService) + eth_log ("EWM", "on ewmCreate: FileService Error: %s", reason); + else + eth_log ("EWM", "on ewmCreate: Error: %s", reason); + + return NULL; +} extern BREthereumEWM ewmCreate (BREthereumNetwork network, @@ -379,47 +389,48 @@ ewmCreate (BREthereumNetwork network, ewm->fs = fileServiceCreate (storagePath, networkGetName(network), "eth", ewm, ewmFileServiceErrorHandler); - if (NULL == ewm->fs) { free (ewm); return NULL; } + if (NULL == ewm->fs) return ewmCreateErrorHandler(ewm, 1, "create"); /// Transaction - fileServiceDefineType (ewm->fs, fileServiceTypeTransactions, - (BRFileServiceContext) ewm, - EWM_TRANSACTION_VERSION_1, - fileServiceTypeTransactionV1Identifier, - fileServiceTypeTransactionV1Reader, - fileServiceTypeTransactionV1Writer); - fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeTransactions, - EWM_TRANSACTION_VERSION_1); + if (1 != fileServiceDefineType (ewm->fs, fileServiceTypeTransactions, EWM_TRANSACTION_VERSION_1, + (BRFileServiceContext) ewm, + fileServiceTypeTransactionV1Identifier, + fileServiceTypeTransactionV1Reader, + fileServiceTypeTransactionV1Writer) || + 1 != fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeTransactions, + EWM_TRANSACTION_VERSION_1)) + return ewmCreateErrorHandler(ewm, 1, fileServiceTypeTransactions); /// Log - fileServiceDefineType (ewm->fs, fileServiceTypeLogs, - (BRFileServiceContext) ewm, - EWM_LOG_VERSION_1, - fileServiceTypeLogV1Identifier, - fileServiceTypeLogV1Reader, - fileServiceTypeLogV1Writer); - fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeLogs, - EWM_LOG_VERSION_1); + if (1 != fileServiceDefineType (ewm->fs, fileServiceTypeLogs, EWM_LOG_VERSION_1, + (BRFileServiceContext) ewm, + fileServiceTypeLogV1Identifier, + fileServiceTypeLogV1Reader, + fileServiceTypeLogV1Writer) || + 1 != fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeLogs, + EWM_LOG_VERSION_1)) + return ewmCreateErrorHandler(ewm, 1, fileServiceTypeLogs); /// Peer - fileServiceDefineType (ewm->fs, fileServiceTypeNodes, - (BRFileServiceContext) ewm, - EWM_NODE_VERSION_1, - fileServiceTypeNodeV1Identifier, - fileServiceTypeNodeV1Reader, - fileServiceTypeNodeV1Writer); - fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeNodes, - EWM_NODE_VERSION_1); + if (1 != fileServiceDefineType (ewm->fs, fileServiceTypeNodes, EWM_NODE_VERSION_1, + (BRFileServiceContext) ewm, + fileServiceTypeNodeV1Identifier, + fileServiceTypeNodeV1Reader, + fileServiceTypeNodeV1Writer) || + 1 != fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeNodes, + EWM_NODE_VERSION_1)) + return ewmCreateErrorHandler(ewm, 1, fileServiceTypeNodes); + /// Block - fileServiceDefineType (ewm->fs, fileServiceTypeBlocks, - (BRFileServiceContext) ewm, - EWM_BLOCK_VERSION_1, - fileServiceTypeBlockV1Identifier, - fileServiceTypeBlockV1Reader, - fileServiceTypeBlockV1Writer); - fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeBlocks, - EWM_BLOCK_VERSION_1); + if (1 != fileServiceDefineType (ewm->fs, fileServiceTypeBlocks, EWM_BLOCK_VERSION_1, + (BRFileServiceContext) ewm, + fileServiceTypeBlockV1Identifier, + fileServiceTypeBlockV1Reader, + fileServiceTypeBlockV1Writer) || + 1 != fileServiceDefineCurrentVersion (ewm->fs, fileServiceTypeBlocks, + EWM_BLOCK_VERSION_1)) + return ewmCreateErrorHandler(ewm, 1, fileServiceTypeBlocks); // Load all the persistent entities BRSetOf(BREthereumTransaction) transactions = initialTransactionsLoad(ewm); diff --git a/support/BRFileService.c b/support/BRFileService.c index e5148a1f6..8d25f32b8 100644 --- a/support/BRFileService.c +++ b/support/BRFileService.c @@ -201,10 +201,10 @@ fileServiceLookupEntityHandler (const BRFileService fs, } /// -/// MARK: Load +/// MARK: Failure Reporting /// static int -fileServiceLoadFailedInternal (BRFileService fs, +fileServiceFailedInternal (BRFileService fs, void* bufferToFree, FILE* fileToClose, BRFileServiceError error) { @@ -218,11 +218,11 @@ fileServiceLoadFailedInternal (BRFileService fs, } static int -fileServiceLoadFailedImpl(BRFileService fs, +fileServiceFailedImpl(BRFileService fs, void* bufferToFree, FILE* fileToClose, const char *reason) { - return fileServiceLoadFailedInternal (fs, bufferToFree, fileToClose, + return fileServiceFailedInternal (fs, bufferToFree, fileToClose, (BRFileServiceError) { FILE_SERVICE_IMPL, { .impl = { reason }} @@ -230,11 +230,11 @@ fileServiceLoadFailedImpl(BRFileService fs, } static int -fileServiceLoadFailedUnix(BRFileService fs, +fileServiceFailedUnix(BRFileService fs, void* bufferToFree, FILE* fileToClose, int error) { - return fileServiceLoadFailedInternal (fs, bufferToFree, fileToClose, + return fileServiceFailedInternal (fs, bufferToFree, fileToClose, (BRFileServiceError) { FILE_SERVICE_UNIX, { .unix = { error }} @@ -242,28 +242,31 @@ fileServiceLoadFailedUnix(BRFileService fs, } static int -fileServiceLoadFailedEntity(BRFileService fs, +fileServiceFailedEntity(BRFileService fs, void* bufferToFree, FILE* fileToClose, const char *type, const char *reason) { - return fileServiceLoadFailedInternal (fs, bufferToFree, fileToClose, + return fileServiceFailedInternal (fs, bufferToFree, fileToClose, (BRFileServiceError) { FILE_SERVICE_ENTITY, { .entity = { type, reason }} }); } +/// +/// MARK: Load +/// extern int fileServiceLoad (BRFileService fs, BRSet *results, const char *type, int updateVersion) { BRFileServiceEntityType *entityType = fileServiceLookupType (fs, type); - if (NULL == entityType) return fileServiceLoadFailedImpl (fs, NULL, NULL, "missed type"); + if (NULL == entityType) return fileServiceFailedImpl (fs, NULL, NULL, "missed type"); BRFileServiceEntityHandler *entityHandlerCurrent = fileServiceEntityTypeLookupHandler(entityType, entityType->currentVersion); - if (NULL == entityHandlerCurrent) return fileServiceLoadFailedImpl (fs, NULL, NULL, "missed type handler"); + if (NULL == entityHandlerCurrent) return fileServiceFailedImpl (fs, NULL, NULL, "missed type handler"); DIR *dir; struct dirent *dirEntry; @@ -274,7 +277,7 @@ fileServiceLoad (BRFileService fs, char filename[strlen(dirPath) + 1 + 2 * sizeof(UInt256) + 1]; if (-1 == directoryMake(dirPath) || NULL == (dir = opendir(dirPath))) - return fileServiceLoadFailedUnix (fs, NULL, NULL, errno); + return fileServiceFailedUnix (fs, NULL, NULL, errno); // Allocate some storage for entity bytes; size_t bufferSize = 8 * 1024; @@ -285,7 +288,7 @@ fileServiceLoad (BRFileService fs, if (dirEntry->d_type == DT_REG) { sprintf (filename, "%s/%s", dirPath, dirEntry->d_name); FILE *file = fopen (filename, "rb"); - if (NULL == file) return fileServiceLoadFailedUnix (fs, buffer, NULL, errno); + if (NULL == file) return fileServiceFailedUnix (fs, buffer, NULL, errno); BRFileServiceVersion version; @@ -294,7 +297,7 @@ fileServiceLoad (BRFileService fs, // read the header version BRFileServiceHeaderFormatVersion headerVersion; if (1 != fread (&headerVersion, sizeof(BRFileServiceHeaderFormatVersion), 1, file)) - return fileServiceLoadFailedUnix (fs, buffer, file, errno); + return fileServiceFailedUnix (fs, buffer, file, errno); // read the header switch (headerVersion) { @@ -304,7 +307,7 @@ fileServiceLoad (BRFileService fs, // read the checksum // read the bytesCount 1 != fread (&bytesCount, sizeof(uint32_t), 1, file)) - return fileServiceLoadFailedUnix (fs, buffer, file, errno); + return fileServiceFailedUnix (fs, buffer, file, errno); break; } @@ -318,13 +321,13 @@ fileServiceLoad (BRFileService fs, // read the bytes - multiple might be required if (bytesCount != fread (buffer, 1, bytesCount, file)) - return fileServiceLoadFailedUnix (fs, buffer, file, errno); + return fileServiceFailedUnix (fs, buffer, file, errno); // All file reading is complete; next read should be EOF. // Done with file. if (0 != fclose (file)) - return fileServiceLoadFailedUnix (fs, buffer, NULL, errno); + return fileServiceFailedUnix (fs, buffer, NULL, errno); // We now have everything @@ -341,11 +344,11 @@ fileServiceLoad (BRFileService fs, // Look up the entity handler BRFileServiceEntityHandler *handler = fileServiceEntityTypeLookupHandler(entityType, version); - if (NULL == handler) return fileServiceLoadFailedImpl (fs, buffer, NULL, "missed type handler"); + if (NULL == handler) return fileServiceFailedImpl (fs, buffer, NULL, "missed type handler"); // Read the entity from buffer and add to results. void *entity = handler->reader (handler->context, fs, buffer, bytesCount); - if (NULL == entity) return fileServiceLoadFailedEntity (fs, buffer, NULL, type, "reader"); + if (NULL == entity) return fileServiceFailedEntity (fs, buffer, NULL, type, "reader"); // Update restuls with the newly restored entity BRSetAdd (results, entity); @@ -363,15 +366,18 @@ fileServiceLoad (BRFileService fs, return 1; } +/// +/// MARK: Save +/// extern void /* error code? */ fileServiceSave (BRFileService fs, const char *type, /* block, peers, transactions, logs, ... */ const void *entity) { /* BRMerkleBlock*, BRTransaction, BREthereumTransaction, ... */ BRFileServiceEntityType *entityType = fileServiceLookupType (fs, type); - if (NULL == entityType) return; + if (NULL == entityType) { fileServiceFailedImpl (fs, NULL, NULL, "missed type"); return; }; BRFileServiceEntityHandler *handler = fileServiceEntityTypeLookupHandler(entityType, entityType->currentVersion); - if (NULL == handler) return; + if (NULL == handler) { fileServiceFailedImpl (fs, NULL, NULL, "missed type handler"); return; }; UInt256 identifier = handler->identifier (handler->context, fs, entity); @@ -382,9 +388,8 @@ fileServiceSave (BRFileService fs, sprintf (filename, "%s/%s/%s", fs->pathToType, type, u256hex(identifier)); FILE *file = fopen (filename, "wb"); - if (NULL == file) { + if (NULL == file) { fileServiceFailedUnix (fs, bytes, NULL, errno); return; } - } // Always, always write the header for the currentHeaderFormatVersion @@ -395,30 +400,35 @@ fileServiceSave (BRFileService fs, // then the checksum? // write the bytesCount 1 != fwrite(&bytesCount, sizeof (uint32_t), 1, file)) { - + fileServiceFailedUnix (fs, bytes, file, errno); + return; } // write the bytes. if (bytesCount != fwrite(bytes, 1, bytesCount, file)) { - + fileServiceFailedUnix (fs, bytes, file, errno); + return; } - if (0 != fclose (file)) { + if (0 != fclose (file)) { fileServiceFailedUnix (fs, bytes, NULL, errno); return; } - } free (bytes); } +/// +/// MARK: Remve, Clear +/// extern void fileServiceRemove (BRFileService fs, const char *type, UInt256 identifier) { BRFileServiceEntityType *entityType = fileServiceLookupType (fs, type); - if (NULL == entityType) return; + if (NULL == entityType) { fileServiceFailedImpl (fs, NULL, NULL, "missed type"); return; }; char filename[strlen(fs->pathToType) + 1 + strlen(type) + 1 + 2*sizeof(UInt256) + 1]; sprintf (filename, "%s/%s/%s", fs->pathToType, type, u256hex(identifier)); + // If failed, then what? remove (filename); } @@ -432,13 +442,13 @@ fileServiceClearForType (BRFileService fs, sprintf (dirPath, "%s/%s", fs->pathToType, entityType->type); if (-1 == directoryMake(dirPath) || NULL == (dir = opendir(dirPath))) { - //*error = errno; + fileServiceFailedUnix (fs, NULL, NULL, errno); return; } while (NULL != (dirEntry = readdir(dir))) if (dirEntry->d_type == DT_REG) - remove (dirEntry->d_name); + remove (dirEntry->d_name); // If failed, then what? closedir(dir); } @@ -447,7 +457,8 @@ extern void fileServiceClear (BRFileService fs, const char *type) { BRFileServiceEntityType *entityType = fileServiceLookupType (fs, type); - if (NULL == type) return; + if (NULL == entityType) { fileServiceFailedImpl (fs, NULL, NULL, "missed type"); return; }; + fileServiceClearForType(fs, entityType); } @@ -459,11 +470,11 @@ fileServiceClearAll (BRFileService fs) { } -extern void +extern int fileServiceDefineType (BRFileService fs, const char *type, - BRFileServiceContext context, BRFileServiceVersion version, + BRFileServiceContext context, BRFileServiceIdentifier identifier, BRFileServiceReader reader, BRFileServiceWriter writer) { @@ -497,22 +508,27 @@ fileServiceDefineType (BRFileService fs, char dirPath[strlen(fs->pathToType) + 1 + strlen(type) + 1]; sprintf (dirPath, "%s/%s", fs->pathToType, type); - if (-1 == directoryMake(dirPath)) return; + if (-1 == directoryMake(dirPath)) + return fileServiceFailedUnix (fs, NULL, NULL, errno); } + + return 1; } -extern void +extern int fileServiceDefineCurrentVersion (BRFileService fs, const char *type, BRFileServiceVersion version) { // Find the entityType for `type` BRFileServiceEntityType *entityType = fileServiceLookupType (fs, type); - if (NULL == entityType) return; + if (NULL == entityType) return fileServiceFailedImpl (fs, NULL, NULL, "missed type"); // Find the entityHandler, for version. BRFileServiceEntityHandler *entityHandler = fileServiceEntityTypeLookupHandler (entityType, version); - if (NULL == entityHandler) return; + if (NULL == entityHandler) return fileServiceFailedImpl (fs, NULL, NULL, "missed type handler"); // We have a handler, therefore it can be the current one. entityType->currentVersion = version; + + return 1; } diff --git a/support/BRFileService.h b/support/BRFileService.h index 78831d36c..afc55aa69 100644 --- a/support/BRFileService.h +++ b/support/BRFileService.h @@ -128,33 +128,58 @@ fileServiceClear (BRFileService fs, extern void fileServiceClearAll (BRFileService fs); +/** + * A function type to produce an identifer from an entity. The identifer must be constant for + * a particulary entity through time. The identifier is used to derive a filename (more generally + * a path and filename). + */ typedef UInt256 (*BRFileServiceIdentifier) (BRFileServiceContext context, BRFileService fs, const void* entity); +/** + * A function type to read an entity from a byte array. You own the entity. + */ typedef void* (*BRFileServiceReader) (BRFileServiceContext context, BRFileService fs, uint8_t *bytes, uint32_t bytesCount); +/** + * A function type to write an entity to a byte array. You own the byte array. + */ typedef uint8_t* (*BRFileServiceWriter) (BRFileServiceContext context, BRFileService fs, const void* entity, uint32_t *bytesCount); -extern void +/** + * Define a 'type', such as {block, peer, transaction, logs, etc}, that is to be stored in the + * file system. + * + * @param fs the file service + * @param type the type + * @param context an arbitrary value to be passed to the type-specific functions. + * @param version the entity version handled by the type-specific functions. + * @param identifier the function that produces the identifier + * @param reader the function the produces an entity from a byte array + * @param writer the function that produces a byte array from an entity. + * + * @return true (1) if success, false (0) otherwise + */ +extern int fileServiceDefineType (BRFileService fs, const char *type, - BRFileServiceContext context, BRFileServiceVersion version, + BRFileServiceContext context, BRFileServiceIdentifier identifier, BRFileServiceReader reader, BRFileServiceWriter writer); -extern void +extern int fileServiceDefineCurrentVersion (BRFileService fs, const char *type, BRFileServiceVersion version);