//-------------------------------------------------------------------------------------------------- void tu_Init ( void ) //-------------------------------------------------------------------------------------------------- { LE_DEBUG("** Initialize Tree User subsystem."); LE_ASSERT(sizeof(uint32_t) >= sizeof(uid_t)); // Startup the internal Legato user API. user_Init(); // Create our memory pools and allocate the info for the root user. UserPoolRef = le_mem_CreatePool(CFG_USER_POOL_NAME, sizeof(User_t)); UserCollectionRef = le_hashmap_Create(CFG_USER_COLLECTION_NAME, 31, le_hashmap_HashUInt32, le_hashmap_EqualsUInt32); le_mem_SetDestructor(UserPoolRef, UserDestructor); // Create our default root user/tree association. CreateUserInfo(0, "root", "system"); }
//-------------------------------------------------------------------------------------------------- void msgService_Init ( void ) //-------------------------------------------------------------------------------------------------- { // Create and initialize the pool of Service objects. ServicePoolRef = le_mem_CreatePool("MessagingServices", sizeof(Service_t)); le_mem_ExpandPool(ServicePoolRef, MAX_EXPECTED_SERVICES); le_mem_SetDestructor(ServicePoolRef, ServiceDestructor); // Create and initialize the pool of event handlers objects. HandlerEventPoolRef = le_mem_CreatePool("HandlerEventPool", sizeof(SessionEventHandler_t)); le_mem_ExpandPool(HandlerEventPoolRef, MAX_EXPECTED_SERVICES*6); // Create safe reference map for add references. HandlersRefMap = le_ref_CreateMap("HandlersRef", MAX_EXPECTED_SERVICES*6); // Create the Service Map. ServiceMapRef = le_hashmap_Create("MessagingServices", MAX_EXPECTED_SERVICES, ComputeServiceIdHash, AreServiceIdsTheSame); // Create the key to be used to identify thread-local data records containing the Message // Reference when running a Service's message receive handler. int result = pthread_key_create(&ThreadLocalRxMsgKey, NULL); if (result != 0) { LE_FATAL("Failed to create thread local key: result = %d (%s).", result, strerror(result)); } }
//-------------------------------------------------------------------------------------------------- le_result_t le_mcc_Init ( void ) { // Create a pool for Call objects MccCallPool = le_mem_CreatePool("MccCallPool", sizeof(struct le_mcc_Call)); le_mem_ExpandPool(MccCallPool, MCC_MAX_CALL); le_mem_SetDestructor(MccCallPool, CallDestructor); SessionRefPool = le_mem_CreatePool("SessionRefPool", sizeof(SessionRefNode_t)); le_mem_ExpandPool(SessionRefPool, MCC_MAX_CALL); // Create the Safe Reference Map to use for Call object Safe References. MccCallRefMap = le_ref_CreateMap("MccCallMap", MCC_MAX_CALL); // Initialize call wakeup source - succeeds or terminates caller WakeupSource = le_pm_NewWakeupSource(0, CALL_WAKEUP_SOURCE_NAME); CallStateEventId = le_event_CreateId("CallStateEventId", sizeof(le_mcc_CallRef_t)); // Register a handler function for Call Event indications if(pa_mcc_SetCallEventHandler(NewCallEventHandler) != LE_OK) { LE_CRIT("Add pa_mcc_SetCallEventHandler failed"); return LE_FAULT; } // Add a handler to the close session service le_msg_AddServiceCloseHandler( le_mcc_GetServiceRef(), CloseSessionEventHandler, NULL ); return LE_OK; }
//-------------------------------------------------------------------------------------------------- void json_Init ( void ) //-------------------------------------------------------------------------------------------------- { // Create the memory pools. ParserPool = le_mem_InitStaticPool(JSONParser, 1, sizeof(Parser_t)); le_mem_SetDestructor(ParserPool, ParserDestructor); ContextPool = le_mem_InitStaticPool(JSONContext, 10, sizeof(Context_t)); // Initialize the thread-local data key. pthread_key_create(&HandlerKey, NULL); }
int main(int argc, char *argv[]) { le_mem_PoolRef_t idPool, colourPool; idObj_t* idsPtr[ID_POOL_SIZE + NUM_EXTRA_ID] = {NULL}; colourObj_t* coloursPtr[COLOUR_POOL_SIZE] = {NULL}; unsigned int i = 0; unsigned int numRelease = 0; printf("\n"); printf("*** Unit Test for le_mem module. ***\n"); // // Create multiple pools. // idPool = le_mem_CreatePool("ID Pool", sizeof(idObj_t)); colourPool = le_mem_CreatePool("Colour Pool", sizeof(colourObj_t)); printf("Created two memory pools.\n"); // // Expand the pools. // idPool = le_mem_ExpandPool(idPool, ID_POOL_SIZE); colourPool = le_mem_ExpandPool(colourPool, COLOUR_POOL_SIZE); printf("Expanded all pools.\n"); // // Set destructors. // le_mem_SetDestructor(idPool, IdDestructor); // // Spawn child process and perform Assert allocation until failure. // pid_t pID = fork(); if (pID == 0) { // This is the child. // Allocate more than the available objects so the assert will kill the process. for (i = 0; i < ID_POOL_SIZE + 1; i++) { idsPtr[i] = le_mem_AssertAlloc(idPool); } return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Assert allocation performed correctly.\n"); } else { printf("Assert allocation incorrect: %d", __LINE__); return LE_FAULT; } } // // Allocate all objects. // for (i = 0; i < ID_POOL_SIZE; i++) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } idsPtr[i]->id = i; } for (i = 0; i < COLOUR_POOL_SIZE; i++) { coloursPtr[i] = le_mem_TryAlloc(colourPool); if (coloursPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } coloursPtr[i]->r = i; coloursPtr[i]->g = i + 1; coloursPtr[i]->b = i + 2; } printf("Allocated all objects from all pools.\n"); // // Check objects // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i]->id != i) { printf("Object error: %d", __LINE__); return LE_FAULT; } } for (i = 0; i < COLOUR_POOL_SIZE; i++) { if ( (coloursPtr[i]->r != i) || (coloursPtr[i]->g != i+1) || (coloursPtr[i]->b != i+2) ) { printf("Object error: %d", __LINE__); return LE_FAULT; } } printf("Checked all objects in pools.\n"); // // Randomly release some objects. // { //seed the random number generator with the clock srand((unsigned int)clock()); idObj_t* objPtr; size_t numNotReleased = 0; NumRelease = 0; for (i = 0; i < ID_POOL_SIZE; i++) { objPtr = idsPtr[i]; if (rand() < REMOVE_THRESHOLD) { // Increase the ref number for these objects. le_mem_AddRef(objPtr); // These objects should not get freed. numNotReleased++; } else { idsPtr[i] = NULL; } // Release all objects but only objects that did not have their ref count increased will be released. le_mem_Release(objPtr); } if (NumRelease != ID_POOL_SIZE - numNotReleased) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Release the rest of the objects. for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] != NULL) { le_mem_Release(idsPtr[i]); idsPtr[i] = NULL; } } // Check the number of free objects. le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if (stats.numFree != ID_POOL_SIZE) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Spawn child process and try to release an object that is already released. pid_t pID = fork(); if (pID == 0) { // This is the child. // This allocation should fail and kill the process. le_mem_Release(objPtr); return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Ref count correct.\n"); } else { printf("Ref count incorrect: %d", __LINE__); return LE_FAULT; } } } printf("Released objects according to ref counts correctly.\n"); printf("Checked that destructors were called correctly.\n"); // // Try allocate until full. // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] == NULL) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } } // The pool should now be empty. if (le_mem_TryAlloc(idPool) != NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } printf("Tried allocating from empty pool.\n"); // // Force allocate. // le_mem_SetNumObjsToForce(idPool, FORCE_SIZE); for (i = ID_POOL_SIZE; i < ID_POOL_SIZE + NUM_EXTRA_ID; i++) { idsPtr[i] = le_mem_ForceAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } printf("Forced allocated objects.\n"); // // Get stats. // le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != ID_POOL_SIZE + NUM_EXTRA_ID + NumRelease) || (stats.numOverflows != (unsigned int)ceil(((1.0*NUM_EXTRA_ID / FORCE_SIZE)))) || (stats.numFree != (stats.numOverflows*FORCE_SIZE) % NUM_EXTRA_ID) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } printf("Stats are correct.\n"); // // Get pool size. // if (le_mem_GetTotalNumObjs(idPool) != ID_POOL_SIZE + (stats.numOverflows * FORCE_SIZE)) { printf("Pool size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked pool size.\n"); // // Get object size. // if (le_mem_GetObjectSize(idPool) != sizeof(idObj_t)) { printf("Object size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked object size.\n"); // // Reset stats. // { size_t numFree = stats.numFree; le_mem_ResetStats(idPool); le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != 0) || (stats.numOverflows != 0) || (stats.numFree != numFree) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } } printf("Reset stats correctly.\n"); // // Create sub-pool. // // Release some objs from the super-pool in a random manner. numRelease = 0; for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; numRelease++; } } // Create the sub-pool. le_mem_PoolRef_t colourSubPool1 = le_mem_CreateSubPool(colourPool, "Colour sub-pool", numRelease); // // Check sub-pools and super-pool. // if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE) ) { printf("Sub-pool incorrect: %d", __LINE__); return LE_FAULT; } printf("Sub-pool created correctly.\n"); // // Create second sub-pool. // // Release the rest of the objects from the super-pool. for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (coloursPtr[i] != NULL) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; } } // Create another sub-pool. le_mem_PoolRef_t colourSubPool2 = le_mem_CreateSubPool(colourPool, "Second sub-pool", COLOUR_POOL_SIZE - numRelease); printf("Created second sub-pool.\n"); // // Expand the sub-pool causing the super-pool to expand. // le_mem_ExpandPool(colourSubPool2, NUM_EXPAND_SUB_POOL); // // Allocate from sub-pool. // for (i = 0; i < COLOUR_POOL_SIZE - numRelease; i++) { coloursPtr[i] = le_mem_TryAlloc(colourSubPool2); if (coloursPtr[i] == NULL) { printf("Error allocating from sub-pool: %d", __LINE__); return LE_FAULT; } } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + NUM_EXPAND_SUB_POOL) || (stats.numFree != 0) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool1, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (stats.numFree != numRelease) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Expanded sub-pool correctly.\n"); printf("Allocated from sub-pools correctly.\n"); // Try Allocating from empty super-pool. if (le_mem_TryAlloc(colourPool) != NULL) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } // // Delete sub-pool. // le_mem_DeleteSubPool(colourSubPool1); // Allocate from the super-pool. for (i = 0; i < NUM_ALLOC_SUPER_POOL; i++) { coloursPtr[numRelease] = le_mem_AssertAlloc(colourPool); } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (stats.numFree != numRelease - NUM_ALLOC_SUPER_POOL) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Deleted sub-pool correctly.\n"); // // Re-create sub-pool causing super pool to expand. // colourSubPool1 = le_mem_CreateSubPool(colourPool, "First sub-pool", numRelease + NUM_EXPAND_SUB_POOL); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease + NUM_EXPAND_SUB_POOL) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + 2*NUM_EXPAND_SUB_POOL + NUM_ALLOC_SUPER_POOL) ) { printf("Error re-creating sub-pool: %d", __LINE__); return LE_FAULT; } printf("Successfully recreated sub-pool.\n"); // // Search for pools by name. // if ( (idPool != le_mem_FindPool("ID Pool")) || (colourSubPool1 != le_mem_FindPool("First sub-pool")) ) { printf("Error finding pools by name: %d", __LINE__); return LE_FAULT; } printf("Successfully searched for pools by name.\n"); printf("*** Unit Test for le_mem module passed. ***\n"); printf("\n"); return LE_OK; }