From 7d397aedf857d3af39372fdf6fdc6a292ede87ac Mon Sep 17 00:00:00 2001 From: Ingo Huerner Date: Thu, 1 Jun 2017 14:24:38 +0200 Subject: Update after static code analysis; Added test for crashed app handling; removed obsolete test data --- configure.ac | 13 + src/key-value-store/database/kissdb.c | 107 +++++ src/key-value-store/database/kissdb.h | 9 + src/key-value-store/pers_low_level_db_access.c | 179 +++---- test/Makefile.am | 7 +- test/data/attachToExistingCache.tar.gz | Bin 27821 -> 0 bytes test/test_pco_key_value_store.c | 632 ++++++++++++++++++++----- 7 files changed, 730 insertions(+), 217 deletions(-) delete mode 100644 test/data/attachToExistingCache.tar.gz diff --git a/configure.ac b/configure.ac index 959567c..1bf051c 100644 --- a/configure.ac +++ b/configure.ac @@ -215,6 +215,19 @@ fi +dnl ********************************************** +dnl *** location of pidfile, default is /var/run * +dnl ********************************************** +AC_ARG_WITH([pidfilelocation], + [AS_HELP_STRING([--with-pidfilelocation=path of pidfile],[Path to the pifile])], + [with_pidfilelocation=$withval],[with_pidfilelocation="/var/run"]) + +AC_SUBST([pidfilelocationpath], [$with_pidfilelocation]) +AC_MSG_NOTICE([PID File Path: $pidfilelocationpath]) +AC_DEFINE_UNQUOTED(PIDFILEDIR, "$pidfilelocationpath", "location for pidfile") + + + ###################################################################### ### max numberr of database slots, default is 100.000 ###################################################################### diff --git a/src/key-value-store/database/kissdb.c b/src/key-value-store/database/kissdb.c index 98df052..c575508 100644 --- a/src/key-value-store/database/kissdb.c +++ b/src/key-value-store/database/kissdb.c @@ -20,6 +20,9 @@ #define _FILE_OFFSET_BITS 64 #define KISSDB_HEADER_SIZE sizeof(Header_s) +#define FILE_DIR_NOT_SELF_OR_PARENT(s) ((s)[0]!='.'&&(((s)[1]!='.'||(s)[2]!='\0')||(s)[1]=='\0')) + + #include "./kissdb.h" #include "../crc32.h" #include @@ -35,6 +38,7 @@ #include #include #include +#include #include "persComErrors.h" // @@ -541,6 +545,17 @@ int KISSDB_open(KISSDB* db, const char* path, int openMode, int writeMode, uint1 } } } + else + { + // we are not the shm creator, now check if someone else has the file open + // if num of open fd's and ref count does not match, report an error and don't increment ref counter + //printf("#### Database closed N O T O K - %d!!!!!\n\n", db->shared->refCount); + if(searchOpenFDs(path) != db->shared->refCount) + { + Kdb_unlock(&db->shared->rwlock); + return KISSDB_ERROR_APPCRASH; + } + } Kdb_unlock(&db->shared->rwlock); return 0; } @@ -1511,6 +1526,98 @@ int checkErrorFlags(KISSDB* db) } + +int searchProcFileSys(pid_t pid, const char* path) +{ + int rval = 0; + DIR* procdir; + struct dirent* procDirEnt; + char procPidDir[128] = {0}; + + memset(procPidDir, 0, 128); + snprintf(procPidDir, 128, "/proc/%d/fd", pid); + + if((procdir = opendir(procPidDir)) != NULL) // search for open fd's + { + for(procDirEnt = readdir(procdir); NULL != procDirEnt; procDirEnt = readdir(procdir)) + { + if(FILE_DIR_NOT_SELF_OR_PARENT(procDirEnt->d_name)) + { + char buffer[128] = {0}; + char fullPath[256] = {0}; + memset(buffer, 0, 128); + memset(fullPath, 0, 256); + + snprintf(fullPath, 256, "%s/%s", procPidDir, procDirEnt->d_name); + if(readlink(fullPath, buffer, 128) != -1) + { + if(strcmp(path, buffer) == 0) + { + //printf(" FOUND [%d]: %s | %s | %s\n", pid, path, fullPath, buffer); + rval = 1; + break; + } + } + else + { + printf("Error readlink: %s\n", strerror(errno)); + } + } + } + closedir(procdir); + } + + return rval; +} + + +int searchOpenFDs(const char* path) +{ + DIR* dir; + struct dirent* ent; + int rval = 0; + int fd = -1; + + if ((dir = opendir(PIDFILEDIR)) != NULL) // search for pidfiles + { + for(ent = readdir(dir); NULL != ent; ent = readdir(dir)) + { + if(FILE_DIR_NOT_SELF_OR_PARENT(ent->d_name)) + { + if(strstr(ent->d_name, PIDFILE_PREFIX) != NULL) + { + // extract the PID form filename + char pidArray[10] = {0}; + char* pidArrayPtr = pidArray; + pid_t pid = 0; + int start = strlen(PIDFILE_PREFIX); + memset(pidArray, 0, 10); + + while(ent->d_name[start] != '.') + { + *(pidArrayPtr)++ = ent->d_name[start++]; + } + pid = atoi(pidArray); + if(getpid() != pid) // check only other pids not own + { + if(searchProcFileSys(pid, path) == 1) + { + rval++; // count number of open fd's + } + } + } + } + } + closedir(dir); + } + else + { + printf("Failed to open directory %s: %s\n", PIDFILEDIR, strerror(errno)); + } + + return rval; +} + int verifyHashtableCS(KISSDB* db) { char* ptr; diff --git a/src/key-value-store/database/kissdb.h b/src/key-value-store/database/kissdb.h index b28e306..3a22dd3 100644 --- a/src/key-value-store/database/kissdb.h +++ b/src/key-value-store/database/kissdb.h @@ -62,6 +62,9 @@ extern "C" { #endif +#define PIDFILE_PREFIX "perslib_" +#define PIDFILE_TEMPLATE PIDFILEDIR "/" PIDFILE_PREFIX"%d.pid" // PIDFILEDIR is defined via configure switch -pidfiledir (default is /var/run if not set) + /** * Version: 2.3 * @@ -247,6 +250,12 @@ typedef struct { * buffer where data should be returned is too small */ #define KISSDB_ERROR_WRONG_BUFSIZE -13 + + +/** + * don't increment ref counter, possible application detected + */ +#define KISSDB_ERROR_APPCRASH -14 /** diff --git a/src/key-value-store/pers_low_level_db_access.c b/src/key-value-store/pers_low_level_db_access.c index 29f535e..c8199d2 100644 --- a/src/key-value-store/pers_low_level_db_access.c +++ b/src/key-value-store/pers_low_level_db_access.c @@ -45,21 +45,6 @@ DltContext persComLldbDLTCtx; DLT_DECLARE_CONTEXT (persComLldbDLTCtx) - - -///// library constructor -//void pco_library_init(void) __attribute__((constructor)); -//void pco_library_init() { -// printf ("\n pco_library_init() constructor \n"); -//} -// -///// library destructor -//void pco_library_destroy(void) __attribute__((destructor)); -//void pco_library_destroy() { -// printf ("\n pco_library_destroy() destructor \n"); -//} - - /* ---------------------- local definition ---------------------------- */ /* max number of open handlers per process */ #define PERS_LLDB_NO_OF_STATIC_HANDLES 16 @@ -69,6 +54,7 @@ DLT_DECLARE_CONTEXT (persComLldbDLTCtx) #define SEM_TIMEDWAIT_TIMEOUT 5 // wait for seconds until sem_timedwait fails + typedef struct { char m_data[PERS_DB_MAX_SIZE_KEY_DATA]; @@ -129,7 +115,7 @@ static struct timespec gSemWaitTimeout; /* ---------------------- local functions --------------------------------- */ static sint_t DeleteDataFromKissDB(sint_t dbHandler, pconststr_t key); -static sint_t DeleteDataFromKissRCT(sint_t dbHandler, pconststr_t key); +//static sint_t DeleteDataFromKissRCT(sint_t dbHandler, pconststr_t key); static sint_t GetAllKeysFromKissLocalDB(sint_t dbHandler, pstr_t buffer, sint_t size); static sint_t GetAllKeysFromKissRCT(sint_t dbHandler, pstr_t buffer, sint_t size); static sint_t GetKeySizeFromKissLocalDB(sint_t dbHandler, pconststr_t key); @@ -160,7 +146,6 @@ static int openCache(KISSDB* db); static int closeCache(KISSDB* db); - __attribute__((constructor)) static void pco_library_init() { @@ -170,8 +155,8 @@ static void pco_library_init() /* init DLT */ (void) snprintf(dltContextID, sizeof(dltContextID), "Pers_%04d", pid); DLT_REGISTER_CONTEXT(persComLldbDLTCtx, dltContextID, "PersCommonLLDB"); - //DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_DEBUG, DLT_TRACE_STATUS_OFF); - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("register context PersCommonLLDB ContextID="); DLT_STRING(dltContextID)); + //DLT_SET_APPLICATION_LL_TS_LIMIT(DLT_LOG_INFO, DLT_TRACE_STATUS_OFF); + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("register context PersCommonLLDB ContextID="); DLT_STRING(dltContextID)); } __attribute__((destructor)) @@ -181,7 +166,6 @@ static void pco_library_destroy() } - /** * \open or create a key-value database * \note : DB type is identified from dbPathname (based on extension) @@ -202,12 +186,13 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo int kdbState = 0; int openMode = KISSDB_OPEN_MODE_RDWR; //default is open existing in RDWR int writeMode = KISSDB_WRITE_MODE_WC; //default is write cached + int incRefCounter = 1; // default increment counter lldb_handler_s* pLldbHandler = NIL; sint_t returnValue = PERS_COM_FAILURE; path = dbPathname; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING("Begin opening:"); DLT_STRING("<"); DLT_STRING(dbPathname); DLT_STRING(">, "); ((PersLldbPurpose_RCT == ePurpose) ? DLT_STRING("RCT, ") : DLT_STRING("DB, ")); ((true == bForceCreationIfNotPresent) ? DLT_STRING("forced, ") : DLT_STRING("unforced, "))); @@ -232,16 +217,17 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo { //bit 1 is set -> writeThrough mode 0x2 (open) 0x3 (create) writeMode = KISSDB_WRITE_MODE_WT; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("Opening in write through mode:"), DLT_STRING("<"), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("Opening in write through mode:"), DLT_STRING("<"), DLT_STRING(dbPathname), DLT_STRING(">, ")); } if( bForceCreationIfNotPresent & (1 << 2)) //check bit 2 { openMode = KISSDB_OPEN_MODE_RDONLY; //bit 2 is set 0x4 - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("Opening in read only mode:"), DLT_STRING("<"), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("Opening in read only mode:"), DLT_STRING("<"), DLT_STRING(dbPathname), DLT_STRING(">, ")); } + if (1 == checkIsLink(dbPathname, linkBuffer)) { path = linkBuffer; @@ -256,6 +242,7 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo if (pLldbHandler->kissDb.alreadyOpen == Kdb_false) //check if this instance has already opened the db before { pLldbHandler->kissDb.semName = kdbGetShmName("-sem", path); + if (NULL == pLldbHandler->kissDb.semName) { return -1; @@ -264,11 +251,11 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo error = errno; //store errno -> (errno could be modified by following DLT_LOG) if (pLldbHandler->kissDb.kdbSem == SEM_FAILED) //open failed { - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(": first sem_open() with mode O_CREAT | O_EXCL failed with: "); DLT_STRING(strerror(error))); if (error == EEXIST) { - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(": semaphore already exists: "); DLT_STRING(strerror(error))); //try to open existing semaphore pLldbHandler->kissDb.kdbSem = sem_open(pLldbHandler->kissDb.semName, O_CREAT, 0644, 0); @@ -298,6 +285,7 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo return PERS_COM_ERR_SEM_WAIT_TIMEOUT; } + kdbState = KISSDB_open(&pLldbHandler->kissDb, path, openMode, writeMode, HASHTABLE_SLOT_COUNT, keysize, datasize); if (kdbState != 0) { @@ -305,14 +293,26 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo { DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING("KISSDB_open: "); DLT_STRING("<"); DLT_STRING(path); DLT_STRING(">, "); DLT_STRING("database to be opened has wrong version! retval=<"); DLT_INT(kdbState); DLT_STRING(">")); + + bCanContinue = false; + } + else if(kdbState == KISSDB_ERROR_APPCRASH) + { + // possible appcrash detected: + // - don't increment counter + // - set kdbState back to 0 + // - bCanContinue still true + incRefCounter = 0; + kdbState = 0; } else { DLT_LOG(persComLldbDLTCtx, DLT_LOG_WARN, DLT_STRING("KISSDB_open: "); DLT_STRING("<"); DLT_STRING(path); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(kdbState); DLT_STRING(">"), DLT_STRING(strerror(errno))); + + bCanContinue = false; } - bCanContinue = false; } } if (kdbState == 0) @@ -330,7 +330,11 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo bLocked = true; } - pLldbHandler->kissDb.shared->refCount++; //increment reference to opened databases + if(incRefCounter == 1) + { + pLldbHandler->kissDb.shared->refCount++; //increment reference to opened databases + } + if (-1 == sem_post(pLldbHandler->kissDb.kdbSem)) //release semaphore { DLT_LOG(persComLldbDLTCtx, DLT_LOG_ERROR, DLT_STRING(__FUNCTION__); DLT_STRING(": End of open -> sem_post() failed: "),DLT_STRING(strerror(errno))); @@ -368,7 +372,6 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo returnValue = PERS_COM_FAILURE; (void) lldb_handles_DeinitHandle(pLldbHandler->dbHandler); } - if (bCanContinue) { if (bLocked) @@ -377,8 +380,7 @@ sint_t pers_lldb_open(str_t const* dbPathname, pers_lldb_purpose_e ePurpose, boo (void) lldb_handles_Unlock(&db->shared->mutex); } } - - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("End of open for:"), DLT_STRING("<"), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR), DLT_STRING(__FUNCTION__), DLT_STRING("End of open for:"), DLT_STRING("<"), DLT_STRING(dbPathname), DLT_STRING(">, "), ((PersLldbPurpose_RCT == ePurpose) ? DLT_STRING("RCT, ") : DLT_STRING("DB, ")), ((true == bForceCreationIfNotPresent) ? DLT_STRING("forced, ") : DLT_STRING("unforced, ")); DLT_STRING("retval=<"), DLT_INT(returnValue), DLT_STRING(">")); @@ -405,7 +407,7 @@ sint_t pers_lldb_close(sint_t handlerDB) lldb_handler_s* pLldbHandler = NIL; sint_t returnValue = PERS_COM_SUCCESS; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(handlerDB)); #ifdef __showTimeMeasurements @@ -452,7 +454,7 @@ sint_t pers_lldb_close(sint_t handlerDB) return PERS_COM_ERR_SEM_WAIT_TIMEOUT; } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("Closing database <"); DLT_STRING(pLldbHandler->dbPathname); DLT_STRING(">")); Kdb_wrlock(&db->shared->rwlock); //lock acces to shared status information @@ -479,6 +481,7 @@ sint_t pers_lldb_close(sint_t handlerDB) #ifdef PFS_TEST printf(" START: writeback of %d slots\n", pLldbHandler->kissDb.tbl->data->usedslots); #endif + if (pLldbHandler->ePurpose == PersLldbPurpose_DB) //write back to local database { writeBackKissDB(&pLldbHandler->kissDb, pLldbHandler); @@ -574,7 +577,7 @@ sint_t pers_lldb_close(sint_t handlerDB) } } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("handlerDB="); DLT_INT(handlerDB); DLT_STRING(" retval=<"); DLT_INT(returnValue); DLT_STRING(">")); #ifdef __showTimeMeasurements @@ -613,7 +616,7 @@ static sint_t writeBackKissRCT(KISSDB* db, lldb_handler_s* pLldbHandler) qnobj_t obj; sint_t returnValue = PERS_COM_SUCCESS; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("START writeback for RCT: "), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("START writeback for RCT: "), DLT_STRING(pLldbHandler->dbPathname)); setMemoryAddress(db->sharedCache, db->tbl[0]); @@ -665,7 +668,7 @@ static sint_t writeBackKissRCT(KISSDB* db, lldb_handler_s* pLldbHandler) free(obj.data); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("END writeback for RCT: "), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("END writeback for RCT: "), DLT_STRING(pLldbHandler->dbPathname)); return returnValue; } @@ -693,7 +696,7 @@ static sint_t writeBackKissDB(KISSDB* db, lldb_handler_s* pLldbHandler) qnobj_t obj; sint_t returnValue = PERS_COM_SUCCESS; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("START writeback for DB: "), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("START writeback for DB: "), DLT_STRING(pLldbHandler->dbPathname)); setMemoryAddress(db->sharedCache, db->tbl[0]); @@ -752,7 +755,7 @@ static sint_t writeBackKissDB(KISSDB* db, lldb_handler_s* pLldbHandler) free(obj.data); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("END writeback for DB: "), + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("END writeback for DB: "), DLT_STRING(pLldbHandler->dbPathname)); return returnValue; } @@ -879,13 +882,9 @@ sint_t pers_lldb_delete_key(sint_t handlerDB, pers_lldb_purpose_e ePurpose, str_ switch (ePurpose) { case PersLldbPurpose_DB: - { - eErrorCode = DeleteDataFromKissDB(handlerDB, key); - break; - } case PersLldbPurpose_RCT: { - eErrorCode = DeleteDataFromKissRCT(handlerDB, key); + eErrorCode = DeleteDataFromKissDB(handlerDB, key); break; } default: @@ -976,7 +975,7 @@ static sint_t DeleteDataFromKissDB(sint_t dbHandler, pconststr_t key) lldb_handler_s* pLldbHandler = NIL; sint_t bytesDeleted = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("handlerDB="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">")); if ((dbHandler >= 0) && (NIL != key)) @@ -1041,13 +1040,14 @@ static sint_t DeleteDataFromKissDB(sint_t dbHandler, pconststr_t key) (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("handlerDB="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesDeleted); DLT_STRING(">")); return bytesDeleted; } +#if 0 static sint_t DeleteDataFromKissRCT(sint_t dbHandler, pconststr_t key) { bool_t bCanContinue = true; @@ -1056,7 +1056,7 @@ static sint_t DeleteDataFromKissRCT(sint_t dbHandler, pconststr_t key) lldb_handler_s* pLldbHandler = NIL; sint_t bytesDeleted = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("handlerDB="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">")); if ((dbHandler >= 0) && (NIL != key)) @@ -1119,12 +1119,13 @@ static sint_t DeleteDataFromKissRCT(sint_t dbHandler, pconststr_t key) (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("handlerDB="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesDeleted); DLT_STRING(">")); return bytesDeleted; } +#endif static sint_t GetAllKeysFromKissLocalDB(sint_t dbHandler, pstr_t buffer, sint_t size) { @@ -1134,7 +1135,7 @@ static sint_t GetAllKeysFromKissLocalDB(sint_t dbHandler, pstr_t buffer, sint_t lldb_handler_s* pLldbHandler = NIL; sint_t result = 0; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("buffer="); DLT_UINT((uint_t)buffer); DLT_STRING("size="); DLT_INT(size)); if (dbHandler >= 0) @@ -1189,7 +1190,7 @@ static sint_t GetAllKeysFromKissLocalDB(sint_t dbHandler, pstr_t buffer, sint_t (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("retval=<"); DLT_INT(result); DLT_STRING(">")); return result; } @@ -1202,7 +1203,7 @@ static sint_t GetAllKeysFromKissRCT(sint_t dbHandler, pstr_t buffer, sint_t size lldb_handler_s* pLldbHandler = NIL; sint_t result = 0; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("buffer="); DLT_UINT((uint_t)buffer); DLT_STRING("size="); DLT_INT(size)); if (dbHandler >= 0) @@ -1256,7 +1257,7 @@ static sint_t GetAllKeysFromKissRCT(sint_t dbHandler, pstr_t buffer, sint_t size (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("retval=<"); DLT_INT(result); DLT_STRING(">")); return result; @@ -1272,7 +1273,7 @@ static sint_t SetDataInKissLocalDB(sint_t dbHandler, pconststr_t key, pconststr_ sint_t bytesWritten = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("size<"); DLT_INT(dataSize); DLT_STRING(">")); @@ -1345,7 +1346,7 @@ static sint_t SetDataInKissLocalDB(sint_t dbHandler, pconststr_t key, pconststr_ (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("size<"); DLT_INT(dataSize); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesWritten); DLT_STRING(">")); @@ -1361,7 +1362,7 @@ static sint_t SetDataInKissRCT(sint_t dbHandler, pconststr_t key, PersistenceCon lldb_handler_s* pLldbHandler = NIL; sint_t bytesWritten = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">")); if ((dbHandler >= 0) && (NIL != key) && (NIL != pConfig)) @@ -1436,7 +1437,7 @@ static sint_t SetDataInKissRCT(sint_t dbHandler, pconststr_t key, PersistenceCon (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesWritten); DLT_STRING(">")); @@ -1450,7 +1451,7 @@ static sint_t GetKeySizeFromKissLocalDB(sint_t dbHandler, pconststr_t key) lldb_handler_s* pLldbHandler = NIL; sint_t bytesRead = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">")); if ((dbHandler >= 0) && (NIL != key)) @@ -1505,7 +1506,7 @@ static sint_t GetKeySizeFromKissLocalDB(sint_t dbHandler, pconststr_t key) KISSDB* db = &pLldbHandler->kissDb; (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesRead); DLT_STRING(">")); @@ -1520,7 +1521,7 @@ static sint_t GetDataFromKissLocalDB(sint_t dbHandler, pconststr_t key, pstr_t b lldb_handler_s* pLldbHandler = NIL; sint_t bytesRead = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("bufsize=<"); DLT_INT(bufSize); DLT_STRING(">")); @@ -1579,7 +1580,7 @@ static sint_t GetDataFromKissLocalDB(sint_t dbHandler, pconststr_t key, pstr_t b (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("bufsize=<"); DLT_INT(bufSize); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesRead); DLT_STRING(">")); return bytesRead; @@ -1592,7 +1593,7 @@ static sint_t GetDataFromKissRCT(sint_t dbHandler, pconststr_t key, PersistenceC lldb_handler_s* pLldbHandler = NIL; sint_t bytesRead = PERS_COM_FAILURE; - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">")); if ((dbHandler >= 0) && (NIL != key) && (NIL != pConfig)) @@ -1650,7 +1651,7 @@ static sint_t GetDataFromKissRCT(sint_t dbHandler, pconststr_t key, PersistenceC (void) lldb_handles_Unlock(&db->shared->mutex); } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler="); DLT_INT(dbHandler); DLT_STRING("key=<"); DLT_STRING(key); DLT_STRING(">, "); DLT_STRING("retval=<"); DLT_INT(bytesRead); DLT_STRING(">")); @@ -1748,7 +1749,7 @@ static lldb_handler_s* lldb_handles_FindInUseHandle(sint_t dbHandler) } } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING((NIL!=pHandler) ? "Found handler <" : "ERROR can't find handler <"); DLT_INT(dbHandler); DLT_STRING(">"); DLT_STRING((NIL!=pHandler) ? (dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "in static area" : "in dynamic list") : "")); @@ -1853,7 +1854,7 @@ static lldb_handler_s* lldb_handles_FindAvailableHandle(void) } } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING((NIL!=pHandler) ? "Found availble handler <" : "ERROR can't find available handler <"); DLT_INT((NIL!=pHandler) ? pHandler->dbHandler : (-1)); DLT_STRING(">"); DLT_STRING((NIL!=pHandler) ? (pHandler->dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "in static area" : "in dynamic list") : "")); @@ -1926,7 +1927,7 @@ static bool_t lldb_handles_DeinitHandle(sint_t dbHandler) } } - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(LT_HDR); DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("dbHandler=<"); DLT_INT(dbHandler); DLT_STRING("> "); DLT_STRING(bEverythingOK ? (dbHandler <= PERS_LLDB_MAX_STATIC_HANDLES ? "deinit handler in static area" : "deinit handler in dynamic list") : "ERROR - handler not found")); @@ -2108,7 +2109,7 @@ sint_t putToCache(KISSDB* db, sint_t dataSize, char* metaKey, void* cachedData) { putOk = 1; printf("INSERT OK \n"); - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("INSERT INTO Cache Nr: "); DLT_INT(k); DLT_STRING("worked : ")); break; } @@ -2142,7 +2143,7 @@ sint_t putToCache(KISSDB* db, sint_t dataSize, char* metaKey, void* cachedData) } else - DLT_LOG(persComLldbDLTCtx, DLT_LOG_DEBUG, + DLT_LOG(persComLldbDLTCtx, DLT_LOG_INFO, DLT_STRING(__FUNCTION__); DLT_STRING(":"); DLT_STRING("INSERT NEW DATA INTO RESIZE OF CACHE WORKS : ")); } printf("END ----------- \n\n"); @@ -2298,33 +2299,42 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe objCount = db->tbl[0]->size(db->tbl[0], &max, &used); if (objCount > 0) { - tmplist = malloc(sizeof(char*) * objCount); - tmp_deleted_list = malloc(sizeof(char*) * objCount); + tmplist = malloc(sizeof(char*) * objCount); if (tmplist != NULL) { - while (db->tbl[0]->getnext(db->tbl[0], &obj, &idx) == true) + tmp_deleted_list = malloc(sizeof(char*) * objCount); + if(tmp_deleted_list != NULL) { - size_t keyLen = strlen(obj.name); - pt = obj.data; - eFlag = (pers_lldb_cache_flag_e) *(int*) pt; - if (eFlag != CachedDataDelete) + while (db->tbl[0]->getnext(db->tbl[0], &obj, &idx) == true) { - tmplist[keyCountCache] = (char*) malloc(keyLen + 1); - (void) strncpy(tmplist[keyCountCache], obj.name, keyLen); - ptr = tmplist[keyCountCache]; - ptr[keyLen] = '\0'; - keyCountCache++; - } else { //get all keys marked as deleted in cache - tmp_deleted_list[deletedKeysInCacheCount] = (char*) malloc(keyLen + 1); - (void) strncpy(tmp_deleted_list[deletedKeysInCacheCount], obj.name, keyLen); - ptr2 = tmp_deleted_list[deletedKeysInCacheCount]; - ptr2[keyLen] = '\0'; - deletedKeysInCacheCount++; + size_t keyLen = strlen(obj.name); + pt = obj.data; + eFlag = (pers_lldb_cache_flag_e) *(int*) pt; + if (eFlag != CachedDataDelete) + { + tmplist[keyCountCache] = (char*) malloc(keyLen + 1); + (void) strncpy(tmplist[keyCountCache], obj.name, keyLen); + ptr = tmplist[keyCountCache]; + ptr[keyLen] = '\0'; + keyCountCache++; + } else { //get all keys marked as deleted in cache + tmp_deleted_list[deletedKeysInCacheCount] = (char*) malloc(keyLen + 1); + (void) strncpy(tmp_deleted_list[deletedKeysInCacheCount], obj.name, keyLen); + ptr2 = tmp_deleted_list[deletedKeysInCacheCount]; + ptr2[keyLen] = '\0'; + deletedKeysInCacheCount++; + } } } + else + { + free(tmp_deleted_list); + return PERS_COM_ERR_MALLOC; + } } else { + free(tmplist); return PERS_COM_ERR_MALLOC; } } @@ -2366,6 +2376,8 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe tbl = qhasharr(memory, memsize); if (tbl == NULL) { + free(tmp_deleted_list); + free(tmplist); return PERS_COM_ERR_MALLOC; } //put keys in cache to a hashtable @@ -2455,6 +2467,7 @@ sint_t getListandSize(KISSDB* db, pstr_t buffer, sint_t size, bool_t bOnlySizeNe } } free(tmp_deleted_list); + free(tmplist); } return PERS_COM_ERR_MALLOC; } diff --git a/test/Makefile.am b/test/Makefile.am index 0d52584..e43a397 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,17 +7,16 @@ AM_CFLAGS = $(DEPS_CFLAGS) $(CHECK_CFLAGS) endif -persdatadir = $(datadir)/persistence/test-data -persdata_DATA = data/attachToExistingCache.tar.gz data/rct_compare.tar.gz +localstate_DATA = data/rct_compare.tar.gz # Add config file to distribution -EXTRA_DIST = $(persdata_DATA) +EXTRA_DIST = $(localstate_DATA) noinst_PROGRAMS = test_pco_key_value_store persistence_common_object_test #persistence_sqlite_experimental test_pco_key_value_store_SOURCES = test_pco_key_value_store.c -test_pco_key_value_store_CFLAGS = $(AM_CFLAGS) $(ARCHIVELIB_CFLAGS) $(ZLIB_CFLAGS) -DPERS_TEST_DATA_DIR='"$(persdatadir)"' +test_pco_key_value_store_CFLAGS = $(AM_CFLAGS) $(ARCHIVELIB_CFLAGS) $(ZLIB_CFLAGS) test_pco_key_value_store_LDADD = $(DLT_LIBS) $(SQLITE_LIBS) $(DEPS_LIBS) $(CHECK_LIBS) $(ARCHIVELIB_LIBS) $(ZLIB_LIBS) \ $(top_srcdir)/src/libpers_common.la diff --git a/test/data/attachToExistingCache.tar.gz b/test/data/attachToExistingCache.tar.gz deleted file mode 100644 index 1002c89..0000000 Binary files a/test/data/attachToExistingCache.tar.gz and /dev/null differ diff --git a/test/test_pco_key_value_store.c b/test/test_pco_key_value_store.c index 2d5454f..5613c34 100644 --- a/test/test_pco_key_value_store.c +++ b/test/test_pco_key_value_store.c @@ -45,26 +45,73 @@ #define READ_SIZE 1024 #define MaxAppNameLen 256 +#define PIDFILE_PREFIX "perslib_" +#define PIDFILE_TEMPLATE PIDFILEDIR "/" PIDFILE_PREFIX"%d.pid" // PIDFILEDIR is defined via configure switch -pidfiledir (default is /var/run if not set) + /// application id char gTheAppId[MaxAppNameLen] = { 0 }; // definition of weekday char* dayOfWeek[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; +static char gPidfilename[40] = {0}; + +// forward declaration +int check_for_same_file_content(char* file1Path, char* file2Path); + + + +static void createPidFile(pid_t pid) +{ + int fd = -1; + + // create pidfile + memset(gPidfilename, 0, 40); + snprintf(gPidfilename, 40, PIDFILE_TEMPLATE, pid); + + fd = open(gPidfilename, O_CREAT|O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); + if(fd != -1) + { + //printf("#### TEST: Created pidfile: %s\n", gPidfilename); + close(fd); + fd = -1; + } + else + { + printf("#### TEST: Failed to create pidfile: %s - error: %s\n", gPidfilename, strerror(errno)); + } +} void data_setup(void) { //ssd DLT_REGISTER_APP("PCOt", "tests the persistence common object library"); + + createPidFile(getpid()); } void data_teardown(void) { DLT_UNREGISTER_APP(); + + remove(gPidfilename); +} + + + +void data_setup_thread(void) +{ + //ssd + DLT_REGISTER_APP("PCOt", "tests the persistence common object library"); } +void data_teardown_thread(void) +{ + DLT_UNREGISTER_APP(); +} + START_TEST(test_OpenLocalDB) { @@ -1922,6 +1969,8 @@ START_TEST(test_CachedConcurrentAccess) //Cleaning up testdata folder remove("/tmp/cached-concurrent.db"); + printf("Test PID: %d\n", getpid()); + pid = fork(); if (pid == 0) { @@ -1938,6 +1987,8 @@ START_TEST(test_CachedConcurrentAccess) snprintf(childSysTimeBuffer, 256, "%s", "1"); + createPidFile(getpid()); + //wait so that father has already opened the db sleep(3); @@ -1969,10 +2020,13 @@ START_TEST(test_CachedConcurrentAccess) fail_unless(ret == 0, "Child failed to close database: retval: [%d]", ret); DLT_UNREGISTER_APP(); + + remove(gPidfilename); _exit(EXIT_SUCCESS); } else if (pid > 0) { + /*parent*/ //printf("Started father process with PID: [%d] \n", pid); int handle = 0; @@ -1982,6 +2036,8 @@ START_TEST(test_CachedConcurrentAccess) char sysTimeBuffer[256] = { 0 }; int i =0; + createPidFile(getpid()); + handle = persComDbOpen("/tmp/cached-concurrent.db", 0x1); //create test.db if not present fail_unless(handle >= 0, "Father failed to create non existent lDB: retval: [%d]", ret); @@ -2024,6 +2080,8 @@ START_TEST(test_CachedConcurrentAccess) } fail_unless(ret == 0, "Father failed to close database: retval: [%d]", ret); + remove(gPidfilename); + _exit(EXIT_SUCCESS); } } @@ -2057,6 +2115,8 @@ START_TEST(test_CachedConcurrentAccess2) char write2[READ_SIZE] = { 0 }; int i =0; + createPidFile(getpid()); + snprintf(childSysTimeBuffer, 256, "%s", "1"); //open database initially (CREATOR) @@ -2101,6 +2161,8 @@ START_TEST(test_CachedConcurrentAccess2) fail_unless(ret == 0, "Child failed to close database: retval: [%d]", ret); DLT_UNREGISTER_APP(); + + remove(gPidfilename); _exit(EXIT_SUCCESS); } else if (pid > 0) @@ -2114,6 +2176,8 @@ START_TEST(test_CachedConcurrentAccess2) char sysTimeBuffer[256] = { 0 }; int i =0; + createPidFile(getpid()); + //wait until child (CREATOR) has opened the database sleep(1); @@ -2160,7 +2224,7 @@ START_TEST(test_CachedConcurrentAccess2) printf("persComDbClose() failed: [%d] \n", ret); } fail_unless(ret == 0, "Father failed to close database: retval: [%d]", ret); - + remove(gPidfilename); _exit(EXIT_SUCCESS); } } @@ -2924,13 +2988,15 @@ START_TEST(test_WriteThrough) char write2[READ_SIZE] = { 0 }; int i =0; + createPidFile(getpid()); + snprintf(childSysTimeBuffer, 256, "%s", "1"); //wait so that father has already opened the db //sleep(3); //open db after father (in order to use the hashtable in shared memory) - handle = persComDbOpen("/tmp/writethrough-concurrent.db", 0x3); //create test.db if not present and writethrough mode + handle = persComDbOpen("/tmp/writethrough-concurrent.db", 0x3 | 0x08); //create test.db if not present and writethrough mode fail_unless(handle >= 0, "Child failed to create non existent lDB: retval: [%d]", ret); //read the new key written by the father from cache @@ -2957,6 +3023,8 @@ START_TEST(test_WriteThrough) fail_unless(ret == 0, "Child failed to close database: retval: [%d]", ret); DLT_UNREGISTER_APP(); + + remove(gPidfilename); _exit(EXIT_SUCCESS); } else if (pid > 0) @@ -2970,7 +3038,9 @@ START_TEST(test_WriteThrough) char sysTimeBuffer[256] = { 0 }; int i =0; - handle = persComDbOpen("/tmp/writethrough-concurrent.db", 0x3); //create test.db if not present and writethrough mode + createPidFile(getpid()); + + handle = persComDbOpen("/tmp/writethrough-concurrent.db", 0x3| 0x08); //create test.db if not present and writethrough mode fail_unless(handle >= 0, "Father failed to create non existent lDB: retval: [%d]", ret); //Write data to cache (cache gets created here) @@ -3011,7 +3081,7 @@ START_TEST(test_WriteThrough) printf("persComDbClose() failed: [%d] \n", ret); } fail_unless(ret == 0, "Father failed to close database: retval: [%d]", ret); - + remove(gPidfilename); _exit(EXIT_SUCCESS); } @@ -3329,12 +3399,237 @@ static int doUncompress(const char* extractFrom, const char* extractTo) } +START_TEST(test_CrashingApp) +{ + int ret = 0, handle = -1, i = 0; + char key[128] = {0}; + char writeData[128] = {0}; + + createPidFile(getpid()); + //printf("Crashing App - pid: [%d]==> \n", getpid()); + + //Cleaning up + remove("/dev/shm/_tmp_attachToExistingCacheFragment_db-cache"); + remove("/dev/shm/_tmp_attachToExistingCacheFragment_db-ht"); + remove("/dev/shm/_tmp_attachToExistingCacheFragment_db-shm-info"); + remove("/tmp/attachToExistingCacheFragment.db"); + + // + // open database and fill with content + // + handle = persComDbOpen("/tmp/attachToExistingCacheFragment.db", 0x1); //write cached create database + fail_unless(handle >= 0, "Failed to open database / create open: retval: [%d]", handle); + + ret = persComDbWriteKey(handle, "Key_A", "some_Key_A_data", strlen("some_Key_A_data")); + fail_unless(ret == strlen("some_Key_A_data"), "Wrong write size"); + ret = persComDbWriteKey(handle, "Key_BB", "some_Key_BB_data", strlen("some_Key_BB_data")); + fail_unless(ret == strlen("some_Key_BB_data"), "Wrong write size"); + ret = persComDbWriteKey(handle, "Key_CCC", "some_Key_CCC_data", strlen("some_Key_CCC_data")); + fail_unless(ret == strlen("some_Key_CCC_data"), "Wrong write size"); + + ret = persComDbClose(handle); + fail_unless(ret == 0, "Failed to close database: retval: [%d]", ret); + + + // + // now open again and write data cache + // + handle = persComDbOpen("/tmp/attachToExistingCacheFragment.db", 0x1); //write cached create database + fail_unless(handle >= 0, "Failed to open database / create open: retval: [%d]", handle); + + // write new keys + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "Key_in_loop_%d_%d_cache",i,i*i); + snprintf(writeData, 128, "DATA-%d_cache",i); + + ret = persComDbWriteKey(handle, key, (char*) writeData, strlen(writeData)); + fail_unless(ret == strlen(writeData), "Wrong write size"); + } + + // now crash is simulated (SIGILL) to end the process ==> next test process (test_RestartedApp) tries to read data from cache and from database file + raise(SIGILL); +} +END_TEST + + + + +START_TEST(test_RestartedApp) +{ + int ret = 0, handle = -1, i = 0; + char key[128] = {0}; + char writeData[128] = {0}; + char readData[128] = {0}; + + createPidFile(getpid()); + //printf("Restarted App - pid: [%d] ==> \n", getpid()); + + // + // check if all temporary files are available + // + fail_unless(access("/dev/shm/sem._tmp_attachToExistingCacheFragment_db-sem", F_OK) == 0); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-cache", F_OK) == 0); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-ht", F_OK) == 0); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-shm-info", F_OK) == 0); + + + handle = persComDbOpen("/tmp/attachToExistingCacheFragment.db", 0x1); //write cached create database + fail_unless(handle >= 0, "Failed to open database / create open: retval: [%d]", handle); + + // + // try to read data from file + // + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_A", (char*) readData, 128); + //printf("Read data - file - 1 - [%d]: \"%s\"\n", ret, readData); + fail_unless(strncmp((char*)readData, "some_Key_A_data", strlen("some_Key_A_data")) == 0, "Wrong data read - file - 1"); + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_BB", (char*) readData, 128); + //printf("Read data - file - 2 - [%d]: \"%s\"\n", ret, readData); + fail_unless(strncmp((char*)readData, "some_Key_BB_data", strlen("some_Key_BB_data")) == 0, "Wrong data read - file - 2"); + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_CCC", (char*) readData, 128); + //printf("Read data - file - 3 - [%d]: \"%s\"\n", ret, readData); + fail_unless(strncmp((char*)readData, "some_Key_CCC_dataa", strlen("some_Key_CCC_data")) == 0, "Wrong data - file - read 3"); + + + // + // try to read data from cache + // + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(readData, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "Key_in_loop_%d_%d_cache",i,i*i); + snprintf(writeData, 128, "DATA-%d_cache",i); // reference data that should be read + + ret = persComDbReadKey(handle, key, (char*) readData, 128); + //printf("Key: - %s - | Data: - %s - \n", key, readData); + fail_unless(strncmp((char*)readData, writeData, strlen(writeData)) == 0, "Wrong data read - cache - %d", i); + fail_unless(ret == strlen(writeData), "Wrong size - cache - %d", i); + } + + + // + // add new data + // + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "new_Key_in_loop_%d_%d_new",i,i*i); + snprintf(writeData, 128, "new_DATA-%d_new",i); + + ret = persComDbWriteKey(handle, key, (char*) writeData, strlen(writeData)); + fail_unless(ret == strlen(writeData), "Father: Wrong write size"); + } + + + // + // read newly added keys + // + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(readData, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "new_Key_in_loop_%d_%d_new",i,i*i); + snprintf(writeData, 128, "new_DATA-%d_new",i); // reference data that should be read + + ret = persComDbReadKey(handle, key, (char*) readData, 128); + fail_unless(strncmp((char*)readData, writeData, strlen(writeData)) == 0, "Wrong data read"); + fail_unless(ret == strlen(writeData), "Wrong read size"); + } + + ret = persComDbClose(handle); + fail_unless(ret == 0, "Failed to close database: retval: [%d]", ret); + + + // + // check if all temporary files were removed + // + fail_unless(access("/dev/shm/sem._tmp_attachToExistingCacheFragment_db-sem", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-cache", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-ht", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-shm-info", F_OK) == -1); + + + // + // open database again and read all keys + // + handle = persComDbOpen("/tmp/attachToExistingCacheFragment.db", 0x1); //write cached create database + fail_unless(handle >= 0, "Failed to open database / create open: retval: [%d]", handle); + + // data previously already in database + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_A", (char*) readData, 128); + fail_unless(strncmp((char*)readData, "some_Key_A_data", strlen("some_Key_A_data")) == 0, "Wrong data read - file - 1"); + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_BB", (char*) readData, 128); + fail_unless(strncmp((char*)readData, "some_Key_BB_data", strlen("some_Key_BB_data")) == 0, "Wrong data read - file - 2"); + memset(readData, 0, 128); + ret = persComDbReadKey(handle, "Key_CCC", (char*) readData, 128); + fail_unless(strncmp((char*)readData, "some_Key_CCC_dataa", strlen("some_Key_CCC_data")) == 0, "Wrong data - file - read 3"); + + // data previously in cache + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(readData, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "Key_in_loop_%d_%d_cache",i,i*i); + snprintf(writeData, 128, "DATA-%d_cache",i); // reference data that should be read + + ret = persComDbReadKey(handle, key, (char*) readData, 128); + //printf("Key: - %s - | Data: - %s - \n", key, readData); + fail_unless(strncmp((char*)readData, writeData, strlen(writeData)) == 0, "Wrong data read - cache - %d", i); + fail_unless(ret == strlen(writeData), "Wrong size - cache - %d", i); + } + + // newly added data + for(i=0; i< 400; i++) + { + memset(key, 0, 128); + memset(readData, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "new_Key_in_loop_%d_%d_new",i,i*i); + snprintf(writeData, 128, "new_DATA-%d_new",i); // reference data that should be read + + ret = persComDbReadKey(handle, key, (char*) readData, 128); + fail_unless(strncmp((char*)readData, writeData, strlen(writeData)) == 0, "Wrong data read"); + fail_unless(ret == strlen(writeData), "Wrong read size"); + } + + ret = persComDbClose(handle); + fail_unless(ret == 0, "Failed to close database: retval: [%d]", ret); + + // + // check if all temporary files were removed + // + fail_unless(access("/dev/shm/sem._tmp_attachToExistingCacheFragment_db-sem", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-cache", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-ht", F_OK) == -1); + fail_unless(access("/dev/shm/_tmp_attachToExistingCacheFragment_db-shm-info", F_OK) == -1); + + + remove(gPidfilename); + //printf("Restarted App <== \n\n"); +} +END_TEST + + + + START_TEST(test_Compare_RCT) { int result = 0; // extract test RCT databases - result = doUncompress(PERS_TEST_DATA_DIR"/rct_compare.tar.gz", "/tmp/"); + result = doUncompress("/usr/local/var/rct_compare.tar.gz", "/tmp/"); fail_unless(result == 0, "Failed to extract test data"); @@ -3386,6 +3681,7 @@ START_TEST(test_Compare_RCT) } END_TEST + static Suite* persistenceCommonLib_suite() { Suite* s = suite_create("Persistence-common-object-test"); @@ -3514,8 +3810,9 @@ static Suite* persistenceCommonLib_suite() tcase_add_checked_fixture(tc_persCacheSize, data_setup, data_teardown); suite_add_tcase(s, tc_persCachedConcurrentAccess); - tcase_add_checked_fixture(tc_persCachedConcurrentAccess, data_setup, data_teardown); - //suite_add_tcase(s, tc_persCachedConcurrentAccess2); + tcase_add_checked_fixture(tc_persCachedConcurrentAccess, data_setup_thread, data_teardown_thread); + suite_add_tcase(s, tc_persCachedConcurrentAccess2); + tcase_add_checked_fixture(tc_persCachedConcurrentAccess2, data_setup_thread, data_teardown_thread); suite_add_tcase(s, tc_BadParameters); tcase_add_checked_fixture(tc_BadParameters, data_setup, data_teardown); @@ -3536,19 +3833,42 @@ static Suite* persistenceCommonLib_suite() tcase_add_checked_fixture(tc_MultipleWrites, data_setup, data_teardown); suite_add_tcase(s, tc_WriteThrough); - tcase_add_checked_fixture(tc_WriteThrough, data_setup, data_teardown); + tcase_add_checked_fixture(tc_WriteThrough, data_setup_thread, data_teardown_thread); suite_add_tcase(s, tc_AddKey_DeleteKey_AddShorterKeyName); suite_add_tcase(s, tc_Compare_RCT); #else + #endif return s; } +static Suite* persistenceCommonLib_suite_appcrash() +{ + Suite* s = suite_create("Persistence-common-object-test app crash"); + + TCase* tc_CrashingApp = tcase_create("CrashingApp"); + tcase_set_timeout(tc_CrashingApp, 120); + tcase_add_test_raise_signal(tc_CrashingApp, test_CrashingApp, SIGILL); + + TCase* tc_RestartedApp = tcase_create("RestartedApp"); + tcase_add_test(tc_RestartedApp, test_RestartedApp); + tcase_set_timeout(tc_RestartedApp, 120); + + + suite_add_tcase(s, tc_CrashingApp); + tcase_add_checked_fixture(tc_CrashingApp, data_setup_thread, data_teardown_thread); + + suite_add_tcase(s, tc_RestartedApp); + tcase_add_checked_fixture(tc_RestartedApp, data_setup_thread, data_teardown_thread); + + return s; +} + void* kvdbOpenThread(void* userData) { @@ -3632,178 +3952,230 @@ void doSemLockTimeoutTest() } +void allocateSharedMemeory() +{ + int handle = -1, i = 0, ret = -1; + char key[128] = {0}; + char writeData[128] = {0}; + char readData[128] = {0}; + + //first create the database + printf("Do Open\n"); + handle = persComDbOpen("/tmp/showAllocatedSharedMemory.db", 0x1); //write cached create database + + printf("Now Write\n"); + for(i=0; i< 200; i++) + { + memset(key, 0, 128); + memset(writeData, 0, 128); + snprintf(key, 128, "new_Key_in_loop_%d_%d_new",i,i*i); + snprintf(writeData, 128, "new_DATA-%d_new",i); + + ret = persComDbWriteKey(handle, key, (char*) writeData, strlen(writeData)); + printf("+"); + fflush(stdout); + usleep(200000); + } + + printf("Write - end => sleep\n"); + sleep(10); + + + printf("Close\n"); + if(handle >= 0 ) + { + (void)persComDbClose(handle); + } +} + + + + int main(int argc, char* argv[]) { - int nr_failed = 0, nr_run = 0, i = 0; - TestResult** tResult; + int nr_failed = 0, nr_failed2 = 0, nr_run = 0, i = 0; - Suite* s = persistenceCommonLib_suite(); - SRunner* sr = srunner_create(s); + printf("Main PID: %d\n", getpid()); if(argc == 1) { + TestResult** tResult; + + Suite* s = persistenceCommonLib_suite(); + Suite * sAppCrash = persistenceCommonLib_suite_appcrash(); + + SRunner* sr = srunner_create(s); + SRunner * srAppCrash = srunner_create(sAppCrash); + srunner_set_xml(sr, "/tmp/persistenceCommonObjectTest.xml"); srunner_set_log(sr, "/tmp/persistenceCommonObjectTest.log"); - srunner_run_all(sr, /*CK_NORMAL*/CK_VERBOSE); + srunner_set_fork_status(srAppCrash, CK_FORK); + srunner_set_xml(srAppCrash, "/tmp/persistenceCommonObjectTest_AC.xml"); + srunner_set_log(srAppCrash, "/tmp/persistenceCommonObjectTest_AC.log"); + + // run normal tests + srunner_run_all(sr, CK_VERBOSE); nr_failed = srunner_ntests_failed(sr); nr_run = srunner_ntests_run(sr); - tResult = srunner_results(sr); for (i = 0; i < nr_run; i++) { (void) tr_rtype(tResult[i]); // get status of each test } - srunner_free(sr); + + // run app crash tests + srunner_run_all(srAppCrash, CK_VERBOSE); + nr_failed2 = srunner_ntests_failed(srAppCrash); + nr_run = srunner_ntests_run(srAppCrash); + tResult = srunner_results(srAppCrash); + srunner_free(srAppCrash); } else { - doSemLockTimeoutTest(); + if(atoi(argv[1]) == 1) + { + doSemLockTimeoutTest(); + } + else if(atoi(argv[1]) == 2) + { + allocateSharedMemeory(); + } } dlt_free(); - return (0 == nr_failed) ? EXIT_SUCCESS : EXIT_FAILURE; + return (0==nr_failed && 0==nr_failed2)?EXIT_SUCCESS:EXIT_FAILURE; } - #define MAX_RESOURCE_LIST_ENTRY 512 int check_for_same_file_content(char* file1Path, char* file2Path) { - int ret = 0; - int rval = 1; - int handle1 = 0; - int handle2 = 0; - char* resourceList = NULL; - int listSize = 0; - PersistenceConfigurationKey_s psConfig1, psConfig2; - - if((NULL == file1Path) || (NULL == file2Path)) - { - return 0; - } + int ret = 0; + int rval = 1; + int handle1 = -1; + int handle2 = -1; + char* resourceList = NULL; + int listSize = 0; + PersistenceConfigurationKey_s psConfig1, psConfig2; - //Open database - handle1 = persComRctOpen(file1Path, 0x0); - if(handle1 < 0) - { - return 0; - } - handle2 = persComRctOpen(file2Path, 0x0); - if(handle2 < 0) - { + if((NULL == file1Path) || (NULL == file2Path)) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Invalid parameters in persadmin_check_for_same_file_content call.")); + return 0; + } + + + //Open database + handle1 = persComRctOpen(file1Path, 0x0); + if(handle1 < 0) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to open : "), DLT_STRING(file1Path)); + return 0; + } + + handle2 = persComRctOpen(file2Path, 0x0); + if(handle2 < 0) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to open : "), DLT_STRING(file2Path)); (void)persComRctClose(handle1); - return 0; - } + return 0; + } - listSize = persComRctGetSizeResourcesList(handle1); - if(listSize != 0) - { - if(listSize > 0) + listSize = persComRctGetSizeResourcesList(handle1); + if(listSize > 0) + { + resourceList = (char*) malloc(listSize); + if(resourceList != NULL) { - resourceList = (char*) malloc(listSize); - if(resourceList != NULL) - { - ret = persComRctGetResourcesList(handle1, resourceList, listSize); - if(ret > 0) - { - int i = 0, idx = 0, numResources = 0, doContinue = 1; - int resourceStartIdx[MAX_RESOURCE_LIST_ENTRY] = {0}; - - resourceStartIdx[idx] = 0; // initial start - - for(i=1; i 0) + { + const char* currentResource = resourceList; + ptrdiff_t currentIndex = 0; + + while (currentIndex < listSize) + { + memset(psConfig1.custom_name, 0, sizeof(psConfig1.custom_name)); + memset(psConfig1.customID, 0, sizeof(psConfig1.customID)); + memset(psConfig1.reponsible, 0, sizeof(psConfig1.reponsible)); + + memset(psConfig2.custom_name, 0, sizeof(psConfig2.custom_name)); + memset(psConfig2.customID, 0, sizeof(psConfig2.customID)); + memset(psConfig2.reponsible, 0, sizeof(psConfig2.reponsible)); + + ret = persComRctRead(handle1, currentResource, &psConfig1); + if(ret != sizeof(psConfig1)) { - numResources++; - resourceStartIdx[++idx] = i+1; - if(idx > MAX_RESOURCE_LIST_ENTRY) - { - doContinue = 0; - break; - } + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("persComRctRead - handle1 failed")); + break; } - } - if(doContinue == 1) - { - for(i=0; i databases are not identical + break; } - } - else - { - printf("Num of array entries exceeded\n"); - rval = 0; - } - } - free(resourceList); - } - else - { - rval = 0; // failure - } + + if(memcmp(&psConfig1, &psConfig2, sizeof(psConfig1)) != 0) // test if value of keys are matching + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Data does not match")); + rval = 0; // no match, end loop and return false ==> databases are not identical + break; + } + + currentResource = (const char*)memchr(currentResource, '\0', listSize - currentIndex); + if (currentResource == NULL) + { + break; + } + currentResource++; + currentIndex = currentResource - resourceList; + } + } + free(resourceList); } else { - rval = 0; // failure + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("malloc failed")); + rval = 0; } - } - else - { + } + else if (listSize < 0) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("persComRctGetSizeResourcesList error")); + rval = 0; + } + else + { // empty src database, check if other database is also empty listSize = persComRctGetSizeResourcesList(handle2); if(listSize != 0) { - rval = 0; // other database is not empty ==> databases are not identicyl + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("databases are not identical")); + rval = 0; // other database is not empty ==> databases are not identical } - } - - //Close database - ret = persComRctClose(handle1); - if (ret != 0) - { - //DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to close : "), DLT_STRING(file1Path)); - } + } - ret = persComRctClose(handle2); - if (ret != 0) - { - //DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to close : "), DLT_STRING(file2Path)); - } + //Close database + ret = persComRctClose(handle1); + if (ret != 0) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to close : "), DLT_STRING(file1Path)); + } - return rval; + ret = persComRctClose(handle2); + if (ret != 0) + { + // DLT_LOG(persAdminSvcDLTCtx, DLT_LOG_ERROR, DLT_STRING(LT_HDR), DLT_STRING("Not able to close : "), DLT_STRING(file2Path)); + } + return rval; } -- cgit v1.2.1