/*
* (C) 2007-2012 Alibaba Group Holding Limited.
*
* 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.
* Authors:
* wuhua <wq163@163.com> , boyan <killme2008@gmail.com>
*/
package com.taobao.metamorphosis.server.assembly;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.taobao.gecko.core.command.kernel.HeartBeatRequestCommand;
import com.taobao.gecko.service.RemotingFactory;
import com.taobao.gecko.service.RemotingServer;
import com.taobao.gecko.service.config.ServerConfig;
import com.taobao.gecko.service.exception.NotifyRemotingException;
import com.taobao.metamorphosis.network.GetCommand;
import com.taobao.metamorphosis.network.MetamorphosisWireFormatType;
import com.taobao.metamorphosis.network.OffsetCommand;
import com.taobao.metamorphosis.network.PutCommand;
import com.taobao.metamorphosis.network.QuitCommand;
import com.taobao.metamorphosis.network.StatsCommand;
import com.taobao.metamorphosis.network.TransactionCommand;
import com.taobao.metamorphosis.server.BrokerZooKeeper;
import com.taobao.metamorphosis.server.CommandProcessor;
import com.taobao.metamorphosis.server.exception.MetamorphosisServerStartupException;
import com.taobao.metamorphosis.server.filter.ConsumerFilterManager;
import com.taobao.metamorphosis.server.network.GetProcessor;
import com.taobao.metamorphosis.server.network.OffsetProcessor;
import com.taobao.metamorphosis.server.network.PutProcessor;
import com.taobao.metamorphosis.server.network.QuitProcessor;
import com.taobao.metamorphosis.server.network.StatsProcessor;
import com.taobao.metamorphosis.server.network.TransactionProcessor;
import com.taobao.metamorphosis.server.network.VersionProcessor;
import com.taobao.metamorphosis.server.stats.StatsManager;
import com.taobao.metamorphosis.server.store.DeletePolicy;
import com.taobao.metamorphosis.server.store.DeletePolicyFactory;
import com.taobao.metamorphosis.server.store.MessageStoreManager;
import com.taobao.metamorphosis.server.transaction.store.JournalTransactionStore;
import com.taobao.metamorphosis.server.utils.MetaConfig;
import com.taobao.metamorphosis.server.utils.MetaMBeanServer;
import com.taobao.metamorphosis.utils.IdWorker;
;
/**
* ��װ��meta server
*
* @author boyan
* @Date 2011-4-29
*
*/
public class MetaMorphosisBroker implements MetaMorphosisBrokerMBean {
private final class ShutdownHook extends Thread {
@Override
public void run() {
MetaMorphosisBroker.this.runShutdownHook = true;
MetaMorphosisBroker.this.stop();
}
}
private final MessageStoreManager storeManager;
private final ExecutorsManager executorsManager;
private final StatsManager statsManager;
private final RemotingServer remotingServer;
private final MetaConfig metaConfig;
private final IdWorker idWorker;
private final BrokerZooKeeper brokerZooKeeper;
private final ConsumerFilterManager consumerFilterManager;
private CommandProcessor brokerProcessor;
static final Log log = LogFactory.getLog(MetaMorphosisBroker.class);
private boolean shutdown = true;
private volatile boolean runShutdownHook = false;
private final ShutdownHook shutdownHook;
private boolean registerZkSuccess;
public CommandProcessor getBrokerProcessor() {
return this.brokerProcessor;
}
public MetaConfig getMetaConfig() {
return this.metaConfig;
}
public synchronized boolean isShutdown() {
return this.shutdown;
}
public MessageStoreManager getStoreManager() {
return this.storeManager;
}
public ExecutorsManager getExecutorsManager() {
return this.executorsManager;
}
public StatsManager getStatsManager() {
return this.statsManager;
}
public RemotingServer getRemotingServer() {
return this.remotingServer;
}
public ConsumerFilterManager getConsumerFilterManager() {
return this.consumerFilterManager;
}
public IdWorker getIdWorker() {
return this.idWorker;
}
public BrokerZooKeeper getBrokerZooKeeper() {
return this.brokerZooKeeper;
}
public void setBrokerProcessor(final CommandProcessor brokerProcessor) {
this.brokerProcessor = brokerProcessor;
}
public MetaMorphosisBroker(final MetaConfig metaConfig) {
super();
this.shutdownHook = new ShutdownHook();
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
this.metaConfig = metaConfig;
this.remotingServer = newRemotingServer(metaConfig);
this.executorsManager = new ExecutorsManager(metaConfig);
this.idWorker = new IdWorker(metaConfig.getBrokerId());
this.storeManager = new MessageStoreManager(metaConfig, this.newDeletePolicy(metaConfig));
this.statsManager = new StatsManager(this.metaConfig, this.storeManager, this.remotingServer);
this.brokerZooKeeper = new BrokerZooKeeper(metaConfig);
JournalTransactionStore transactionStore = null;
try {
transactionStore = new JournalTransactionStore(metaConfig.getDataLogPath(), this.storeManager, metaConfig);
}
catch (final Exception e) {
throw new MetamorphosisServerStartupException("Initializing transaction store failed", e);
}
try {
this.consumerFilterManager = new ConsumerFilterManager(metaConfig);
}
catch (final Exception e) {
throw new MetamorphosisServerStartupException("Initializing ConsumerFilterManager failed", e);
}
final BrokerCommandProcessor next =
new BrokerCommandProcessor(this.storeManager, this.executorsManager, this.statsManager,
this.remotingServer, metaConfig, this.idWorker, this.brokerZooKeeper, this.consumerFilterManager);
this.brokerProcessor =
new TransactionalCommandProcessor(metaConfig, this.storeManager, this.idWorker, next, transactionStore,
this.statsManager);
MetaMBeanServer.registMBean(this, null);
}
private DeletePolicy newDeletePolicy(final MetaConfig metaConfig) {
final String deletePolicy = metaConfig.getDeletePolicy();
if (deletePolicy != null) {
return DeletePolicyFactory.getDeletePolicy(deletePolicy);
}
return null;
}
private static RemotingServer newRemotingServer(final MetaConfig metaConfig) {
final ServerConfig serverConfig = new ServerConfig();
serverConfig.setWireFormatType(new MetamorphosisWireFormatType());
serverConfig.setPort(metaConfig.getServerPort());
final RemotingServer server = RemotingFactory.newRemotingServer(serverConfig);
return server;
}
public synchronized void start() {
if (!this.shutdown) {
return;
}
this.shutdown = false;
this.storeManager.init();
this.executorsManager.init();
this.statsManager.init();
this.registerProcessors();
try {
this.remotingServer.start();
}
catch (final NotifyRemotingException e) {
throw new MetamorphosisServerStartupException("start remoting server failed", e);
}
try {
this.brokerZooKeeper.registerBrokerInZk();
this.brokerZooKeeper.registerMasterConfigFileChecksumInZk();
this.addTopicsChangeListener();
this.registerTopicsInZk();
this.registerZkSuccess = true;
}
catch (final Exception e) {
this.registerZkSuccess = false;
throw new MetamorphosisServerStartupException("Register broker to zk failed", e);
}
log.info("Starting metamorphosis server...");
this.brokerProcessor.init();
log.info("Start metamorphosis server successfully");
}
private void registerProcessors() {
this.remotingServer.registerProcessor(GetCommand.class, new GetProcessor(this.brokerProcessor,
this.executorsManager.getGetExecutor()));
this.remotingServer.registerProcessor(PutCommand.class, new PutProcessor(this.brokerProcessor,
this.executorsManager.getUnOrderedPutExecutor()));
this.remotingServer.registerProcessor(OffsetCommand.class, new OffsetProcessor(this.brokerProcessor,
this.executorsManager.getGetExecutor()));
this.remotingServer
.registerProcessor(HeartBeatRequestCommand.class, new VersionProcessor(this.brokerProcessor));
this.remotingServer.registerProcessor(QuitCommand.class, new QuitProcessor(this.brokerProcessor));
this.remotingServer.registerProcessor(StatsCommand.class, new StatsProcessor(this.brokerProcessor));
this.remotingServer.registerProcessor(TransactionCommand.class, new TransactionProcessor(this.brokerProcessor,
this.executorsManager.getUnOrderedPutExecutor()));
}
private void addTopicsChangeListener() {
// ����topics�б�仯��ע�ᵽzk
this.metaConfig.addPropertyChangeListener("topics", new PropertyChangeListener() {
@Override
public void propertyChange(final PropertyChangeEvent evt) {
try {
MetaMorphosisBroker.this.registerTopicsInZk();
}
catch (final Exception e) {
log.error("Register topic in zk failed", e);
}
}
});
}
private void registerTopicsInZk() throws Exception {
// ��ע�����õ�topic��zookeeper
for (final String topic : this.metaConfig.getTopics()) {
this.brokerZooKeeper.registerTopicInZk(topic, true);
}
// ע����ص�topic��zookeeper
for (final String topic : this.storeManager.getMessageStores().keySet()) {
this.brokerZooKeeper.registerTopicInZk(topic, true);
}
}
@Override
public synchronized void stop() {
if (this.shutdown) {
return;
}
log.info("Stopping metamorphosis server...");
this.shutdown = true;
this.brokerZooKeeper.close(this.registerZkSuccess);
try {
// Waiting for zookeeper to notify clients.
Thread.sleep(this.brokerZooKeeper.getZkConfig().zkSyncTimeMs);
}
catch (InterruptedException e) {
// ignore
}
this.executorsManager.dispose();
this.storeManager.dispose();
this.statsManager.dispose();
try {
this.remotingServer.stop();
}
catch (final NotifyRemotingException e) {
log.error("Shutdown remoting server failed", e);
}
if (!this.runShutdownHook && this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (Exception e) {
// ignore
}
}
this.brokerProcessor.dispose();
EmbedZookeeperServer.getInstance().stop();
log.info("Stop metamorphosis server successfully");
}
}