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 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::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); } }