blob: fde770d1ce1bec05eaf093caf6797a384c78d2b1 [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 "RebalancePushImpl.h"
#include <string.h>
#include <limits.h>
#include "DefaultMQPushConsumerImpl.h"
#include "AllocateMessageQueueStrategy.h"
#include "MQClientFactory.h"
#include "MessageQueueListener.h"
#include "OffsetStore.h"
#include "DefaultMQPushConsumer.h"
#include "MQAdminImpl.h"
namespace rmq
{
RebalancePushImpl::RebalancePushImpl(DefaultMQPushConsumerImpl* pDefaultMQPushConsumerImpl)
: RebalanceImpl("", BROADCASTING, NULL, NULL),
m_pDefaultMQPushConsumerImpl(pDefaultMQPushConsumerImpl)
{
}
RebalancePushImpl::RebalancePushImpl(const std::string& consumerGroup,
MessageModel messageModel,
AllocateMessageQueueStrategy* pAllocateMessageQueueStrategy,
MQClientFactory* pMQClientFactory,
DefaultMQPushConsumerImpl* pDefaultMQPushConsumerImpl)
: RebalanceImpl(consumerGroup, messageModel, pAllocateMessageQueueStrategy, pMQClientFactory),
m_pDefaultMQPushConsumerImpl(pDefaultMQPushConsumerImpl)
{
}
void RebalancePushImpl::dispatchPullRequest(std::list<PullRequest*>& pullRequestList)
{
std::list<PullRequest*>::iterator it = pullRequestList.begin();
for (; it != pullRequestList.end(); it++)
{
m_pDefaultMQPushConsumerImpl->executePullRequestImmediately(*it);
RMQ_INFO("doRebalance, {%s}, add a new pull request {%s}",
m_consumerGroup.c_str(), (*it)->toString().c_str());
}
}
long long RebalancePushImpl::computePullFromWhere(MessageQueue& mq)
{
long long result = -1;
ConsumeFromWhere consumeFromWhere =
m_pDefaultMQPushConsumerImpl->getDefaultMQPushConsumer()->getConsumeFromWhere();
OffsetStore* offsetStore = m_pDefaultMQPushConsumerImpl->getOffsetStore();
switch (consumeFromWhere)
{
case CONSUME_FROM_FIRST_OFFSET:
{
long long lastOffset = offsetStore->readOffset(mq, READ_FROM_STORE);
if (lastOffset >= 0)
{
result = lastOffset;
}
else if (-1 == lastOffset)
{
result = 0L;
}
else
{
result = -1;
}
break;
}
case CONSUME_FROM_LAST_OFFSET:
{
long long lastOffset = offsetStore->readOffset(mq, READ_FROM_STORE);
if (lastOffset >= 0)
{
result = lastOffset;
}
else if (-1 == lastOffset)
{
if (strncmp(MixAll::RETRY_GROUP_TOPIC_PREFIX.c_str(), mq.getTopic().c_str(), MixAll::RETRY_GROUP_TOPIC_PREFIX.size()) == 0)
{
result = 0L;
}
else
{
//result = LLONG_MAX;
try
{
result = m_pMQClientFactory->getMQAdminImpl()->maxOffset(mq);
}
catch(...)
{
result = -1;
}
}
}
else
{
result = -1;
}
break;
}
case CONSUME_FROM_MAX_OFFSET:
result = LLONG_MAX;
break;
case CONSUME_FROM_MIN_OFFSET:
result = 0L;
break;
case CONSUME_FROM_TIMESTAMP:
{
long long lastOffset = offsetStore->readOffset(mq, READ_FROM_STORE);
if (lastOffset >= 0)
{
result = lastOffset;
}
else if (-1 == lastOffset)
{
if (strncmp(MixAll::RETRY_GROUP_TOPIC_PREFIX.c_str(), mq.getTopic().c_str(), MixAll::RETRY_GROUP_TOPIC_PREFIX.size()) == 0)
{
//result = LLONG_MAX;
try
{
result = m_pMQClientFactory->getMQAdminImpl()->maxOffset(mq);
}
catch(...)
{
result = -1;
}
}
else
{
try
{
long timestamp = UtilAll::str2tm(
m_pDefaultMQPushConsumerImpl->getDefaultMQPushConsumer()->getConsumeTimestamp(),
rmq::yyyyMMddHHmmss);
result = m_pMQClientFactory->getMQAdminImpl()->searchOffset(mq, timestamp);
}
catch(...)
{
result = -1;
}
}
}
else
{
result = -1;
}
break;
}
break;
default:
break;
}
return result;
}
void RebalancePushImpl::messageQueueChanged(const std::string& topic,
std::set<MessageQueue>& mqAll,
std::set<MessageQueue>& mqDivided)
{
}
bool RebalancePushImpl::removeUnnecessaryMessageQueue(MessageQueue& mq, ProcessQueue& pq)
{
m_pDefaultMQPushConsumerImpl->getOffsetStore()->persist(mq);
m_pDefaultMQPushConsumerImpl->getOffsetStore()->removeOffset(mq);
if (m_pDefaultMQPushConsumerImpl->isConsumeOrderly()
&& m_pDefaultMQPushConsumerImpl->messageModel() == CLUSTERING)
{
if (pq.getLockConsume().TryLock(1000))
{
try
{
this->unlock(mq, true);
}
catch (std::exception& e)
{
RMQ_ERROR("removeUnnecessaryMessageQueue Exception: %s", e.what());
}
pq.getLockConsume().Unlock();
}
else
{
RMQ_WARN("[WRONG]mq is consuming, so can not unlock it, MQ:%s, maybe hanged for a while, times:{%lld}",
mq.toString().c_str(),
pq.getTryUnlockTimes());
pq.incTryUnlockTimes();
}
return false;
}
return true;
}
}