/** takes ownership of txn */ void SubscriberImpl::messageHandler(const PubSubResponsePtr& m, const PubSubDataPtr& txn) { if (!txn.get()) { LOG4CXX_ERROR(logger, "Invalid transaction"); return; } LOG4CXX_DEBUG(logger, "message received with status " << m->statuscode()); switch (m->statuscode()) { case SUCCESS: txn->getCallback()->operationComplete(); break; case SERVICE_DOWN: txn->getCallback()->operationFailed(ServiceDownException()); break; case CLIENT_ALREADY_SUBSCRIBED: case TOPIC_BUSY: txn->getCallback()->operationFailed(AlreadySubscribedException()); break; case CLIENT_NOT_SUBSCRIBED: txn->getCallback()->operationFailed(NotSubscribedException()); break; default: txn->getCallback()->operationFailed(UnexpectedResponseException()); break; } }
void CloseSubscriptionResponseHandler::handleResponse( const PubSubResponsePtr& m, const PubSubDataPtr& txn, const DuplexChannelPtr& channel) { switch (m->statuscode()) { case SUCCESS: if (m->has_responsebody()) { txn->getCallback()->operationComplete(m->responsebody()); } else { txn->getCallback()->operationComplete(ResponseBody()); } break; case SERVICE_DOWN: LOG4CXX_ERROR(logger, "Server responsed with SERVICE_DOWN for " << txn->getTxnId()); txn->getCallback()->operationFailed(ServiceDownException()); break; case CLIENT_ALREADY_SUBSCRIBED: case TOPIC_BUSY: txn->getCallback()->operationFailed(AlreadySubscribedException()); break; case CLIENT_NOT_SUBSCRIBED: txn->getCallback()->operationFailed(NotSubscribedException()); break; case NOT_RESPONSIBLE_FOR_TOPIC: redirectRequest(m, txn, channel); break; default: LOG4CXX_ERROR(logger, "Unexpected response " << m->statuscode() << " for " << txn->getTxnId()); txn->getCallback()->operationFailed(UnexpectedResponseException()); break; } }
void SubscriberClientChannelHandler::startDelivery(const MessageHandlerCallbackPtr& handler) { { boost::lock_guard<boost::shared_mutex> lock(queue_lock); this->handler = handler; if (!(this->handler.get())) { // no message handler callback LOG4CXX_WARN(logger, "Handler " << this << " try to start an empty message handler"); return; } while (!queue.empty()) { PubSubResponsePtr m = queue.front(); queue.pop_front(); OperationCallbackPtr callback(new SubscriberConsumeCallback(client, shared_from_this(), origData, m)); this->handler->consume(origData->getTopic(), origData->getSubscriberId(), m->message(), callback); } } // put channel#startReceiving out of lock of subscriber#queue_lock // otherwise we enter dead lock // subscriber#startDelivery(subscriber#queue_lock) => // channel#startReceiving(channel#receiving_lock) => channel->startReceiving(); }
void ActiveSubscriber::deliverMessage(const PubSubResponsePtr& m) { boost::lock_guard<boost::shared_mutex> lock(queue_lock); LOG4CXX_INFO(logger, "Message received (topic:" << origData->getTopic() << ", subscriberId:" << origData->getSubscriberId() << ", msgId:" << m->message().msgid().localcomponent() << ") from channel " << channel.get()); if (this->handler.get()) { OperationCallbackPtr callback(new SubscriberConsumeCallback(channelManager, shared_from_this(), m)); this->handler->consume(origData->getTopic(), origData->getSubscriberId(), m->message(), callback); } else { queueMessage(m); } }
void ActiveSubscriber::doStartDelivery(const MessageHandlerCallbackPtr& origHandler, const ClientMessageFilterPtr& origFilter) { MessageHandlerCallbackPtr handler; // origHandler & origFilter has been passed validation. If origFilter is null, // we start delivery w/o message filtering. or If the preferences is null, which // means we connected to an old version hub server, also starts w/o message filtering if (origFilter.get() && preferences.get()) { origFilter->setSubscriptionPreferences(origData->getTopic(), origData->getSubscriberId(), preferences); handler = MessageHandlerCallbackPtr(new FilterableMessageHandler(origHandler, origFilter)); } else { handler = origHandler; } { boost::lock_guard<boost::shared_mutex> lock(queue_lock); if (this->handler.get()) { LOG4CXX_ERROR(logger, *this << " has started delivery with message handler " << this->handler.get()); throw AlreadyStartDeliveryException(); } if (!handler.get()) { // no message handler callback LOG4CXX_WARN(logger, *this << " try to start an empty message handler"); return; } this->handler = handler; // store the original filter and handler this->origHandler = origHandler; this->origFilter = origFilter; while (!queue.empty()) { PubSubResponsePtr m = queue.front(); queue.pop_front(); OperationCallbackPtr callback(new SubscriberConsumeCallback(channelManager, shared_from_this(), m)); this->handler->consume(origData->getTopic(), origData->getSubscriberId(), m->message(), callback); } } LOG4CXX_INFO(logger, *this << " #startDelivery to receive messages from channel " << channel.get()); }
void SubscriberClientChannelHandler::messageReceived(const DuplexChannelPtr& channel, const PubSubResponsePtr& m) { if (m->has_message()) { boost::lock_guard<boost::shared_mutex> lock(queue_lock); LOG4CXX_DEBUG(logger, "Message received (topic:" << origData->getTopic() << ", subscriberId:" << origData->getSubscriberId() << ")"); if (this->handler.get()) { OperationCallbackPtr callback(new SubscriberConsumeCallback(client, shared_from_this(), origData, m)); this->handler->consume(origData->getTopic(), origData->getSubscriberId(), m->message(), callback); } else { queue.push_back(m); if (queue.size() >= (std::size_t)client->getConfiguration().getInt(Configuration::MAX_MESSAGE_QUEUE_SIZE, DEFAULT_MAX_MESSAGE_QUEUE_SIZE)) { channel->stopReceiving(); } } } else { HedwigClientChannelHandler::messageReceived(channel, m); } }
void PublisherImpl::messageHandler(const PubSubResponsePtr& m, const PubSubDataPtr& txn) { switch (m->statuscode()) { case SUCCESS: if (m->has_responsebody()) { txn->getCallback()->operationComplete(m->responsebody()); } else { txn->getCallback()->operationComplete(ResponseBody()); } break; case SERVICE_DOWN: LOG4CXX_ERROR(logger, "Server responsed with SERVICE_DOWN for " << txn->getTxnId()); txn->getCallback()->operationFailed(ServiceDownException()); break; default: LOG4CXX_ERROR(logger, "Unexpected response " << m->statuscode() << " for " << txn->getTxnId()); txn->getCallback()->operationFailed(UnexpectedResponseException()); break; } }
void SubscriberClientChannelHandler::messageReceived(const DuplexChannelPtr& channel, const PubSubResponsePtr& m) { if (m->has_message()) { TopicSubscriber ts(m->topic(), m->subscriberid()); // dispatch the message to target topic subscriber. deliverMessage(ts, m); return; } if (m->has_responsebody()) { const ResponseBody& respBody = m->responsebody(); if (respBody.has_subscriptionevent()) { const SubscriptionEventResponse& eventResp = respBody.subscriptionevent(); // dispatch the event TopicSubscriber ts(m->topic(), m->subscriberid()); handleSubscriptionEvent(ts, eventResp.event()); return; } } HedwigClientChannelHandler::messageReceived(channel, m); }