blob: 8d7f8a1264db7e3d9314148bbbcc42ff197f5b23 [file]
/**
* Copyright (C) 2013 kangliqiang ,kangliq@163.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DefaultMQPushConsumerImpl.h"
#include <string>
#include <set>
#include "DefaultMQPushConsumer.h"
#include "ConsumerStatManage.h"
#include "DefaultMQPullConsumer.h"
#include "DefaultMQProducer.h"
#include "MQClientFactory.h"
#include "MQAdminImpl.h"
#include "RebalancePushImpl.h"
#include "MQClientAPIImpl.h"
#include "OffsetStore.h"
#include "MixAll.h"
#include "MQClientManager.h"
#include "LocalFileOffsetStore.h"
#include "RemoteBrokerOffsetStore.h"
#include "PullSysFlag.h"
#include "FilterAPI.h"
#include "PullAPIWrapper.h"
#include "MQClientException.h"
#include "Validators.h"
#include "MessageListener.h"
#include "ConsumeMessageHook.h"
#include "PullMessageService.h"
#include "ConsumeMessageOrderlyService.h"
#include "ConsumeMessageConcurrentlyService.h"
#include "KPRUtil.h"
#include "TimerThread.h"
namespace rmq
{
/* RemoveProcessQueueLater */
class RemoveProcessQueueLater : public kpr::TimerHandler
{
public:
RemoveProcessQueueLater(DefaultMQPushConsumerImpl* pConsumerImp, PullRequest* pPullRequest)
: m_pConsumerImp(pConsumerImp), m_pPullRequest(pPullRequest)
{
}
void OnTimeOut(unsigned int timerID)
{
try
{
m_pConsumerImp->getOffsetStore()->updateOffset(m_pPullRequest->getMessageQueue(), m_pPullRequest->getNextOffset(), false);
m_pConsumerImp->getOffsetStore()->persist(m_pPullRequest->getMessageQueue());
m_pConsumerImp->getRebalanceImpl()->removeProcessQueue(m_pPullRequest->getMessageQueue());
RMQ_WARN("fix the pull request offset, {%s}", m_pPullRequest->toString().c_str());
}
catch(...)
{
RMQ_ERROR("RemoveProcessQueueLater OnTimeOut Exception");
}
delete this;
}
private:
DefaultMQPushConsumerImpl* m_pConsumerImp;
PullRequest* m_pPullRequest;
};
/* DefaultMQPushConsumerImplCallback */
class DefaultMQPushConsumerImplCallback : public PullCallback
{
public:
DefaultMQPushConsumerImplCallback(SubscriptionData& subscriptionData,
DefaultMQPushConsumerImpl* pDefaultMQPushConsumerImpl,
PullRequest* pPullRequest)
: m_subscriptionData(subscriptionData),
m_pDefaultMQPushConsumerImpl(pDefaultMQPushConsumerImpl),
m_pPullRequest(pPullRequest)
{
m_beginTimestamp = KPRUtil::GetCurrentTimeMillis();
}
void onSuccess(PullResult& pullResult)
{
RMQ_DEBUG("onSuccess begin: %s", pullResult.toString().c_str());
PullResult* pPullResult = &pullResult;
if (pPullResult != NULL)
{
pPullResult =
m_pDefaultMQPushConsumerImpl->m_pPullAPIWrapper->processPullResult(
m_pPullRequest->getMessageQueue(), *pPullResult, m_subscriptionData);
switch (pPullResult->pullStatus)
{
case FOUND:
{
m_pPullRequest->setNextOffset(pPullResult->nextBeginOffset);
long long pullRT = KPRUtil::GetCurrentTimeMillis() - m_beginTimestamp;
m_pDefaultMQPushConsumerImpl->getConsumerStatManager()->getConsumertat()
.pullTimesTotal++;
m_pDefaultMQPushConsumerImpl->getConsumerStatManager()->getConsumertat()
.pullRTTotal.fetchAndAdd(pullRT);
ProcessQueue* processQueue = m_pPullRequest->getProcessQueue();
bool dispatchToConsume = processQueue->putMessage(pPullResult->msgFoundList);
m_pDefaultMQPushConsumerImpl->m_pConsumeMessageService->submitConsumeRequest(//
pPullResult->msgFoundList, //
processQueue, //
m_pPullRequest->getMessageQueue(), //
dispatchToConsume);
if (m_pDefaultMQPushConsumerImpl->m_pDefaultMQPushConsumer->getPullInterval() > 0)
{
m_pDefaultMQPushConsumerImpl->executePullRequestLater(m_pPullRequest,
m_pDefaultMQPushConsumerImpl->m_pDefaultMQPushConsumer->getPullInterval());
}
else
{
m_pDefaultMQPushConsumerImpl->executePullRequestImmediately(m_pPullRequest);
}
}
break;
case NO_NEW_MSG:
m_pPullRequest->setNextOffset(pPullResult->nextBeginOffset);
m_pDefaultMQPushConsumerImpl->correctTagsOffset(*m_pPullRequest);
m_pDefaultMQPushConsumerImpl->executePullRequestImmediately(m_pPullRequest);
break;
case NO_MATCHED_MSG:
m_pPullRequest->setNextOffset(pPullResult->nextBeginOffset);
m_pDefaultMQPushConsumerImpl->correctTagsOffset(*m_pPullRequest);
m_pDefaultMQPushConsumerImpl->executePullRequestImmediately(m_pPullRequest);
break;
case OFFSET_ILLEGAL:
RMQ_WARN("the pull request offset illegal, %s, %s",
m_pPullRequest->toString().c_str(), pPullResult->toString().c_str());
/*
if (m_pPullRequest->getNextOffset() < pPullResult->minOffset)
{
m_pPullRequest->setNextOffset(pPullResult->minOffset);
}
else if (m_pPullRequest->getNextOffset() > pPullResult->maxOffset)
{
m_pPullRequest->setNextOffset(pPullResult->maxOffset);
}
m_pDefaultMQPushConsumerImpl->m_pOffsetStore->updateOffset(
m_pPullRequest->getMessageQueue(), m_pPullRequest->getNextOffset(), false);
m_pDefaultMQPushConsumerImpl->executePullRequestImmediately(m_pPullRequest);
*/
// todo
m_pPullRequest->setNextOffset(pPullResult->nextBeginOffset);
m_pPullRequest->getProcessQueue()->setDropped(true);
m_pDefaultMQPushConsumerImpl->executeTaskLater(new RemoveProcessQueueLater(
m_pDefaultMQPushConsumerImpl, m_pPullRequest), 10000);
break;
default:
break;
}
}
else
{
RMQ_WARN("Warning: PullRequest is null!");
}
RMQ_DEBUG("onSuccess end");
}
void onException(MQException& e)
{
std::string topic = m_pPullRequest->getMessageQueue().getTopic();
if (topic.find(MixAll::RETRY_GROUP_TOPIC_PREFIX) != std::string::npos)
{
RMQ_WARN("execute the pull request exception:%s", e.what());
}
m_pDefaultMQPushConsumerImpl->executePullRequestLater(m_pPullRequest,
DefaultMQPushConsumerImpl::s_PullTimeDelayMillsWhenException);
}
private:
SubscriptionData m_subscriptionData;
DefaultMQPushConsumerImpl* m_pDefaultMQPushConsumerImpl;
PullRequest* m_pPullRequest;
unsigned long long m_beginTimestamp;
};
DefaultMQPushConsumerImpl::DefaultMQPushConsumerImpl(DefaultMQPushConsumer* pDefaultMQPushConsumer)
{
m_pDefaultMQPushConsumer = pDefaultMQPushConsumer;
m_serviceState = CREATE_JUST;
flowControlTimes1 = 0;
flowControlTimes2 = 0;
m_pause = false;
m_consumeOrderly = false;
m_pMQClientFactory = NULL;
m_pPullAPIWrapper = NULL;
m_pMessageListenerInner = NULL;
m_pOffsetStore = NULL;
m_pRebalanceImpl = new RebalancePushImpl(this);
m_pConsumerStatManager = new ConsumerStatManager();
m_pConsumeMessageService = NULL;
}
DefaultMQPushConsumerImpl::~DefaultMQPushConsumerImpl()
{
//delete m_pMessageListenerInner;
if (m_pPullAPIWrapper)
delete m_pPullAPIWrapper;
if (m_pRebalanceImpl)
delete m_pRebalanceImpl;
if (m_pConsumerStatManager)
delete m_pConsumerStatManager;
if (m_pConsumeMessageService)
delete m_pConsumeMessageService;
if (m_pOffsetStore)
delete m_pOffsetStore;
//delete m_pMQClientFactory;
}
void DefaultMQPushConsumerImpl::start()
{
RMQ_DEBUG("DefaultMQPushConsumerImpl::start()");
switch (m_serviceState)
{
case CREATE_JUST:
{
RMQ_INFO("the consumer [{%s}] start beginning. messageModel={%s}",
m_pDefaultMQPushConsumer->getConsumerGroup().c_str(),
getMessageModelString(m_pDefaultMQPushConsumer->getMessageModel()));
m_serviceState = START_FAILED;
checkConfig();
copySubscription();
if (m_pDefaultMQPushConsumer->getMessageModel() == CLUSTERING)
{
m_pDefaultMQPushConsumer->changeInstanceNameToPID();
}
m_pMQClientFactory = MQClientManager::getInstance()->getAndCreateMQClientFactory(*m_pDefaultMQPushConsumer);
m_pRebalanceImpl->setConsumerGroup(m_pDefaultMQPushConsumer->getConsumerGroup());
m_pRebalanceImpl->setMessageModel(m_pDefaultMQPushConsumer->getMessageModel());
m_pRebalanceImpl->setAllocateMessageQueueStrategy(m_pDefaultMQPushConsumer->getAllocateMessageQueueStrategy());
m_pRebalanceImpl->setmQClientFactory(m_pMQClientFactory);
m_pPullAPIWrapper = new PullAPIWrapper(m_pMQClientFactory, m_pDefaultMQPushConsumer->getConsumerGroup());
if (m_pDefaultMQPushConsumer->getOffsetStore() != NULL)
{
m_pOffsetStore = m_pDefaultMQPushConsumer->getOffsetStore();
}
else
{
switch (m_pDefaultMQPushConsumer->getMessageModel())
{
case BROADCASTING:
m_pOffsetStore = new LocalFileOffsetStore(m_pMQClientFactory, m_pDefaultMQPushConsumer->getConsumerGroup());
break;
case CLUSTERING:
m_pOffsetStore = new RemoteBrokerOffsetStore(m_pMQClientFactory, m_pDefaultMQPushConsumer->getConsumerGroup());
break;
default:
break;
}
}
m_pOffsetStore->load();
if (dynamic_cast<MessageListenerOrderly*>(m_pMessageListenerInner) != NULL)
{
m_consumeOrderly = true;
m_pConsumeMessageService =
new ConsumeMessageOrderlyService(this, (MessageListenerOrderly*)m_pMessageListenerInner);
}
else if (dynamic_cast<MessageListenerConcurrently*>(m_pMessageListenerInner) != NULL)
{
m_consumeOrderly = false;
m_pConsumeMessageService =
new ConsumeMessageConcurrentlyService(this, (MessageListenerConcurrently*)m_pMessageListenerInner);
}
m_pConsumeMessageService->start();
bool registerOK = m_pMQClientFactory->registerConsumer(m_pDefaultMQPushConsumer->getConsumerGroup(), this);
if (!registerOK)
{
m_serviceState = CREATE_JUST;
m_pConsumeMessageService->shutdown();
std::string str = "The consumer group[" + m_pDefaultMQPushConsumer->getConsumerGroup();
str += "] has been created before, specify another name please.";
THROW_MQEXCEPTION(MQClientException, str, -1);
}
m_pMQClientFactory->start();
RMQ_INFO("the consumer [%s] start OK.", m_pDefaultMQPushConsumer->getConsumerGroup().c_str());
m_serviceState = RUNNING;
}
break;
case RUNNING:
case START_FAILED:
case SHUTDOWN_ALREADY:
THROW_MQEXCEPTION(MQClientException, "The PullConsumer service state not OK, maybe started once, ", -1);
default:
break;
}
updateTopicSubscribeInfoWhenSubscriptionChanged();
m_pMQClientFactory->sendHeartbeatToAllBrokerWithLock();
m_pMQClientFactory->rebalanceImmediately();
}
void DefaultMQPushConsumerImpl::shutdown()
{
RMQ_DEBUG("DefaultMQPushConsumerImpl::shutdown()");
switch (m_serviceState)
{
case CREATE_JUST:
break;
case RUNNING:
m_pConsumeMessageService->shutdown();
persistConsumerOffset();
m_pMQClientFactory->unregisterConsumer(m_pDefaultMQPushConsumer->getConsumerGroup());
m_pMQClientFactory->shutdown();
m_serviceState = SHUTDOWN_ALREADY;
break;
case SHUTDOWN_ALREADY:
break;
default:
break;
}
}
bool DefaultMQPushConsumerImpl::hasHook()
{
return !m_hookList.empty();
}
void DefaultMQPushConsumerImpl::registerHook(ConsumeMessageHook* pHook)
{
m_hookList.push_back(pHook);
}
void DefaultMQPushConsumerImpl::executeHookBefore(ConsumeMessageContext& context)
{
std::list<ConsumeMessageHook*>::iterator it = m_hookList.begin();
for (; it != m_hookList.end(); it++)
{
try
{
(*it)->consumeMessageBefore(context);
}
catch (...)
{
RMQ_WARN("consumeMessageBefore exception");
}
}
}
void DefaultMQPushConsumerImpl::executeHookAfter(ConsumeMessageContext& context)
{
std::list<ConsumeMessageHook*>::iterator it = m_hookList.begin();
for (; it != m_hookList.end(); it++)
{
try
{
(*it)->consumeMessageAfter(context);
}
catch (...)
{
RMQ_WARN("consumeMessageAfter exception");
}
}
}
void DefaultMQPushConsumerImpl::createTopic(const std::string& key, const std::string& newTopic, int queueNum)
{
m_pMQClientFactory->getMQAdminImpl()->createTopic(key, newTopic, queueNum);
}
std::set<MessageQueue>* DefaultMQPushConsumerImpl::fetchSubscribeMessageQueues(const std::string& topic)
{
std::map<std::string, std::set<MessageQueue> >& mqs = m_pRebalanceImpl->getTopicSubscribeInfoTable();
std::map<std::string, std::set<MessageQueue> >::iterator it = mqs.find(topic);
if (it == mqs.end())
{
m_pMQClientFactory->updateTopicRouteInfoFromNameServer(topic);
mqs = m_pRebalanceImpl->getTopicSubscribeInfoTable();
it = mqs.find(topic);
}
if (it == mqs.end())
{
THROW_MQEXCEPTION(MQClientException, "The topic[" + topic + "] not exist", -1);
}
std::set<MessageQueue>* result = new std::set<MessageQueue>(it->second.begin(), it->second.end());
return result;
}
DefaultMQPushConsumer* DefaultMQPushConsumerImpl::getDefaultMQPushConsumer()
{
return m_pDefaultMQPushConsumer;
}
long long DefaultMQPushConsumerImpl::earliestMsgStoreTime(const MessageQueue& mq)
{
return m_pMQClientFactory->getMQAdminImpl()->earliestMsgStoreTime(mq);
}
long long DefaultMQPushConsumerImpl::maxOffset(const MessageQueue& mq)
{
return m_pMQClientFactory->getMQAdminImpl()->maxOffset(mq);
}
long long DefaultMQPushConsumerImpl::minOffset(const MessageQueue& mq)
{
return m_pMQClientFactory->getMQAdminImpl()->minOffset(mq);
}
OffsetStore* DefaultMQPushConsumerImpl::getOffsetStore()
{
return m_pOffsetStore;
}
void DefaultMQPushConsumerImpl::setOffsetStore(OffsetStore* pOffsetStore)
{
m_pOffsetStore = pOffsetStore;
}
//MQConsumerInner
std::string DefaultMQPushConsumerImpl::groupName()
{
return m_pDefaultMQPushConsumer->getConsumerGroup();
}
MessageModel DefaultMQPushConsumerImpl::messageModel()
{
return m_pDefaultMQPushConsumer->getMessageModel();
}
ConsumeType DefaultMQPushConsumerImpl::consumeType()
{
return CONSUME_PASSIVELY;
}
ConsumeFromWhere DefaultMQPushConsumerImpl::consumeFromWhere()
{
return m_pDefaultMQPushConsumer->getConsumeFromWhere();
}
std::set<SubscriptionData> DefaultMQPushConsumerImpl::subscriptions()
{
std::set<SubscriptionData> sds;
std::map<std::string, SubscriptionData>& subscription = m_pRebalanceImpl->getSubscriptionInner();
std::map<std::string, SubscriptionData>::iterator it = subscription.begin();
for (; it != subscription.end(); it++)
{
sds.insert(it->second);
}
return sds;
}
void DefaultMQPushConsumerImpl::doRebalance()
{
if (m_pRebalanceImpl != NULL)
{
m_pRebalanceImpl->doRebalance();
}
}
void DefaultMQPushConsumerImpl::persistConsumerOffset()
{
try
{
makeSureStateOK();
std::set<MessageQueue> mqs;
{
kpr::ScopedRLock<kpr::RWMutex> lock(m_pRebalanceImpl->getProcessQueueTableLock());
std::map<MessageQueue, ProcessQueue*>& processQueueTable = m_pRebalanceImpl->getProcessQueueTable();
RMQ_FOR_EACH(processQueueTable, it)
{
mqs.insert(it->first);
}
}
m_pOffsetStore->persistAll(mqs);
}
catch (...)
{
RMQ_ERROR("persistConsumerOffset exception, group: %s",
m_pDefaultMQPushConsumer->getConsumerGroup().c_str());
}
}
void DefaultMQPushConsumerImpl::updateTopicSubscribeInfo(const std::string& topic, const std::set<MessageQueue>& info)
{
std::map<std::string, SubscriptionData>& subTable = getSubscriptionInner();
if (subTable.find(topic) != subTable.end())
{
m_pRebalanceImpl->getTopicSubscribeInfoTable().insert(std::pair<std::string, std::set<MessageQueue> >(topic, info));
}
}
std::map<std::string, SubscriptionData>& DefaultMQPushConsumerImpl::getSubscriptionInner()
{
return m_pRebalanceImpl->getSubscriptionInner();
}
bool DefaultMQPushConsumerImpl::isSubscribeTopicNeedUpdate(const std::string& topic)
{
std::map<std::string, SubscriptionData>& subTable = getSubscriptionInner();
if (subTable.find(topic) != subTable.end())
{
std::map<std::string, std::set<MessageQueue> >& mqs =
m_pRebalanceImpl->getTopicSubscribeInfoTable();
return mqs.find(topic) == mqs.end();
}
return false;
}
bool DefaultMQPushConsumerImpl::isPause()
{
return m_pause;
}
void DefaultMQPushConsumerImpl::setPause(bool pause)
{
m_pause = pause;
}
void DefaultMQPushConsumerImpl::correctTagsOffset(PullRequest& pullRequest)
{
if (pullRequest.getProcessQueue()->getMsgCount().get() == 0)
{
m_pOffsetStore->updateOffset(pullRequest.getMessageQueue(), pullRequest.getNextOffset(), true);
}
}
void DefaultMQPushConsumerImpl::pullMessage(PullRequest* pPullRequest)
{
RMQ_DEBUG("pullMessage begin: %s", pPullRequest->toString().c_str());
ProcessQueue* processQueue = pPullRequest->getProcessQueue();
if (processQueue->isDropped())
{
RMQ_WARN("the pull request[%s] is dropped.", pPullRequest->toString().c_str());
delete pPullRequest;
return;
}
pPullRequest->getProcessQueue()->setLastPullTimestamp(KPRUtil::GetCurrentTimeMillis());
try
{
makeSureStateOK();
}
catch (const MQException& e)
{
RMQ_WARN("pullMessage exception [%s], consumer state not ok", e.what());
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenException);
return;
}
if (isPause())
{
RMQ_WARN("consumer was paused, execute pull request later. instanceName={%s}",
m_pDefaultMQPushConsumer->getInstanceName().c_str());
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenSuspend);
return;
}
long size = processQueue->getMsgCount().get();
if (size > m_pDefaultMQPushConsumer->getPullThresholdForQueue())
{
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenFlowControl);
if ((flowControlTimes1++ % 3000) == 0)
{
RMQ_WARN("the consumer message buffer is full, so do flow control, {%ld} {%s} {%lld}", size,
pPullRequest->toString().c_str(), flowControlTimes1);
}
return;
}
if (!m_consumeOrderly)
{
if (processQueue->getMaxSpan() > m_pDefaultMQPushConsumer->getConsumeConcurrentlyMaxSpan())
{
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenFlowControl);
if ((flowControlTimes2++ % 3000) == 0)
{
RMQ_WARN("the queue's messages, span too long, so do flow control, size: {%ld}, pullRequest: {%s}, times: {%lld}, maxspan: {%lld}",
size, pPullRequest->toString().c_str(), flowControlTimes2, processQueue->getMaxSpan());
}
return;
}
}
std::map<std::string, SubscriptionData>& subTable = getSubscriptionInner();
std::string topic = pPullRequest->getMessageQueue().getTopic();
std::map<std::string, SubscriptionData>::iterator it = subTable.find(topic);
if (it == subTable.end())
{
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenException);
RMQ_WARN("find the consumer's subscription failed, {%s}", pPullRequest->toString().c_str());
return;
}
SubscriptionData subscriptionData = it->second;
PullCallback* pullCallback = new DefaultMQPushConsumerImplCallback(subTable[topic], this, pPullRequest);
bool commitOffsetEnable = false;
long commitOffsetValue = 0L;
if (CLUSTERING == m_pDefaultMQPushConsumer->getMessageModel())
{
commitOffsetValue = m_pOffsetStore->readOffset(pPullRequest->getMessageQueue(),
READ_FROM_MEMORY);
if (commitOffsetValue > 0)
{
commitOffsetEnable = true;
}
}
int sysFlag = PullSysFlag::buildSysFlag(
commitOffsetEnable, // commitOffset
true, // suspend
false// subscription
);
try
{
m_pPullAPIWrapper->pullKernelImpl(
pPullRequest->getMessageQueue(), // 1
"", // 2
subscriptionData.getSubVersion(), // 3
pPullRequest->getNextOffset(), // 4
m_pDefaultMQPushConsumer->getPullBatchSize(), // 5
sysFlag, // 6
commitOffsetValue,// 7
s_BrokerSuspendMaxTimeMillis, // 8
s_ConsumerTimeoutMillisWhenSuspend, // 9
ASYNC, // 10
pullCallback// 11
);
}
catch (...)
{
RMQ_ERROR("pullKernelImpl exception");
executePullRequestLater(pPullRequest, s_PullTimeDelayMillsWhenException);
}
RMQ_DEBUG("pullMessage end");
}
void DefaultMQPushConsumerImpl::executePullRequestImmediately(PullRequest* pullRequest)
{
m_pMQClientFactory->getPullMessageService()->executePullRequestImmediately(pullRequest);
}
void DefaultMQPushConsumerImpl::executePullRequestLater(PullRequest* pullRequest, long timeDelay)
{
m_pMQClientFactory->getPullMessageService()->executePullRequestLater(pullRequest, timeDelay);
}
void DefaultMQPushConsumerImpl::executeTaskLater(kpr::TimerHandler* handler, long timeDelay)
{
m_pMQClientFactory->getPullMessageService()->executeTaskLater(handler, timeDelay);
}
void DefaultMQPushConsumerImpl::makeSureStateOK()
{
if (m_serviceState != RUNNING)
{
THROW_MQEXCEPTION(MQClientException, "The consumer service state not OK, ", -1);
}
}
ConsumerStatManager* DefaultMQPushConsumerImpl::getConsumerStatManager()
{
return m_pConsumerStatManager;
}
QueryResult DefaultMQPushConsumerImpl::queryMessage(const std::string& topic,
const std::string& key,
int maxNum,
long long begin,
long long end)
{
return m_pMQClientFactory->getMQAdminImpl()->queryMessage(topic, key, maxNum, begin, end);
}
void DefaultMQPushConsumerImpl::registerMessageListener(MessageListener* pMessageListener)
{
m_pMessageListenerInner = pMessageListener;
}
void DefaultMQPushConsumerImpl::resume()
{
m_pause = false;
}
long long DefaultMQPushConsumerImpl::searchOffset(const MessageQueue& mq, long long timestamp)
{
return m_pMQClientFactory->getMQAdminImpl()->searchOffset(mq, timestamp);
}
void DefaultMQPushConsumerImpl::sendMessageBack(MessageExt& msg, int delayLevel, const std::string& brokerName)
{
try
{
std::string brokerAddr = brokerName.empty() ?
socketAddress2IPPort(msg.getStoreHost()) : m_pMQClientFactory->findBrokerAddressInPublish(brokerName);
m_pMQClientFactory->getMQClientAPIImpl()->consumerSendMessageBack(brokerAddr, msg,
m_pDefaultMQPushConsumer->getConsumerGroup(),
delayLevel,
5000);
}
catch (...)
{
RMQ_ERROR("sendMessageBack Exception, group: %s", m_pDefaultMQPushConsumer->getConsumerGroup().c_str());
Message newMsg(MixAll::getRetryTopic(m_pDefaultMQPushConsumer->getConsumerGroup()),
msg.getBody(), msg.getBodyLen());
std::string originMsgId = msg.getProperty(Message::PROPERTY_ORIGIN_MESSAGE_ID);
newMsg.putProperty(Message::PROPERTY_ORIGIN_MESSAGE_ID, UtilAll::isBlank(originMsgId) ? msg.getMsgId()
: originMsgId);
newMsg.setFlag(msg.getFlag());
newMsg.setProperties(msg.getProperties());
newMsg.putProperty(Message::PROPERTY_RETRY_TOPIC, msg.getTopic());
int reTimes = msg.getReconsumeTimes() + 1;
newMsg.putProperty(Message::PROPERTY_RECONSUME_TIME, UtilAll::toString(reTimes));
newMsg.putProperty(Message::PROPERTY_MAX_RECONSUME_TIMES, UtilAll::toString(m_pDefaultMQPushConsumer->getMaxReconsumeTimes()));
newMsg.setDelayTimeLevel(3 + reTimes);
m_pMQClientFactory->getDefaultMQProducer()->send(newMsg);
}
}
void DefaultMQPushConsumerImpl::checkConfig()
{
// consumerGroup check
Validators::checkGroup(m_pDefaultMQPushConsumer->getConsumerGroup());
// consumerGroup
if (m_pDefaultMQPushConsumer->getConsumerGroup() == MixAll::DEFAULT_CONSUMER_GROUP)
{
THROW_MQEXCEPTION(MQClientException, "consumerGroup can not equal "
+ MixAll::DEFAULT_CONSUMER_GROUP //
+ ", please specify another one.", -1);
}
if (m_pDefaultMQPushConsumer->getMessageModel() != BROADCASTING
&& m_pDefaultMQPushConsumer->getMessageModel() != CLUSTERING)
{
THROW_MQEXCEPTION(MQClientException, "messageModel is invalid ", -1);
}
// allocateMessageQueueStrategy
if (m_pDefaultMQPushConsumer->getAllocateMessageQueueStrategy() == NULL)
{
THROW_MQEXCEPTION(MQClientException, "allocateMessageQueueStrategy is null", -1);
}
// consumeFromWhereOffset
if (m_pDefaultMQPushConsumer->getConsumeFromWhere() < CONSUME_FROM_LAST_OFFSET
|| m_pDefaultMQPushConsumer->getConsumeFromWhere() > CONSUME_FROM_MAX_OFFSET)
{
THROW_MQEXCEPTION(MQClientException, "consumeFromWhere is invalid", -1);
}
// subscription
/*
if (m_pDefaultMQPushConsumer->getSubscription().size() == 0)
{
THROW_MQEXCEPTION(MQClientException,"subscription is null" ,-1);
}
*/
// messageListener
if (m_pDefaultMQPushConsumer->getMessageListener() == NULL)
{
THROW_MQEXCEPTION(MQClientException, "messageListener is null", -1);
}
MessageListener* listener = m_pDefaultMQPushConsumer->getMessageListener();
MessageListener* orderly = (dynamic_cast<MessageListenerOrderly*>(listener)) ;
MessageListener* concurrently = (dynamic_cast<MessageListenerConcurrently*>(listener)) ;
if (!orderly && !concurrently)
{
THROW_MQEXCEPTION(MQClientException,
"messageListener must be instanceof MessageListenerOrderly or MessageListenerConcurrently" ,
-1);
}
// consumeThreadMin
if (m_pDefaultMQPushConsumer->getConsumeThreadMin() < 1
|| m_pDefaultMQPushConsumer->getConsumeThreadMin() > 1000
|| m_pDefaultMQPushConsumer->getConsumeThreadMin() > m_pDefaultMQPushConsumer->getConsumeThreadMax()
)
{
THROW_MQEXCEPTION(MQClientException, "consumeThreadMin Out of range [1, 1000]", -1);
}
// consumeThreadMax
if (m_pDefaultMQPushConsumer->getConsumeThreadMax() < 1
|| m_pDefaultMQPushConsumer->getConsumeThreadMax() > 1000)
{
THROW_MQEXCEPTION(MQClientException, "consumeThreadMax Out of range [1, 1000]", -1);
}
// consumeConcurrentlyMaxSpan
if (m_pDefaultMQPushConsumer->getConsumeConcurrentlyMaxSpan() < 1
|| m_pDefaultMQPushConsumer->getConsumeConcurrentlyMaxSpan() > 65535)
{
THROW_MQEXCEPTION(MQClientException, "consumeConcurrentlyMaxSpan Out of range [1, 65535]" , -1);
}
// pullThresholdForQueue
if (m_pDefaultMQPushConsumer->getPullThresholdForQueue() < 1
|| m_pDefaultMQPushConsumer->getPullThresholdForQueue() > 65535)
{
THROW_MQEXCEPTION(MQClientException, "pullThresholdForQueue Out of range [1, 65535]", -1);
}
// pullInterval
if (m_pDefaultMQPushConsumer->getPullInterval() < 0
|| m_pDefaultMQPushConsumer->getPullInterval() > 65535)
{
THROW_MQEXCEPTION(MQClientException, "pullInterval Out of range [0, 65535]", -1);
}
// consumeMessageBatchMaxSize
if (m_pDefaultMQPushConsumer->getConsumeMessageBatchMaxSize() < 1
|| m_pDefaultMQPushConsumer->getConsumeMessageBatchMaxSize() > 1024)
{
THROW_MQEXCEPTION(MQClientException, "consumeMessageBatchMaxSize Out of range [1, 1024]", -1);
}
// pullBatchSize
if (m_pDefaultMQPushConsumer->getPullBatchSize() < 1
|| m_pDefaultMQPushConsumer->getPullBatchSize() > 1024)
{
THROW_MQEXCEPTION(MQClientException, "pullBatchSize Out of range [1, 1024]", -1);
}
}
void DefaultMQPushConsumerImpl::copySubscription()
{
try
{
std::map<std::string, std::string>& sub = m_pDefaultMQPushConsumer->getSubscription();
std::map<std::string, std::string>::iterator it = sub.begin();
for (; it != sub.end(); it++)
{
SubscriptionDataPtr subscriptionData = FilterAPI::buildSubscriptionData(it->first, it->second);
m_pRebalanceImpl->getSubscriptionInner()[it->first] = *subscriptionData;
}
if (m_pMessageListenerInner == NULL)
{
m_pMessageListenerInner = m_pDefaultMQPushConsumer->getMessageListener();
}
switch (m_pDefaultMQPushConsumer->getMessageModel())
{
case BROADCASTING:
break;
case CLUSTERING:
{
std::string retryTopic = MixAll::getRetryTopic(m_pDefaultMQPushConsumer->getConsumerGroup());
SubscriptionDataPtr subscriptionData =
FilterAPI::buildSubscriptionData(retryTopic, SubscriptionData::SUB_ALL);
m_pRebalanceImpl->getSubscriptionInner()[retryTopic] = *subscriptionData;
}
break;
default:
break;
}
}
catch (...)
{
THROW_MQEXCEPTION(MQClientException, "subscription exception", -1);
}
}
void DefaultMQPushConsumerImpl::updateTopicSubscribeInfoWhenSubscriptionChanged()
{
std::map<std::string, SubscriptionData> subTable = getSubscriptionInner();
std::map<std::string, SubscriptionData>::iterator it = subTable.begin();
for (; it != subTable.end(); it++)
{
m_pMQClientFactory->updateTopicRouteInfoFromNameServer(it->first);
}
}
MessageListener* DefaultMQPushConsumerImpl::getMessageListenerInner()
{
return m_pMessageListenerInner;
}
void DefaultMQPushConsumerImpl::subscribe(const std::string& topic, const std::string& subExpression)
{
try
{
SubscriptionDataPtr subscriptionData = FilterAPI::buildSubscriptionData(topic, subExpression);
m_pRebalanceImpl->getSubscriptionInner()[topic] = *subscriptionData;
if (m_pMQClientFactory)
{
m_pMQClientFactory->sendHeartbeatToAllBrokerWithLock();
}
}
catch (...)
{
THROW_MQEXCEPTION(MQClientException, "subscription exception", -1);
}
}
void DefaultMQPushConsumerImpl::suspend()
{
m_pause = true;
}
void DefaultMQPushConsumerImpl::unsubscribe(const std::string& topic)
{
m_pRebalanceImpl->getSubscriptionInner().erase(topic);
}
void DefaultMQPushConsumerImpl::updateConsumeOffset(MessageQueue& mq, long long offset)
{
m_pOffsetStore->updateOffset(mq, offset, false);
}
void DefaultMQPushConsumerImpl::updateCorePoolSize(int corePoolSize)
{
m_pConsumeMessageService->updateCorePoolSize(corePoolSize);
}
MessageExt* DefaultMQPushConsumerImpl::viewMessage(const std::string& msgId)
{
return m_pMQClientFactory->getMQAdminImpl()->viewMessage(msgId);
}
RebalanceImpl* DefaultMQPushConsumerImpl::getRebalanceImpl()
{
return m_pRebalanceImpl;
}
bool DefaultMQPushConsumerImpl::isConsumeOrderly()
{
return m_consumeOrderly;
}
void DefaultMQPushConsumerImpl::setConsumeOrderly(bool consumeOrderly)
{
m_consumeOrderly = consumeOrderly;
}
MQClientFactory* DefaultMQPushConsumerImpl::getmQClientFactory()
{
return m_pMQClientFactory;
}
void DefaultMQPushConsumerImpl::setmQClientFactory(MQClientFactory* mQClientFactory)
{
m_pMQClientFactory = mQClientFactory;
}
ServiceState DefaultMQPushConsumerImpl::getServiceState()
{
return m_serviceState;
}
void DefaultMQPushConsumerImpl::setServiceState(ServiceState serviceState)
{
m_serviceState = serviceState;
}
}