package com.alibaba.rocketmq.namesrv.daemon; import static com.alibaba.rocketmq.common.protocol.MQProtos.MQRequestCode.SYNC_NAMESRV_RUNTIME_CONF_VALUE; import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_INVALID; import static com.alibaba.rocketmq.namesrv.common.MergeResult.MERGE_SUCCESS; import static com.alibaba.rocketmq.namesrv.common.MergeResult.NOT_MERGE; import static com.alibaba.rocketmq.namesrv.common.MergeResult.SYS_ERROR; import static com.alibaba.rocketmq.remoting.protocol.RemotingProtos.ResponseCode.SUCCESS_VALUE; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.rocketmq.common.MixAll; import com.alibaba.rocketmq.common.ServiceThread; import com.alibaba.rocketmq.common.namesrv.NamesrvConfig; import com.alibaba.rocketmq.common.namesrv.TopicRuntimeData; import com.alibaba.rocketmq.namesrv.common.Result; import com.alibaba.rocketmq.namesrv.sync.Exec; import com.alibaba.rocketmq.namesrv.sync.FutureGroup; import com.alibaba.rocketmq.namesrv.sync.TaskGroup; import com.alibaba.rocketmq.namesrv.sync.TaskGroupExecutor; import com.alibaba.rocketmq.namesrv.topic.TopicRuntimeDataManager; import com.alibaba.rocketmq.remoting.common.RemotingHelper; import com.alibaba.rocketmq.remoting.protocol.RemotingCommand; /** * namesrv��Ⱥ���ڵ������ͬ�� * * @author lansheng.zj@taobao.com */ public class NamesrvSync extends ServiceThread { private static final Logger log = LoggerFactory.getLogger(MixAll.NamesrvLoggerName); private TaskGroupExecutor<Object, Object> syncTaskGroupExecutor; private TopicRuntimeDataManager topicRuntimeDataManager; private NamesrvConfig namesrvConf; private TaskGroup<Object, Object> syncTaskGroup; public NamesrvSync(NamesrvConfig namesrvConf, TopicRuntimeDataManager topicRuntimeDataManager) { this.namesrvConf = namesrvConf; this.topicRuntimeDataManager = topicRuntimeDataManager; syncTaskGroup = createTaskGroup(); syncTaskGroupExecutor = new TaskGroupExecutor<Object, Object>(new ThreadFactory() { private AtomicInteger index = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { return new Thread(r, "sync-taskgroup-executor-" + index.getAndIncrement()); } }); } private TaskGroup<Object, Object> createTaskGroup() { TaskGroup<Object, Object> taskGroup = new TaskGroup<Object, Object>(); String namesrv = namesrvConf.getNamesrvAddr(); if (null != namesrv && !"".equals(namesrv)) { String[] addresses = namesrv.split(";"); for (String address : addresses) { // �ų�������������ע������ if (!MixAll.isLocalAddr(address)) { taskGroup.addTask(address, createTask(address)); } } } return taskGroup; } public void init() { namesrvConf.addPropertyChangeListener("namesrvAddr", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { // copyOnWirte syncTaskGroup = createTaskGroup(); } }); } private Exec<Object, Object> createTask(final String address) { return new Exec<Object, Object>() { @Override public void beforeExec() { // TODO log } @Override public Object doExec(Object object) throws Exception { // ����ͬ�����ڵ�����ݣ�������ȡ��ʽ��ֻͬ��namesrv�ϳ־û����� RemotingCommand request = RemotingCommand.createRequestCommand(SYNC_NAMESRV_RUNTIME_CONF_VALUE, null); RemotingCommand response = RemotingHelper.invokeSync(address, request, namesrvConf.getSyncTimeout()); if (SUCCESS_VALUE == response.getCode()) { byte[] data = response.getBody(); TopicRuntimeData topicRuntimeData = TopicRuntimeData.decode(data); // �ϲ�����,��ͬkey���ݲ�ͬ��ɾ�����ݣ����������⣬û��ɾ����������ɾ���� int code = topicRuntimeDataManager.merge(topicRuntimeData); switch (code) { case NOT_MERGE: // TODO ͳ������ break; case MERGE_SUCCESS: // TODO ͳ������ break; case MERGE_INVALID: // TODO ���� break; case SYS_ERROR: // TODO ���� break; default: } } else { // TODO } return null; } }; } public FutureGroup<Object> groupCommit() { return syncTaskGroupExecutor.groupCommit(syncTaskGroup, null); } @Override public void run() { try { // initial delay Thread.sleep(2000L); } catch (InterruptedException e) { log.error("namesrv sync initial delay interrupted.", e); } while (!isStoped()) { try { FutureGroup<Object> futureGroup = groupCommit(); long timeout = namesrvConf.getSyncTimeout(); Result result = futureGroup.await(timeout); if (!result.isSuccess()) { // ��ʱδ���ر��� log.error("namesrv sync timeout(" + timeout + "). detail:" + result.getDetail()); } this.waitForRunning(namesrvConf.getSyncInterval()); } catch (Exception e) { // exception handler log.error("namesrv sync exception.", e); } } } @Override public String getServiceName() { return "namesrv-sync"; } public void shutdown() { super.shutdown(); syncTaskGroupExecutor.shutdown(); } @Override public void stop() { super.stop(); syncTaskGroupExecutor.shutdown(); } @Override public void stop(boolean interrupt) { super.stop(interrupt); syncTaskGroupExecutor.shutdown(); } }