private void createAndUpdateQueueData(final String brokerName, final TopicConfig topicConfig) {
    QueueData queueData = new QueueData();
    queueData.setBrokerName(brokerName);
    queueData.setWriteQueueNums(topicConfig.getWriteQueueNums());
    queueData.setReadQueueNums(topicConfig.getReadQueueNums());
    queueData.setPerm(topicConfig.getPerm());

    List<QueueData> queueDataList = this.topicQueueTable.get(topicConfig.getTopicName());
    if (null == queueDataList) {
      queueDataList = new LinkedList<QueueData>();
      queueDataList.add(queueData);
      this.topicQueueTable.put(topicConfig.getTopicName(), queueDataList);
      log.info("new topic registerd, {} {}", topicConfig.getTopicName(), queueData);
    } else {
      boolean addNewOne = true;

      Iterator<QueueData> it = queueDataList.iterator();
      while (it.hasNext()) {
        QueueData qd = it.next();
        if (qd.getBrokerName().equals(brokerName)) {
          if (qd.equals(queueData)) {
            addNewOne = false;
          } else {
            log.info(
                "topic changed, {} OLD: {} NEW: {}", topicConfig.getTopicName(), qd, queueData);
            it.remove();
          }
        }
      }

      if (addNewOne) {
        queueDataList.add(queueData);
      }
    }
  }
  private RemotingCommand getTopicStatsInfo(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetTopicStatsInfoRequestHeader requestHeader =
        (GetTopicStatsInfoRequestHeader)
            request.decodeCommandCustomHeader(GetTopicStatsInfoRequestHeader.class);

    final String topic = requestHeader.getTopic();
    TopicConfig topicConfig =
        this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
    if (null == topicConfig) {
      response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE);
      response.setRemark("topic[" + topic + "] not exist");
      return response;
    }

    TopicStatsTable topicStatsTable = new TopicStatsTable();
    for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) {
      MessageQueue mq = new MessageQueue();
      mq.setTopic(topic);
      mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
      mq.setQueueId(i);

      TopicOffset topicOffset = new TopicOffset();
      long min = this.brokerController.getMessageStore().getMinOffsetInQuque(topic, i);
      if (min < 0) min = 0;

      long max = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i);
      if (max < 0) max = 0;

      long timestamp = 0;
      if (max > 0) {
        timestamp =
            this.brokerController.getMessageStore().getMessageStoreTimeStamp(topic, i, (max - 1));
      }

      topicOffset.setMinOffset(min);
      topicOffset.setMaxOffset(max);
      topicOffset.setLastUpdateTimestamp(timestamp);

      topicStatsTable.getOffsetTable().put(mq, topicOffset);
    }

    byte[] body = topicStatsTable.encode();
    response.setBody(body);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  private RemotingCommand getConsumeStats(ChannelHandlerContext ctx, RemotingCommand request)
      throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(null);
    final GetConsumeStatsRequestHeader requestHeader =
        (GetConsumeStatsRequestHeader)
            request.decodeCommandCustomHeader(GetConsumeStatsRequestHeader.class);

    ConsumeStats consumeStats = new ConsumeStats();

    Set<String> topics =
        this.brokerController
            .getConsumerOffsetManager()
            .whichTopicByConsumer(requestHeader.getConsumerGroup());

    for (String topic : topics) {
      TopicConfig topicConfig =
          this.brokerController.getTopicConfigManager().selectTopicConfig(topic);
      if (null == topicConfig) {
        response.setCode(MQResponseCode.TOPIC_NOT_EXIST_VALUE);
        response.setRemark("topic[" + topic + "] not exist");
        return response;
      }

      for (int i = 0; i < topicConfig.getWriteQueueNums(); i++) {
        MessageQueue mq = new MessageQueue();
        mq.setTopic(topic);
        mq.setBrokerName(this.brokerController.getBrokerConfig().getBrokerName());
        mq.setQueueId(i);

        OffsetWrapper offsetWrapper = new OffsetWrapper();

        long brokerOffset = this.brokerController.getMessageStore().getMaxOffsetInQuque(topic, i);
        if (brokerOffset < 0) brokerOffset = 0;

        long consumerOffset =
            this.brokerController
                .getConsumerOffsetManager()
                .queryOffset( //
                    requestHeader.getConsumerGroup(), //
                    topic, //
                    i);
        if (consumerOffset < 0) consumerOffset = 0;

        offsetWrapper.setBrokerOffset(brokerOffset);
        offsetWrapper.setConsumerOffset(consumerOffset);

        // 查询消费者最后一条消息对应的时间戳
        long timeOffset = consumerOffset - 1;
        if (timeOffset >= 0) {
          long lastTimestamp =
              this.brokerController
                  .getMessageStore()
                  .getMessageStoreTimeStamp(topic, i, timeOffset);
          if (lastTimestamp > 0) {
            offsetWrapper.setLastTimestamp(lastTimestamp);
          }
        }

        consumeStats.getOffsetTable().put(mq, offsetWrapper);
      }

      long consumeTps =
          this.brokerController
              .getConsumerOffsetManager()
              .computePullTPS(topic, requestHeader.getConsumerGroup());

      consumeTps += consumeStats.getConsumeTps();
      consumeStats.setConsumeTps(consumeTps);
    }

    byte[] body = consumeStats.encode();
    response.setBody(body);
    response.setCode(ResponseCode.SUCCESS_VALUE);
    response.setRemark(null);
    return response;
  }
  @Override
  public void execute(final CommandLine commandLine, final Options options, RPCHook rpcHook) {
    DefaultMQAdminExt defaultMQAdminExt = new DefaultMQAdminExt(rpcHook);
    defaultMQAdminExt.setInstanceName(Long.toString(System.currentTimeMillis()));

    try {
      TopicConfig topicConfig = new TopicConfig();
      topicConfig.setReadQueueNums(8);
      topicConfig.setWriteQueueNums(8);
      topicConfig.setTopicName(commandLine.getOptionValue('t').trim());

      // readQueueNums
      if (commandLine.hasOption('r')) {
        topicConfig.setReadQueueNums(Integer.parseInt(commandLine.getOptionValue('r').trim()));
      }

      // writeQueueNums
      if (commandLine.hasOption('w')) {
        topicConfig.setWriteQueueNums(Integer.parseInt(commandLine.getOptionValue('w').trim()));
      }

      // perm
      if (commandLine.hasOption('p')) {
        topicConfig.setPerm(Integer.parseInt(commandLine.getOptionValue('p').trim()));
      }

      boolean isUnit = false;
      if (commandLine.hasOption('u')) {
        isUnit = Boolean.parseBoolean(commandLine.getOptionValue('u').trim());
      }

      boolean isCenterSync = false;
      if (commandLine.hasOption('s')) {
        isCenterSync = Boolean.parseBoolean(commandLine.getOptionValue('s').trim());
      }

      int topicCenterSync = TopicSysFlag.buildSysFlag(isUnit, isCenterSync);
      topicConfig.setTopicSysFlag(topicCenterSync);

      boolean isOrder = false;
      if (commandLine.hasOption('o')) {
        isOrder = Boolean.parseBoolean(commandLine.getOptionValue('o').trim());
      }
      topicConfig.setOrder(isOrder);

      if (commandLine.hasOption('b')) {
        String addr = commandLine.getOptionValue('b').trim();

        defaultMQAdminExt.start();
        defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig);

        if (isOrder) {
          String brokerName = CommandUtil.fetchBrokerNameByAddr(defaultMQAdminExt, addr);
          String orderConf = brokerName + ":" + topicConfig.getWriteQueueNums();
          defaultMQAdminExt.createOrUpdateOrderConf(topicConfig.getTopicName(), orderConf, false);
          System.out.println(
              String.format(
                  "set broker orderConf. isOrder=%s, orderConf=[%s]",
                  isOrder, orderConf.toString()));
        }
        System.out.printf("create topic to %s success.%n", addr);
        System.out.println(topicConfig);
        return;

      } else if (commandLine.hasOption('c')) {
        String clusterName = commandLine.getOptionValue('c').trim();

        defaultMQAdminExt.start();

        Set<String> masterSet =
            CommandUtil.fetchMasterAddrByClusterName(defaultMQAdminExt, clusterName);
        for (String addr : masterSet) {
          defaultMQAdminExt.createAndUpdateTopicConfig(addr, topicConfig);
          System.out.printf("create topic to %s success.%n", addr);
        }

        if (isOrder) {
          Set<String> brokerNameSet =
              CommandUtil.fetchBrokerNameByClusterName(defaultMQAdminExt, clusterName);
          StringBuilder orderConf = new StringBuilder();
          String splitor = "";
          for (String s : brokerNameSet) {
            orderConf.append(splitor).append(s).append(":").append(topicConfig.getWriteQueueNums());
            splitor = ";";
          }
          defaultMQAdminExt.createOrUpdateOrderConf(
              topicConfig.getTopicName(), orderConf.toString(), true);
          System.out.println(
              String.format(
                  "set cluster orderConf. isOrder=%s, orderConf=[%s]",
                  isOrder, orderConf.toString()));
        }

        System.out.println(topicConfig);
        return;
      }

      ServerUtil.printCommandLineHelp("mqadmin " + this.commandName(), options);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      defaultMQAdminExt.shutdown();
    }
  }
  /** 发消息时,如果Topic不存在,尝试创建 */
  public TopicConfig createTopicInSendMessageMethod(
      final String topic,
      final String defaultTopic,
      final String remoteAddress,
      final int clientDefaultTopicQueueNums) {
    TopicConfig topicConfig = null;
    boolean createNew = false;

    try {
      if (this.lockTopicConfigTable.tryLock(LockTimeoutMillis, TimeUnit.MILLISECONDS)) {
        try {
          topicConfig = this.topicConfigTable.get(topic);
          if (topicConfig != null) return topicConfig;

          TopicConfig defaultTopicConfig = this.topicConfigTable.get(defaultTopic);
          if (defaultTopicConfig != null) {
            if (PermName.isInherited(defaultTopicConfig.getPerm())) {
              topicConfig = new TopicConfig(topic);

              int queueNums =
                  clientDefaultTopicQueueNums > defaultTopicConfig.getWriteQueueNums()
                      ? defaultTopicConfig.getWriteQueueNums()
                      : clientDefaultTopicQueueNums;

              if (queueNums < 0) {
                queueNums = 0;
              }

              topicConfig.setReadQueueNums(queueNums);
              topicConfig.setWriteQueueNums(queueNums);
              int perm = defaultTopicConfig.getPerm();
              perm &= ~PermName.PERM_INHERIT;
              topicConfig.setPerm(perm);
              topicConfig.setTopicFilterType(defaultTopicConfig.getTopicFilterType());
            } else {
              log.warn(
                  "create new topic failed, because the default topic["
                      + defaultTopic
                      + "] no perm, "
                      + defaultTopicConfig.getPerm()
                      + " producer: "
                      + remoteAddress);
            }
          } else {
            log.warn(
                "create new topic failed, because the default topic["
                    + defaultTopic
                    + "] not exist."
                    + " producer: "
                    + remoteAddress);
          }

          if (topicConfig != null) {
            log.info(
                "create new topic by default topic["
                    + defaultTopic
                    + "], "
                    + topicConfig
                    + " producer: "
                    + remoteAddress);

            this.topicConfigTable.put(topic, topicConfig);

            createNew = true;

            this.persist();
          }
        } finally {
          this.lockTopicConfigTable.unlock();
        }
      }
    } catch (InterruptedException e) {
      log.error("createTopicInSendMessageMethod exception", e);
    }

    if (createNew) {
      this.brokerController.registerBrokerAll();
    }

    return topicConfig;
  }