static void *dispatchThreadProc( void *closure ) { mamaDispatcherImpl* impl = (mamaDispatcherImpl*)closure; wInterlocked_set (1, &impl->mIsDispatching); while (wInterlocked_read (&impl->mIsDispatching) && MAMA_STATUS_OK == mamaQueue_dispatch (impl->mQueue)); wInterlocked_set (0, &impl->mIsDispatching); return NULL; }
mama_status avisTransportBridge_stop(avisTransportBridge* transportBridge) { CHECK_TRANSPORT(transportBridge); if (0 == wInterlocked_read (&transportBridge->mDispatching)) { mama_log (MAMA_LOG_LEVEL_WARN, "avisTransportBridge_stop(): " "Avis already stopped"); log_avis_error (MAMA_LOG_LEVEL_WARN, transportBridge->mAvis); return MAMA_STATUS_OK; } wInterlocked_set (0, &transportBridge->mDispatching); /* Dispatch a dummy notification to get the event polling to iterate * another loop and examine the mDispatching state */ elvin_invoke (transportBridge->mAvis, &closeNotification, transportBridge); while (-1 == wsem_wait(&transportBridge->mAvisDispatchSem)) { if (errno != EINTR) return MAMA_STATUS_SYSTEM_ERROR; } wthread_join (transportBridge->mThreadId, NULL); return MAMA_STATUS_OK; }
mama_status avisTransportBridge_start(avisTransportBridge* transportBridge) { /* stop Avis event loop */ int rc; CHECK_TRANSPORT(transportBridge); if (1 == wInterlocked_read (&transportBridge->mDispatching)) { mama_log (MAMA_LOG_LEVEL_WARN, "avisTransportBridge_start(): " "Avis already dispatching"); log_avis_error (MAMA_LOG_LEVEL_WARN, transportBridge->mAvis); return MAMA_STATUS_OK; } wInterlocked_set (1, &transportBridge->mDispatching); rc = wthread_create (&transportBridge->mThreadId, NULL, avisDispatchThread, transportBridge); if (0 != rc) { mama_log (MAMA_LOG_LEVEL_ERROR, "wthread_create returned %d", rc); return MAMA_STATUS_SYSTEM_ERROR; } return MAMA_STATUS_OK; }
mama_status mamaDispatcher_destroy (mamaDispatcher dispatcher) { mamaDispatcherImpl* impl = (mamaDispatcherImpl*)dispatcher; if (!impl) return MAMA_STATUS_NULL_ARG; /* Set dispatching atomic so dispatcher thread is ready to exit */ wInterlocked_set(0, &impl->mIsDispatching); if (impl->mQueue) { mamaQueue_stopDispatch (impl->mQueue); } /* Wait for the thread to return. */ wthread_join (impl->mThread, NULL); wInterlocked_destroy (&impl->mIsDispatching); /* Destroy the thread handle. */ wthread_destroy(impl->mThread); impl->mQueue->mDispatcher = NULL; impl->mThread = 0; free (impl); return MAMA_STATUS_OK; }
mama_status mamaQueue_create_usingNative (mamaQueue* queue, mamaBridge bridgeImpl, void* nativeQueue) { mama_status status = MAMA_STATUS_OK; mamaBridgeImpl* bImpl = (mamaBridgeImpl*)bridgeImpl; mamaQueueImpl* impl = NULL; if (!bridgeImpl) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_create(): NULL bridge."); return MAMA_STATUS_NO_BRIDGE_IMPL; } if (!queue) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_create(): NULL queue" " address."); return MAMA_STATUS_NULL_ARG; } /*Create the queue structure*/ impl = (mamaQueueImpl*)calloc (1, sizeof (mamaQueueImpl)); if (!impl) return MAMA_STATUS_NOMEM; impl->mBridgeImpl = bImpl; impl->mMamaQueueBridgeImpl = NULL; impl->mDispatcher = NULL; impl->mQueueName = strdup ("NO_NAME"); impl->mHighWatermark = 0; impl->mLowWatermark = 1; impl->mQueueMonitorCallbacks.onQueueHighWatermarkExceeded = NULL; impl->mQueueMonitorCallbacks.onQueueLowWatermark = NULL; impl->mQueueMonitorClosure = NULL; /* Create the counter lock. */ wInterlocked_set(0, &impl->mNumberOpenObjects); mamaQueue_createReuseableMsg(impl); /* Call the bridge impl specific queue create function*/ if (MAMA_STATUS_OK!=(status=impl->mBridgeImpl->bridgeMamaQueueCreateUsingNative (&(impl->mMamaQueueBridgeImpl), impl, nativeQueue))) { mama_log (MAMA_LOG_LEVEL_ERROR, "Could not create queue bridge."); mamaQueue_destroy ((mamaQueue)impl); return status; } *queue = (mamaQueue)impl; return MAMA_STATUS_OK; }
mama_status mamaDispatcher_create (mamaDispatcher *result, mamaQueue queue) { mamaQueueImpl* qImpl = (mamaQueueImpl*)queue; mamaDispatcherImpl* impl = NULL; if (!queue) { mama_log (MAMA_LOG_LEVEL_WARN, "mamaDispatcher_create(): NULL queue."); return MAMA_STATUS_INVALID_ARG; } if (!result) { mama_log (MAMA_LOG_LEVEL_WARN, "mamaDispatcher_create(): Invalid " "address"); return MAMA_STATUS_NULL_ARG; } *result = NULL; /*A queue can only have a single dispatcher.*/ if (qImpl->mDispatcher) return MAMA_STATUS_TOO_MANY_DISPATCHERS; impl = (mamaDispatcherImpl*)calloc( 1, sizeof(mamaDispatcherImpl) ); if (impl == NULL) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaDispatcher_create(): Could not " "allocate dispatcher."); return MAMA_STATUS_NOMEM; } wInterlocked_initialize(&impl->mIsDispatching); wInterlocked_set(0, &impl->mIsDispatching); impl->mQueue = queue; if (wthread_create(&impl->mThread, NULL, dispatchThreadProc, impl)) { free (impl); mama_log (MAMA_LOG_LEVEL_ERROR, "mamaDispatcher_create(): Could not " "create dispatch thread."); return MAMA_STATUS_SYSTEM_ERROR; } qImpl->mDispatcher = (mamaDispatcher)impl; *result = (mamaDispatcher)impl; return MAMA_STATUS_OK; }
void closeListener(Elvin* avis, CloseReason reason, const char* message, void* closure) { const char* errMsg = NULL; avisTransportBridge* bridge = (avisTransportBridge*) closure; if (bridge == NULL) { mama_log (MAMA_LOG_LEVEL_FINE, "Avis closeListener: could not get Avis transport bridge"); return; } switch( reason ) { case REASON_CLIENT_SHUTDOWN: errMsg = "Avis client shutdown"; break; case REASON_ROUTER_SHUTDOWN: errMsg = "Avis router shutdown"; break; case REASON_PROTOCOL_VIOLATION: errMsg = "Avis protocol violation"; break; case REASON_ROUTER_STOPPED_RESPONDING: errMsg = "Avis router stopped responding"; break; default: errMsg = "Unknown Avis error"; } mama_log (MAMA_LOG_LEVEL_FINE, "%s : %s", errMsg, message); if (REASON_PROTOCOL_VIOLATION == reason) { /* Ignore protocol violations */ return; } mamaTransportImpl_disconnect( bridge->mTransport, MAMA_TRANSPORT_DISCONNECT, NULL, NULL); wInterlocked_set (0, &bridge->mDispatching); }
mama_status mamaQueue_stopDispatch (mamaQueue queue) { mamaQueueImpl* impl = (mamaQueueImpl*)queue; if (!impl) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_stopDispatch(): NULL queue."); return MAMA_STATUS_NULL_ARG; } wInterlocked_set (0, &impl->mIsDispatching); return impl->mBridgeImpl->bridgeMamaQueueStopDispatch (impl->mMamaQueueBridgeImpl); }
mama_status mamaQueue_timedDispatch (mamaQueue queue, uint64_t timeout) { mamaQueueImpl* impl = (mamaQueueImpl*)queue; if (!impl) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_timedDispatch(): NULL queue."); return MAMA_STATUS_NULL_ARG; } wInterlocked_set (1, &impl->mIsDispatching); return impl->mBridgeImpl->bridgeMamaQueueTimedDispatch (impl->mMamaQueueBridgeImpl, timeout); }
mama_status mamaQueue_create (mamaQueue* queue, mamaBridge bridgeImpl) { mama_status status = MAMA_STATUS_OK; mamaBridgeImpl* bImpl = (mamaBridgeImpl*)bridgeImpl; mamaQueueImpl* impl = NULL; if (!bridgeImpl) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_create(): NULL bridge."); return MAMA_STATUS_NO_BRIDGE_IMPL; } if (!queue) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_create(): NULL queue" " address."); return MAMA_STATUS_NULL_ARG; } /*Create the queue structure*/ impl = (mamaQueueImpl*)calloc (1, sizeof (mamaQueueImpl)); if (!impl) return MAMA_STATUS_NOMEM; impl->mBridgeImpl = bImpl; impl->mMamaQueueBridgeImpl = NULL; impl->mDispatcher = NULL; impl->mQueueName = strdup ("NO_NAME"); impl->mHighWatermark = 0; impl->mLowWatermark = 1; impl->mQueueMonitorCallbacks.onQueueHighWatermarkExceeded = NULL; impl->mQueueMonitorCallbacks.onQueueLowWatermark = NULL; impl->mQueueMonitorClosure = NULL; /* Create the counter lock. */ wInterlocked_initialize(&impl->mNumberOpenObjects); wInterlocked_set(0, &impl->mNumberOpenObjects); /* Call the bridge impl specific queue create function*/ if (MAMA_STATUS_OK!=(status=impl->mBridgeImpl->bridgeMamaQueueCreate (&(impl->mMamaQueueBridgeImpl), impl))) { mama_log (MAMA_LOG_LEVEL_ERROR, "Could not create queue bridge."); mamaQueue_destroy ((mamaQueue)impl); return status; } /* Determine if object lock tracking is enabled. */ { const char *propValue = mama_getProperty(MAMAQUEUE_PROPERTY_OBJECT_LOCK_TRACKING); /* Only do this if it's set. */ if(NULL != propValue) { impl->mTrackObjectLocks = strtobool(propValue); } } *queue = (mamaQueue)impl; mamaQueue_enableStats((mamaQueue)impl); return MAMA_STATUS_OK; }
mama_status mamaQueue_destroy (mamaQueue queue) { mamaQueueImpl* impl = (mamaQueueImpl*)queue; mama_status status = MAMA_STATUS_OK; mama_log (MAMA_LOG_LEVEL_FINEST, "Entering mamaQueue_destroy for queue 0x%X.", queue); if (!queue) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_destroy(): NULL queue."); return MAMA_STATUS_NULL_ARG; } /* The queue can only be destroyed if there are no open event objects. */ status = MAMA_STATUS_QUEUE_OPEN_OBJECTS; /* Only continue if the object count is 0. */ if (0 == wInterlocked_read(&impl->mNumberOpenObjects)) { wInterlocked_set (0, &impl->mIsDispatching); if (impl->mDispatcher) { /* Try to ensure that the dispatcher does not restart the queue * dispatching after we've stopped and destroy it. */ mamaDispatcherImpl* dispatcherImpl = (mamaDispatcherImpl*)impl->mDispatcher; wInterlocked_set (0, &dispatcherImpl->mIsDispatching); dispatcherImpl->mQueue = NULL; } if (impl->mMamaQueueBridgeImpl) { if (MAMA_STATUS_OK!=(status=impl->mBridgeImpl->bridgeMamaQueueDestroy ( impl->mMamaQueueBridgeImpl))) { mama_log (MAMA_LOG_LEVEL_ERROR, "mamaQueue_destroy(): Could not destroy queue bridge."); /*We should continue and free up the rest of the structure.*/ } } /*Destroy the cached mamaMsg - no longer needed*/ if (impl->mMsg) mamaMsg_destroy (impl->mMsg); if (impl->mInitialStat) { mamaStat_destroy (impl->mInitialStat); impl->mInitialStat = NULL; } if (impl->mRecapStat) { mamaStat_destroy (impl->mRecapStat); impl->mRecapStat = NULL; } if (impl->mUnknownMsgStat) { mamaStat_destroy (impl->mUnknownMsgStat); impl->mUnknownMsgStat = NULL; } if (impl->mMessageStat) { mamaStat_destroy (impl->mMessageStat); impl->mMessageStat = NULL; } if (impl->mQueueSizeStat) { mamaStat_destroy (impl->mQueueSizeStat); impl->mQueueSizeStat = NULL; } if (impl->mSubscriptionStat) { mamaStat_destroy (impl->mSubscriptionStat); impl->mSubscriptionStat = NULL; } if (impl->mTimeoutStat) { mamaStat_destroy (impl->mTimeoutStat); impl->mTimeoutStat = NULL; } if (impl->mWombatMsgsStat) { mamaStat_destroy (impl->mWombatMsgsStat); impl->mWombatMsgsStat = NULL; } if (impl->mFastMsgsStat) { mamaStat_destroy (impl->mFastMsgsStat); impl->mFastMsgsStat = NULL; } if (impl->mRvMsgsStat) { mamaStat_destroy (impl->mRvMsgsStat); impl->mRvMsgsStat = NULL; } if (impl->mStatsCollector) { mamaStatsGenerator_removeStatsCollector (mamaInternal_getStatsGenerator(), impl->mStatsCollector); mamaStatsCollector_destroy (impl->mStatsCollector); impl->mStatsCollector = NULL; } if (impl->mQueueName) free ((void*)impl->mQueueName); impl->mBridgeImpl = NULL; impl->mMamaQueueBridgeImpl = NULL; impl->mMsg = NULL; /* Destroy the counter lock */ wInterlocked_destroy(&impl->mNumberOpenObjects); wInterlocked_destroy(&impl->mIsDispatching); /* Destroy the queue counter lock */ wInterlocked_destroy(&gQueueNumber); free (impl); mama_log (MAMA_LOG_LEVEL_FINEST, "Leaving mamaQueue_destroy for queue 0x%X.", queue); status = MAMA_STATUS_OK; } return status; }