/**
   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;
  }
}
Esempio n. 2
0
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();
}
Esempio n. 4
0
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);
  }
}
Esempio n. 5
0
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);
  }
}
Esempio n. 7
0
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;
  }
}
Esempio n. 8
0
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);
}