Example #1
0
//--------------------------------------------------------------------------------------------------
le_mrc_ScanInformation_Ref_t le_mrc_GetFirstCellularNetworkScan
(
    le_mrc_ScanInformation_ListRef_t  scanInformationListRef ///< [IN] The list of scan information.
)
{
    pa_mrc_ScanInformation_t* nodePtr;
    le_dls_Link_t*          linkPtr;

    le_mrc_ScanInformationList_t* scanInformationListPtr = le_ref_Lookup(ScanInformationListRefMap,
                                                                         scanInformationListRef);

    if (scanInformationListPtr == NULL)
    {
        LE_KILL_CLIENT("Invalid reference (%p) provided!", scanInformationListRef);
        return NULL;
    }

    linkPtr = le_dls_Peek(&(scanInformationListPtr->paScanInformationList));
    if (linkPtr != NULL)
    {
        nodePtr = CONTAINER_OF(linkPtr, pa_mrc_ScanInformation_t, link);
        scanInformationListPtr->currentLink = linkPtr;

        le_mrc_ScanInformationSafeRef_t* newScanInformationPtr = le_mem_ForceAlloc(ScanInformationSafeRefPool);
        newScanInformationPtr->safeRef = le_ref_CreateRef(ScanInformationRefMap,nodePtr);
        newScanInformationPtr->link = LE_DLS_LINK_INIT;
        le_dls_Queue(&(scanInformationListPtr->safeRefScanInformationList),&(newScanInformationPtr->link));

        return (le_mrc_ScanInformation_Ref_t)newScanInformationPtr->safeRef;
    }
    else
    {
        return NULL;
    }
}
Example #2
0
//--------------------------------------------------------------------------------------------------
void fdMon_DestructThread
(
    event_PerThreadRec_t* perThreadRecPtr
)
//--------------------------------------------------------------------------------------------------
{
    le_dls_Link_t* linkPtr;

    while ((linkPtr = le_dls_Peek(&perThreadRecPtr->fdMonitorList)) != NULL)
    {
        FdMonitor_t* fdMonitorPtr = CONTAINER_OF(linkPtr, FdMonitor_t, link);
        DeleteFdMonitor(fdMonitorPtr);
    }
}
Example #3
0
//--------------------------------------------------------------------------------------------------
le_result_t le_mcc_Delete
(
    le_mcc_CallRef_t callRef   ///< [IN] The call object to free.
)
{
    le_mcc_Call_t* callPtr = le_ref_Lookup(MccCallRefMap, callRef);

    if (callPtr == NULL)
    {
        LE_ERROR("Invalid reference (%p) provided!", callRef);
        return LE_NOT_FOUND;
    }

    if (callPtr->inProgress)
    {
        return LE_FAULT;
    }
    else
    {
        SessionRefNode_t* sessionRefNodePtr;
        le_dls_Link_t* linkPtr;

        callPtr->refCount--;
        LE_DEBUG("refcount %d", callPtr->refCount);

        // Remove corresponding node from the sessionRefList
        linkPtr = le_dls_Peek(&(callPtr->sessionRefList));

        while (linkPtr != NULL)
        {
            sessionRefNodePtr = CONTAINER_OF(linkPtr, SessionRefNode_t, link);
            linkPtr = le_dls_PeekNext(&(callPtr->sessionRefList), linkPtr);

            if ( sessionRefNodePtr->sessionRef == le_mcc_GetClientSessionRef() )
            {
                le_dls_Remove(  &(callPtr->sessionRefList),
                                &(sessionRefNodePtr->link));

                le_mem_Release(sessionRefNodePtr);
            }
        }

        le_mem_Release(callPtr);
        return LE_OK;
    }
}
Example #4
0
//--------------------------------------------------------------------------------------------------
static void CloseAllSessions
(
    Service_t* servicePtr
)
//--------------------------------------------------------------------------------------------------
{
    for (;;)
    {
        le_dls_Link_t* linkPtr = le_dls_Peek(&servicePtr->sessionList);

        if (linkPtr != NULL)
        {
            le_msg_DeleteSession(msgSession_GetSessionContainingLink(linkPtr));
        }
        else
        {
            break;
        }
    }
}
Example #5
0
//--------------------------------------------------------------------------------------------------
void msgService_CallCloseHandler
(
    le_msg_ServiceRef_t serviceRef,
    le_msg_SessionRef_t sessionRef
)
//--------------------------------------------------------------------------------------------------
{
    // If there is a Close Handler registered, call it now.
    le_dls_Link_t* closeLinkPtr = le_dls_Peek(&serviceRef->closeListPtr);

    while (closeLinkPtr)
    {
        SessionEventHandler_t* closeEventPtr = CONTAINER_OF(closeLinkPtr, SessionEventHandler_t, link);

        if (closeEventPtr && (closeEventPtr->handler != NULL))
        {
            closeEventPtr->handler(sessionRef, closeEventPtr->contextPtr);
        }

        closeLinkPtr = le_dls_PeekNext(&serviceRef->closeListPtr, closeLinkPtr);
    }
}
Example #6
0
//--------------------------------------------------------------------------------------------------
static void CallOpenHandler
(
    le_msg_ServiceRef_t serviceRef,
    le_msg_SessionRef_t sessionRef
)
//--------------------------------------------------------------------------------------------------
 {
    // If there is a Close Handler registered, call it now.
    le_dls_Link_t* openLinkPtr = le_dls_Peek(&serviceRef->openListPtr);

    while (openLinkPtr)
    {
        SessionEventHandler_t* openEventPtr = CONTAINER_OF(openLinkPtr, SessionEventHandler_t, link);

        if (openEventPtr->handler != NULL)
        {
            openEventPtr->handler(sessionRef, openEventPtr->contextPtr);
        }

        openLinkPtr = le_dls_PeekNext(&serviceRef->openListPtr, openLinkPtr);
    }
}
Example #7
0
//--------------------------------------------------------------------------------------------------
static void VerifyUniquenessOfName
(
    le_mem_PoolRef_t newPool
)
//--------------------------------------------------------------------------------------------------
{
    le_dls_Link_t* poolLinkPtr = le_dls_Peek(&ListOfPools);

    while (poolLinkPtr)
    {
        MemPool_t* memPoolPtr = CONTAINER_OF(poolLinkPtr, MemPool_t, poolLink);

        if ((strcmp(newPool->name, memPoolPtr->name) == 0) && (newPool != memPoolPtr))
        {
            LE_ERROR("Multiple memory pools share the same name '%s'."
                     " This will become illegal in future releases.\n", memPoolPtr->name);
            break;
        }

        poolLinkPtr = le_dls_PeekNext(&ListOfPools, poolLinkPtr);
    }
}
Example #8
0
//--------------------------------------------------------------------------------------------------
static void CloseSessionEventHandler
(
    le_msg_SessionRef_t sessionRef,
    void*               contextPtr
)
{
    le_mcc_Call_t* callPtr = NULL;
    SessionRefNode_t* sessionRefNodePtr;
    le_dls_Link_t* linkPtr;

    le_ref_IterRef_t iterRef = le_ref_GetIterator(MccCallRefMap);

    while (le_ref_NextNode(iterRef) == LE_OK)
    {
        callPtr = (le_mcc_Call_t*) le_ref_GetValue(iterRef);

        // Remove corresponding node from the sessionRefList
        linkPtr = le_dls_Peek(&(callPtr->sessionRefList));

        while (linkPtr != NULL)
        {
            sessionRefNodePtr = CONTAINER_OF(linkPtr, SessionRefNode_t, link);

            linkPtr = le_dls_PeekNext(&(callPtr->sessionRefList), linkPtr);

            // Remove corresponding node from the sessionRefList
            if ( sessionRefNodePtr->sessionRef == sessionRef )
            {
                le_dls_Remove(&(callPtr->sessionRefList),
                    &(sessionRefNodePtr->link));

                le_mem_Release(sessionRefNodePtr);

                callPtr->refCount--;
                le_mem_Release(callPtr);
            }
        }
    }
}
Example #9
0
//--------------------------------------------------------------------------------------------------
static HandlerObj_t* FindHandlerObj
(
    const int sigNum,
    le_dls_List_t* listPtr
)
{
    // Search for the sigNum from the list.
    le_dls_Link_t* handlerLinkPtr = le_dls_Peek(listPtr);

    while (handlerLinkPtr != NULL)
    {
        HandlerObj_t* handlerObjPtr = CONTAINER_OF(handlerLinkPtr, HandlerObj_t, link);

        if (handlerObjPtr->sigNum == sigNum)
        {
            return handlerObjPtr;
        }

        handlerLinkPtr = le_dls_PeekNext(listPtr, handlerLinkPtr);
    }

    return NULL;
}
Example #10
0
//--------------------------------------------------------------------------------------------------
void le_sem_Delete
(
    le_sem_Ref_t    semaphorePtr   ///< [IN] Pointer to the semaphore
)
{
    // TODO: Implement traceable semaphore deletion.

    // Remove the Semaphore object from the Semaphore List.
    LOCK_SEMAPHORE_LIST();
    le_dls_Remove(&SemaphoreList, &semaphorePtr->semaphoreListLink);
    UNLOCK_SEMAPHORE_LIST();

    LOCK_WAITING_LIST(semaphorePtr);
    if ( le_dls_Peek(&semaphorePtr->waitingList)==NULL ) {
        UNLOCK_WAITING_LIST(semaphorePtr);
        if (pthread_mutex_destroy(&semaphorePtr->waitingListMutex) != 0)
        {
            LE_FATAL(   "Semaphore '%s' could not destroy internal mutex!",
                        semaphorePtr->nameStr);
        }
            // Destroy the semaphore.
        if (sem_destroy(&semaphorePtr->semaphore) != 0)
        {
            LE_FATAL(   "Semaphore '%s' is not a valid semaphore!",
                        semaphorePtr->nameStr);
        }
    } else {
        UNLOCK_WAITING_LIST(semaphorePtr);
        // TODO print more information
        LE_FATAL("Semaphore '%s' deleted while threads are still waiting for it!",
                 semaphorePtr->nameStr);
    }


    // Release the semaphore object back to the Semaphore Pool.
    le_mem_Release(semaphorePtr);
}
Example #11
0
//--------------------------------------------------------------------------------------------------
le_mem_PoolRef_t _le_mem_FindPool
(
    const char*     componentName,  ///< [IN] Name of the component.
    const char*     name            ///< [IN] Name of the pool inside the component.
)
{
    le_mem_PoolRef_t result = NULL;

    // Construct the component-scoped pool name.
    // Note: Don't check for truncation because if it is truncated, it will be consistent with
    //       the truncation that would have occurred in InitPool().
    char fullName[MAX_POOL_NAME_BYTES];
    (void)snprintf(fullName, sizeof(fullName), "%s.%s", componentName, name);

    Lock();

    // Search all pools except for the first one because the first pool is always the sub-pools pool.
    le_dls_Link_t* poolLinkPtr = le_dls_Peek(&ListOfPools);
    poolLinkPtr = le_dls_PeekNext(&ListOfPools, poolLinkPtr);

    while (poolLinkPtr)
    {
        MemPool_t* memPoolPtr = CONTAINER_OF(poolLinkPtr, MemPool_t, poolLink);

        if (strcmp(fullName, memPoolPtr->name) == 0)
        {
            result = memPoolPtr;
            break;
        }

        poolLinkPtr = le_dls_PeekNext(&ListOfPools, poolLinkPtr);
    }

    Unlock();

    return result;
}
Example #12
0
//--------------------------------------------------------------------------------------------------
void le_sig_SetEventHandler
(
    int sigNum,                                 ///< The signal to set the event handler for.  See
                                                ///  parameter documentation in comments above.
    le_sig_EventHandlerFunc_t sigEventHandler   ///< The event handler to call when a signal is
                                                ///  received.
)
{
    // Check parameters.
    if ( (sigNum == SIGKILL) || (sigNum == SIGSTOP) || (sigNum == SIGFPE) || (sigNum == SIGILL) ||
         (sigNum == SIGSEGV) || (sigNum == SIGBUS) || (sigNum == SIGABRT) || (sigNum == SIGIOT) ||
         (sigNum == SIGTRAP) || (sigNum == SIGSYS) )
    {
        LE_FATAL("Signal event handler for %s is not allowed.", strsignal(sigNum));
    }

    // Get the monitor object for this thread.
    MonitorObj_t* monitorObjPtr = pthread_getspecific(SigMonKey);

    if (monitorObjPtr == NULL)
    {
        if (sigEventHandler == NULL)
        {
            // Event handler already does not exist so we don't need to do anything, just return.
            return;
        }
        else
        {
            // Create the monitor object
            monitorObjPtr = le_mem_ForceAlloc(MonitorObjPool);
            monitorObjPtr->handlerObjList = LE_DLS_LIST_INIT;
            monitorObjPtr->fd = -1;
            monitorObjPtr->monitorRef = NULL;

            // Add it to the thread's local data.
            LE_ASSERT(pthread_setspecific(SigMonKey, monitorObjPtr) == 0);
        }
    }

    // See if a handler for this signal already exists.
    HandlerObj_t* handlerObjPtr = FindHandlerObj(sigNum, &(monitorObjPtr->handlerObjList));

    if (handlerObjPtr == NULL)
    {
        if (sigEventHandler == NULL)
        {
            // Event handler already does not exist so we don't need to do anything, just return.
            return;
        }
        else
        {
            // Create the handler object.
            handlerObjPtr = le_mem_ForceAlloc(HandlerObjPool);

            // Set the handler.
            handlerObjPtr->link = LE_DLS_LINK_INIT;
            handlerObjPtr->handler = sigEventHandler;
            handlerObjPtr->sigNum = sigNum;

            // Add the handler object to the list.
            le_dls_Queue(&(monitorObjPtr->handlerObjList), &(handlerObjPtr->link));
        }
    }
    else
    {
        if (sigEventHandler == NULL)
        {
            // Remove the handler object from the list.
            le_dls_Remove(&(monitorObjPtr->handlerObjList), &(handlerObjPtr->link));
        }
        else
        {
            // Just update the handler.
            handlerObjPtr->handler = sigEventHandler;
        }
    }

    // Recreate the signal mask.
    sigset_t sigSet;
    LE_ASSERT(sigemptyset(&sigSet) == 0);

    le_dls_Link_t* handlerLinkPtr = le_dls_Peek(&(monitorObjPtr->handlerObjList));
    while (handlerLinkPtr != NULL)
    {
        HandlerObj_t* handlerObjPtr = CONTAINER_OF(handlerLinkPtr, HandlerObj_t, link);

        LE_ASSERT(sigaddset(&sigSet, handlerObjPtr->sigNum) == 0);

        handlerLinkPtr = le_dls_PeekNext(&(monitorObjPtr->handlerObjList), handlerLinkPtr);
    }

    // Update or create the signal fd.
    monitorObjPtr->fd = signalfd(monitorObjPtr->fd, &sigSet, SFD_NONBLOCK);

    if (monitorObjPtr->fd == -1)
    {
        LE_FATAL("Could not set signal event handler: %m");
    }

    // Create a monitor fd if it doesn't already exist.
    if (monitorObjPtr->monitorRef == NULL)
    {
        // Create the monitor name using SIG_STR + thread name.
        char monitorName[LIMIT_MAX_THREAD_NAME_BYTES + sizeof(SIG_STR)] = SIG_STR;

        LE_ASSERT(le_utf8_Copy(monitorName + sizeof(SIG_STR),
                               le_thread_GetMyName(),
                               LIMIT_MAX_THREAD_NAME_BYTES + sizeof(SIG_STR),
                               NULL) == LE_OK);

        // Create the monitor.
        monitorObjPtr->monitorRef = le_fdMonitor_Create(monitorName,
                                                        monitorObjPtr->fd,
                                                        OurSigHandler,
                                                        POLLIN);
    }
}
Example #13
0
static le_result_t TestDoublyLinkLists(size_t maxListSize)
{
    // Node definition.
    typedef struct
    {
        le_dls_Link_t link;
        uint32_t id;  
    }
    idRecord_t;

    int i;
    le_dls_List_t list0, list1;
    le_dls_Link_t* removedLinksPtr0[REMOVE_SIZE] = {NULL};
    le_dls_Link_t* removedLinksPtr1[REMOVE_SIZE] = {NULL};

    printf("\n");
    printf("*** Unit Test for le_doublyLinkedList module. ***\n");

    //
    // Multiple list creation
    //
    // Initialize the lists
    list0 = LE_DLS_LIST_INIT;
    list1 = LE_DLS_LIST_INIT;
    printf("Two doubly linked lists were successfully created.\n");


    //
    // Attempt to query empty list
    //
    if ( (le_dls_Peek(&list0) != NULL) || (le_dls_PeekTail(&list0) != NULL) ||
         (le_dls_Pop(&list0) != NULL) || (le_dls_PopTail(&list0) != NULL) )
    {
        printf("Query of empty list failed: %d", __LINE__);
        return LE_FAULT;
    }
    printf("Query of empty list correct.\n");


    //
    // Node insertions
    //
    {
        idRecord_t* newNodePtr;
        
        // Insert to the tail
        for (i = 0; i < maxListSize; i++)
        {
            // Create the new node
            newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t));
            newNodePtr->id = i;
            
            // Initialize the link.
            newNodePtr->link = LE_DLS_LINK_INIT;

            // Insert the new node to the tail.
            le_dls_Queue(&list0, &(newNodePtr->link));
        }
        printf("%zu nodes were added to the tail of list0.\n", maxListSize);
        
        // Insert to the head
        for (i = 0; i < maxListSize; i++)
        {
            // Create the new node
            newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t));
            newNodePtr->id = i;
            
            // Initialize the link.
            newNodePtr->link = LE_DLS_LINK_INIT;

            // Insert the new node to the tail.
            le_dls_Stack(&list1, &(newNodePtr->link));
        }
        printf("%zu nodes were added to the head of list1.\n", maxListSize);
    }

    //
    // Check that all the nodes have been added properly
    //
    {
        idRecord_t* nodePtr;
        le_dls_Link_t* link0Ptr = le_dls_Peek(&list0);
        le_dls_Link_t* link1Ptr = le_dls_PeekTail(&list1);
        
        if ( (link0Ptr == NULL) || (link1Ptr == NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
        
        i = 0;
        do
        {
            // Get the node from list 0
            nodePtr = CONTAINER_OF(link0Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }

            // Get the node from list 1
            nodePtr = CONTAINER_OF(link1Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }

            // Move to the next node.
            link0Ptr = le_dls_PeekNext(&list0, link0Ptr);
            link1Ptr = le_dls_PeekPrev(&list1, link1Ptr);
            i++;

        } while (link0Ptr != NULL);
        
        // Make sure everything is correct.
        if ( (i != maxListSize) || (link1Ptr != NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
    }
    
    printf("Checked that all nodes added to the head and tails are all correct.\n");
    

    //
    // Remove random nodes
    //

    //seed the random number generator with the clock
    srand((unsigned int)clock());
    
    {
        // Start at the end of the lists and randomly remove links.
        le_dls_Link_t* linkToRemovePtr;
        le_dls_Link_t* link0Ptr = le_dls_PeekTail(&list0);
        le_dls_Link_t* link1Ptr = le_dls_Peek(&list1);
        
        int r0 = 0;
        int r1 = 0;
        do
        {
            // For list 0
            if ( (rand() < REMOVE_THRESHOLD) && (r0 < REMOVE_SIZE) )
            {
                // Mark this node for removal.
                linkToRemovePtr = link0Ptr;
                
                // Move to the next node.
                link0Ptr = le_dls_PeekPrev(&list0, link0Ptr);
                
                // Remove the node.
                le_dls_Remove(&list0, linkToRemovePtr);
                
                // Store the removed node for later use.
                removedLinksPtr0[r0++] = linkToRemovePtr;
            }
            else
            {
                // Just move one
                link0Ptr = le_dls_PeekPrev(&list0, link0Ptr);
            }
            
            
            // For list 1
            if ( (rand() < REMOVE_THRESHOLD) && (r1 < REMOVE_SIZE) )
            {
                // Mark this node for removal.
                linkToRemovePtr = link1Ptr;
                
                // Move to the next node.
                link1Ptr = le_dls_PeekNext(&list1, link1Ptr);
                
                // Remove the node.
                le_dls_Remove(&list1, linkToRemovePtr);
                
                // Store the removed node for later use.
                removedLinksPtr1[r1++] = linkToRemovePtr;
            }
            else
            {
                // Just move to the next node
                link1Ptr = le_dls_PeekNext(&list1, link1Ptr);
            }
        } while (link0Ptr != NULL);
        
        printf("Randomly removed %d nodes from list0.\n", r0);
        printf("Randomly removed %d nodes from list1.\n", r1);
    }


    //
    // Check that the proper nodes were removed
    //
    {
        int numNodesRemoved = 0;
        
        // For list 0.
        // Check that the nodes in the removed nodes are indeed not in the list.
        for (i = 0; i < REMOVE_SIZE; i++)
        {
            if (removedLinksPtr0[i] == NULL)
            {
                break;
            }
            
            if (le_dls_IsInList(&list0, removedLinksPtr0[i]))
            {
                printf("Node removal incorrect: %d", __LINE__);
                return LE_FAULT;
            }
            
            numNodesRemoved++;
        }
        
        // Compare the list count.
        if ( (numNodesRemoved != maxListSize - le_dls_NumLinks(&list0)) || (le_dls_NumLinks(&list0) == maxListSize) )
        {
            printf("Node removal incorrect: %d", __LINE__);
            return LE_FAULT;
        }
        
        // For list 1.
        // Check that the nodes in the removed nodes are indeed not in the list.
        numNodesRemoved = 0;
        for (i = 0; i < REMOVE_SIZE; i++)
        {
            if (removedLinksPtr1[i] == NULL)
            {
                break;
            }
            
            if (le_dls_IsInList(&list1, removedLinksPtr1[i]))
            {
                printf("Node removal incorrect: %d", __LINE__);
                return LE_FAULT;
            }
            
            numNodesRemoved++;
        }
        
        // Compare the list count.
        if ( (numNodesRemoved != maxListSize - le_dls_NumLinks(&list1)) || (le_dls_NumLinks(&list1) == maxListSize) )
        {
            printf("Node removal incorrect: %d", __LINE__);
            return LE_FAULT;
        }
    }
    
    printf("Checked that nodes were removed correctly.\n");
    
    
    //
    // Add the randomly removed nodes back in.
    //
    {        
        idRecord_t *nodePtr, *removedNodePtr;
        le_dls_Link_t* linkPtr;
     
        // For list 0.
        for (i = 0; i < REMOVE_SIZE; i++)
        {
            if (removedLinksPtr0[i] == NULL)
            {
                break;
            }
            
            removedNodePtr = CONTAINER_OF(removedLinksPtr0[i], idRecord_t, link);
            
            if (removedNodePtr->id == maxListSize-1)
            {
                le_dls_Queue(&list0, removedLinksPtr0[i]);
            }
            else
            {            
                // Search the list for the place to insert this.            
                linkPtr = le_dls_PeekTail(&list0);
                do
                {
                    // Get the node
                    nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);
                    
                    // Find the id that is just before this one.
                    if (nodePtr->id == removedNodePtr->id + 1)
                    {
                        le_dls_AddBefore(&list0, linkPtr, removedLinksPtr0[i]);
                        break;
                    }
                    
                    linkPtr = le_dls_PeekPrev(&list0, linkPtr);
                    
                } while (linkPtr != NULL);
            }
        }
        
        
        // For list 1.
        for (i = 0; i < REMOVE_SIZE; i++)
        {
            if (removedLinksPtr1[i] == NULL)
            {
                break;
            }
            
            removedNodePtr = CONTAINER_OF(removedLinksPtr1[i], idRecord_t, link);
            
            if (removedNodePtr->id == maxListSize-1)
            {
                le_dls_Stack(&list1, removedLinksPtr1[i]);
            }
            else
            {            
                // Search the list for the place to insert this.            
                linkPtr = le_dls_Peek(&list1);
                do
                {
                    // Get the node
                    nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);
                    
                    // Find the id that is just before this one.
                    if (nodePtr->id == removedNodePtr->id + 1)
                    {
                        le_dls_AddAfter(&list1, linkPtr, removedLinksPtr1[i]);
                        break;
                    }
                    
                    linkPtr = le_dls_PeekNext(&list1, linkPtr);
                    
                } while (linkPtr != NULL);
            }
        }
    }
    
    printf("Added all randomly removed nodes back in.\n");
    
    //Check that the list is correct.
    {
        idRecord_t* nodePtr;
        le_dls_Link_t* link0Ptr = le_dls_Peek(&list0);
        le_dls_Link_t* link1Ptr = le_dls_PeekTail(&list1);
        
        if ( (link0Ptr == NULL) || (link1Ptr == NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
        
        i = 0;
        do
        {
            // Get the node from list 0
            nodePtr = CONTAINER_OF(link0Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }
            
            // Get the node from list 1
            nodePtr = CONTAINER_OF(link1Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }        
            
            // Move to the next node.
            link0Ptr = le_dls_PeekNext(&list0, link0Ptr);
            link1Ptr = le_dls_PeekPrev(&list1, link1Ptr);
            i++;
            
        } while (link0Ptr != NULL);
        
        // Make sure everything is correct.
        if ( (i != maxListSize) || (link1Ptr != NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
    }
    
    printf("Checked that all nodes are now added back in in the correct order.\n");
    
    
    //
    // Swap nodes.
    //
    {
        //Swap all the nodes in the list so the list is in reverse order.
        le_dls_Link_t* linkPtr, *tmpLinkPtr;
        le_dls_Link_t* otherlinkPtr;    
        idRecord_t* nodePtr, *otherNodePtr;

        // For list 0.
        linkPtr = le_dls_Peek(&list0);
        otherlinkPtr = le_dls_PeekTail(&list0);    
        for (i = 0; i < (le_dls_NumLinks(&list0) / 2); i++)
        {
            nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);
            otherNodePtr = CONTAINER_OF(otherlinkPtr, idRecord_t, link);
            
            if (nodePtr->id < otherNodePtr->id) 
            {
                le_dls_Swap(&list0, linkPtr, otherlinkPtr);
            }
            else
            {
                break;
            }
            
            // switch the pointers back but not the links.
            tmpLinkPtr = linkPtr;
            linkPtr = otherlinkPtr;
            otherlinkPtr = tmpLinkPtr;
            
            linkPtr = le_dls_PeekNext(&list0, linkPtr);
            otherlinkPtr = le_dls_PeekPrev(&list0, otherlinkPtr);
        }


        // For list 1.
        linkPtr = le_dls_Peek(&list1);
        otherlinkPtr = le_dls_PeekTail(&list1);    
        for (i = 0; i < (le_dls_NumLinks(&list1) / 2); i++)
        {
            nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);
            otherNodePtr = CONTAINER_OF(otherlinkPtr, idRecord_t, link);
            
            if (nodePtr->id > otherNodePtr->id) 
            {
                le_dls_Swap(&list1, linkPtr, otherlinkPtr);
            }
            else
            {
                break;
            }
            
            // switch the pointers back but not the links.
            tmpLinkPtr = linkPtr;
            linkPtr = otherlinkPtr;
            otherlinkPtr = tmpLinkPtr;
            
            linkPtr = le_dls_PeekNext(&list1, linkPtr);
            otherlinkPtr = le_dls_PeekPrev(&list1, otherlinkPtr);
        }
    }
    
    printf("Reversed the order of both lists using swap.\n");
    
    //Check that the list is correct.
    {
        idRecord_t* nodePtr;
        le_dls_Link_t* link0Ptr = le_dls_PeekTail(&list0);
        le_dls_Link_t* link1Ptr = le_dls_Peek(&list1);
        
        if ( (link0Ptr == NULL) || (link1Ptr == NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
        
        i = 0;
        do
        {
            // Get the node from list 0
            nodePtr = CONTAINER_OF(link0Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }
            
            // Get the node from list 1
            nodePtr = CONTAINER_OF(link1Ptr, idRecord_t, link);

            // Check the node.
            if ( nodePtr->id != i)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }        

            // Move to the next node.
            link0Ptr = le_dls_PeekPrev(&list0, link0Ptr);
            link1Ptr = le_dls_PeekNext(&list1, link1Ptr);
            i++;
            
        } while (link0Ptr != NULL);
        
        // Make sure everything is correct.
        if ( (i != maxListSize) || (link1Ptr != NULL) )
        {
            printf("Link error: %d", __LINE__);
            return LE_FAULT;
        }
    }
    
    printf("Checked that all nodes are now correctly in the reverse order.\n");
    

    //
    // Pop nodes.
    //
    {
        //pop all of list0 except for one node.  Save the first node using swap before the pop.
        for (i = maxListSize; i > 1; i--)
        {
            // get the first two links.
            le_dls_Link_t* linkPtr = le_dls_Peek(&list0);
            le_dls_Link_t* otherlinkPtr = le_dls_PeekNext(&list0, linkPtr);

            // swap the first two links.
            le_dls_Swap(&list0, linkPtr, otherlinkPtr);

            // pop the first link.
            le_dls_Pop(&list0);
        }
        
        
        //pop half the list.
        for (i = 0; i < (maxListSize / 2); i++)
        {
            le_dls_PopTail(&list1);
        }
    }
    
    printf("Popped all the nodes except one from the head of list0.\n");
    printf("Popped half the nodes from the tail of list1.\n");
    
    // Check that the list is still in tact.
    {
        idRecord_t* nodePtr;
        
        // For list 0.
        le_dls_Link_t* linkPtr = le_dls_Peek(&list0); 
        nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);

        if (nodePtr->id != maxListSize-1)
        {
            printf("Link error: %d", __LINE__);
        }

        // Check that the number of links left is correct.
        if (le_dls_NumLinks(&list0) != 1)
        {
            printf("Wrong number of links: %d", __LINE__);
            return LE_FAULT;
        }
        
        // For list1.
        linkPtr = le_dls_Peek(&list1); 
        i = 0;
        do
        {
            nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link);
            
            if (nodePtr->id != i++)
            {
                printf("Link error: %d", __LINE__);
                return LE_FAULT;
            }
            
            linkPtr = le_dls_PeekNext(&list1, linkPtr);
        } while(linkPtr != NULL);
        
        // Check that the number of links left is correct.
        if (i != maxListSize - (maxListSize / 2))
        {
            printf("Wrong number of links: %d", __LINE__);
            return LE_FAULT;
        }
    }
    
    printf("Checked that all nodes were properly popped from the lists.\n");


    //
    // Check for list corruption.
    //
    {
        le_dls_Link_t* linkPtr;
        
        if (le_dls_IsListCorrupted(&list1))
        {
            printf("List1 is corrupt but shouldn't be: %d", __LINE__);
            return LE_FAULT;
        }

        // Access one of the links directly.  This should corrupt the list.
        linkPtr = le_dls_PeekTail(&list1);
        linkPtr = le_dls_PeekPrev(&list1, linkPtr);
        linkPtr->prevPtr = linkPtr;

        if (!le_dls_IsListCorrupted(&list1))
        {
            printf("List1 is not corrupted but should be: %d", __LINE__);
            return LE_FAULT;
        }
    }

    printf("Checked lists for corruption.\n");

    
    printf("*** Unit Test for le_doublyLinkedList module passed. ***\n");
    printf("\n");
    return LE_OK;
}