Ejemplo n.º 1
0
//--------------------------------------------------------------------------------------------------
le_msg_SessionEventHandlerRef_t le_msg_AddServiceCloseHandler
(
    le_msg_ServiceRef_t             serviceRef, ///< [in] Reference to the service.
    le_msg_SessionEventHandler_t    handlerFunc,///< [in] Handler function.
    void*                           contextPtr  ///< [in] Opaque pointer value to pass to handler.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef == NULL,
                "Service doesn't exist. Make sure service is started before setting handlers");
    LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(),
                "Service (%s:%s) not owned by calling thread.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    // Create the node.
    SessionEventHandler_t* closeEventPtr = le_mem_ForceAlloc(HandlerEventPoolRef);

    // Initialize the node.
    closeEventPtr->handler = handlerFunc;
    closeEventPtr->contextPtr = contextPtr;
    closeEventPtr->link = LE_DLS_LINK_INIT;
    closeEventPtr->listPtr = &serviceRef->closeListPtr;

    // Add the node to the head of the list by passing in the node's link.
    le_dls_Stack(&serviceRef->closeListPtr, &closeEventPtr->link);

    // Need to return a unique reference that will be used by the remove function.
    closeEventPtr->ref = le_ref_CreateRef(HandlersRefMap, &closeEventPtr->link);

    return closeEventPtr->ref;
}
Ejemplo n.º 2
0
//--------------------------------------------------------------------------------------------------
le_msg_ServiceRef_t le_msg_CreateService
(
    le_msg_ProtocolRef_t    protocolRef,    ///< [in] Reference to the protocol to be used.
    const char*             serviceName     ///< [in] The service instance name.
)
//--------------------------------------------------------------------------------------------------
{
    // Must lock the mutex to prevent races between different threads trying to offer the
    // same service at the same time, or one thread trying to delete a service while another
    // tries to create it, or accessing the Service List hashmap while another thread
    // is updating it.

    LOCK

    // Get a Service object.
    Service_t* servicePtr = GetService(protocolRef, serviceName);

    // If the Service object already has a server thread, then it means that this service
    // is already being offered by someone else in this very process.
    LE_FATAL_IF(servicePtr->serverThread != NULL,
                "Duplicate service (%s:%s) offered in same process.",
                serviceName,
                le_msg_GetProtocolIdStr(protocolRef));

    servicePtr->serverThread = le_thread_GetCurrent();

    UNLOCK

    return servicePtr;
}
Ejemplo n.º 3
0
//--------------------------------------------------------------------------------------------------
void le_msg_DeleteService
(
    le_msg_ServiceRef_t             serviceRef  ///< [in] Reference to the service.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(),
                "Attempted to delete service (%s:%s) not owned by thread.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    // If the service is still advertised, hide it.
    le_msg_HideService(serviceRef);

    // Close any remaining open sessions.
    CloseAllSessions(serviceRef);

    // NOTE: Lock the mutex here to prevent a race between this thread dropping ownership
    // of the service and another thread trying to offer the same service.  This is very
    // unlikely to ever happen, but just in case, make sure it fails with a sensible
    // ("duplicate") log message, instead of just quietly messing up the hashmap or something.
    LOCK

    // Clear out the server thread reference.
    serviceRef->serverThread = NULL;

    // Release the server's hold on the object.
    le_mem_Release(serviceRef);

    UNLOCK
}
Ejemplo n.º 4
0
//--------------------------------------------------------------------------------------------------
void AdvertiseService
(
    void
)
{
    LE_DEBUG("======= Starting Server %s ========", SERVICE_INSTANCE_NAME);

    le_msg_ProtocolRef_t protocolRef;

    // Create the server data pool
    _ServerDataPool = le_mem_CreatePool("ServerData", sizeof(_ServerData_t));

    // Create safe reference map for handler references.
    // The size of the map should be based on the number of handlers defined for the server.
    // Don't expect that to be more than 2-3, so use 3 as a reasonable guess.
    _HandlerRefMap = le_ref_CreateMap("ServerHandlers", 3);

    // Start the server side of the service
    protocolRef = le_msg_GetProtocolRef(PROTOCOL_ID_STR, sizeof(_Message_t));
    _ServerServiceRef = le_msg_CreateService(protocolRef, SERVICE_INSTANCE_NAME);
    le_msg_SetServiceRecvHandler(_ServerServiceRef, ServerMsgRecvHandler, NULL);
    le_msg_AdvertiseService(_ServerServiceRef);

    // Register for client sessions being closed
    le_msg_AddServiceCloseHandler(_ServerServiceRef, CleanupClientData, NULL);

    // Need to keep track of the thread that is registered to provide this service.
    _ServerThreadRef = le_thread_GetCurrent();
}
Ejemplo n.º 5
0
// A thread "main" function which creates a series of sems.
static void* ThreadCreateSem
(
    void* context
)
{
    char semNameBuffer[LIMIT_MAX_SEMAPHORE_NAME_BYTES] = {0};


    LE_INFO("Thread [%s] has started. Waiting on a semaphore.", le_thread_GetMyName());

    le_mutex_Lock(SemIndexMutexRef);

    snprintf(semNameBuffer, LIMIT_MAX_SEMAPHORE_NAME_BYTES, "[%s]Sem%ld",
             le_thread_GetMyName(), SemCreateIdx);

    le_sem_Ref_t sem = le_sem_Create(semNameBuffer, 0);

    SemRefArray[SemCreateIdx] = (SemRef_t){le_thread_GetCurrent(), sem};

    SemCreateIdx++;

    le_mutex_Unlock(SemIndexMutexRef);

    LE_INFO("In thread [%s], about to wait sem", le_thread_GetMyName());

    // notify the calling thread that this thread is about to wait on its sema.
    le_sem_Post(SemaRef);

    le_sem_Wait(sem);
    LE_INFO("In thread [%s], sema is posted", le_thread_GetMyName());

    le_event_RunLoop();
    return NULL;
}
Ejemplo n.º 6
0
// Delete all mutexes for the first thread.
static void DelAllMutexesFor1stThread
(
    void* param1,
    void* param2
)
{
    LE_INFO("DelAllMutexesFor1stThread in thread [%s]", le_thread_GetMyName());

    // Determine if this is the "1st" thread on the thread list. If so, delete all mutexes.
    if (le_thread_GetCurrent() == ThreadRefArray[0])
    {
        LE_INFO("This thread is the 1st thread in the thread list - deleting all mutexes.");
        DelMutexes(0, 0);
    }
}
Ejemplo n.º 7
0
//--------------------------------------------------------------------------------------------------
void le_msg_SetServiceRecvHandler
(
    le_msg_ServiceRef_t     serviceRef, ///< [in] Reference to the service.
    le_msg_ReceiveHandler_t handlerFunc,///< [in] Handler function.
    void*                   contextPtr  ///< [in] Opaque pointer value to pass to the handler.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(),
                "Service (%s:%s) not owned by calling thread.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    serviceRef->recvHandler = handlerFunc;
    serviceRef->recvContextPtr = contextPtr;
}
Ejemplo n.º 8
0
// Delete all mutexes for a thread in the middle.
static void DelAllMutexesForMidThread
(
    void* param1,
    void* param2
)
{
    LE_INFO("DelAllMutexesForMidThread in thread [%s]", le_thread_GetMyName());

    long midIdx = ThreadNum / 2;

    // Determine if this is the "mid" thread on the thread list. If so, delete all mutexes.
    if (le_thread_GetCurrent() == ThreadRefArray[midIdx])
    {
        LE_INFO("This thread is the mid thread in the thread list - deleting all mutexes.");
        DelMutexes(0, 0);
    }
}
Ejemplo n.º 9
0
//--------------------------------------------------------------------------------------------------
__attribute__((unused)) static void SendMsgToClient
(
    le_msg_MessageRef_t msgRef      ///< [in] Reference to the message.
)
{
    /*
     * If called from a thread other than the server thread, queue the message onto the server
     * thread.  This is necessary to allow async response/handler functions to be called from any
     * thread, whereas messages to the client can only be sent from the server thread.
     */
    if ( le_thread_GetCurrent() != _ServerThreadRef )
    {
        le_event_QueueFunctionToThread(_ServerThreadRef,
                                       SendMsgToClientQueued,
                                       msgRef,
                                       NULL);
    }
    else
    {
        le_msg_Send(msgRef);
    }
}
Ejemplo n.º 10
0
//--------------------------------------------------------------------------------------------------
BugTestRef_t AddBugTest
(
    const char* newPathPtr,
        ///< [IN]

    BugTestFunc_t handlerPtr,
        ///< [IN]

    void* contextPtr
        ///< [IN]
)
{
    le_msg_MessageRef_t _msgRef;
    le_msg_MessageRef_t _responseMsgRef;
    _Message_t* _msgPtr;

    // Will not be used if no data is sent/received from server.
    __attribute__((unused)) uint8_t* _msgBufPtr;

    BugTestRef_t _result;

    // Range check values, if appropriate
    if ( strlen(newPathPtr) > 512 ) LE_FATAL("strlen(newPathPtr) > 512");


    // Create a new message object and get the message buffer
    _msgRef = le_msg_CreateMsg(GetCurrentSessionRef());
    _msgPtr = le_msg_GetPayloadPtr(_msgRef);
    _msgPtr->id = _MSGID_AddBugTest;
    _msgBufPtr = _msgPtr->buffer;

    // Pack the input parameters
    _msgBufPtr = PackString( _msgBufPtr, newPathPtr );
    // The input parameters are stored in the client data object, and it is
    // a pointer to this object that is passed down.
    // Create a new client data object and fill it in
    _ClientData_t* _clientDataPtr = le_mem_ForceAlloc(_ClientDataPool);
    _clientDataPtr->handlerPtr = (le_event_HandlerFunc_t)handlerPtr;
    _clientDataPtr->contextPtr = contextPtr;
    _clientDataPtr->callersThreadRef = le_thread_GetCurrent();
    contextPtr = _clientDataPtr;
    _msgBufPtr = PackData( _msgBufPtr, &contextPtr, sizeof(void*) );

    // Send a request to the server and get the response.
    LE_DEBUG("Sending message to server and waiting for response");
    _responseMsgRef = le_msg_RequestSyncResponse(_msgRef);
    // It is a serious error if we don't get a valid response from the server
    LE_FATAL_IF(_responseMsgRef == NULL, "Valid response was not received from server");

    // Process the result and/or output parameters, if there are any.
    _msgPtr = le_msg_GetPayloadPtr(_responseMsgRef);
    _msgBufPtr = _msgPtr->buffer;

    // Unpack the result first
    _msgBufPtr = UnpackData( _msgBufPtr, &_result, sizeof(_result) );
    // Put the handler reference result into the client data object, and
    // then return a safe reference to the client data object as the reference.
    _clientDataPtr->handlerRef = (le_event_HandlerRef_t)_result;
    _LOCK
    _result = le_ref_CreateRef(_HandlerRefMap, _clientDataPtr);
    _UNLOCK

    // Unpack any "out" parameters


    // Release the message object, now that all results/output has been copied.
    le_msg_ReleaseMsg(_responseMsgRef);

    return _result;
}