rocketmq 之namesrv(六)mqclient admin请求处理删除topic

一步步往源码底层探索很有意思,不过rocketmq的源码没有注解真的是很伤心,自己先跟着天河把一些注释补全 看一遍,然后自己从头到尾追进去以博客形式记录下来,加深理解!

删除topic AdminBrokerProcessor#processRequest#deleteTopic
private synchronized RemotingCommand deleteTopic(ChannelHandlerContext ctx,
        RemotingCommand request) throws RemotingCommandException {
        final RemotingCommand response = RemotingCommand.createResponseCommand(null);
        DeleteTopicRequestHeader requestHeader =
            (DeleteTopicRequestHeader) request.decodeCommandCustomHeader(DeleteTopicRequestHeader.class);

        log.info("deleteTopic called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
//        删除topic
        this.brokerController.getTopicConfigManager().deleteTopicConfig(requestHeader.getTopic());
//        删除客户端消息队列中的无用的topic
        this.brokerController.getMessageStore()
            .cleanUnusedTopic(this.brokerController.getTopicConfigManager().getTopicConfigTable().keySet());

        response.setCode(ResponseCode.SUCCESS);
        response.setRemark(null);
        return response;
    }
TopicConfigManager#deleteTopicConfig
public void deleteTopicConfig(final String topic) {
//        先删除缓存
        TopicConfig old = this.topicConfigTable.remove(topic);
        if (old != null) {
            log.info("delete topic config OK, topic: {}", old);
//            更新数据版本号
            this.dataVersion.nextVersion();
//            删除持久化文件中的topic
            this.persist();
        } else {
            log.warn("delete topic config failed, topic: {} not exists", topic);
        }
    }
this.brokerController.getMessageStore().cleanUnusedTopic

DefaultMessageStore#cleanUnusedTopic

public int cleanUnusedTopic(Set<String> topics) {
//        遍历缓存的消息队列
        Iterator<Entry<String, ConcurrentMap<Integer, ConsumeQueue>>> it = this.consumeQueueTable.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, ConcurrentMap<Integer, ConsumeQueue>> next = it.next();
            String topic = next.getKey();

            if (!topics.contains(topic) && !topic.equals(ScheduleMessageService.SCHEDULE_TOPIC)) {
                ConcurrentMap<Integer, ConsumeQueue> queueTable = next.getValue();
                for (ConsumeQueue cq : queueTable.values()) {
//                    消费队列销毁
                    cq.destroy();
                    log.info("cleanUnusedTopic: {} {} ConsumeQueue cleaned",
                        cq.getTopic(),
                        cq.getQueueId()
                    );
//                    删除消息队列
                    this.commitLog.removeQueueFromTopicQueueTable(cq.getTopic(), cq.getQueueId());
                }
//                topic所在的消息队列删除完毕后消费队列所在的集合元素删除
                it.remove();

                log.info("cleanUnusedTopic: {},topic destroyed", topic);
            }
        }

        return 0;
    }
消费队列销毁ConsumeQueue#destroy
public void destroy() {
        this.maxPhysicOffset = -1;
        this.minLogicOffset = 0;
//        映射文件队列销毁
        this.mappedFileQueue.destroy();
        if (isExtReadEnable()) {
//            消费队列销毁
            this.consumeQueueExt.destroy();
        }
    }
映射文件队列销毁MappedFileQueue#destroy
public void destroy() {
        for (MappedFile mf : this.mappedFiles) {
//            映射文件销毁 间隔3秒
            mf.destroy(1000 * 3);
        }
//        同步删除映射文件队列
        this.mappedFiles.clear();
        this.flushedWhere = 0;

        // delete parent directory 删除父级文件夹
        File file = new File(storePath);
        if (file.isDirectory()) {
            file.delete();
        }
    }
映射文件销毁MappedFile#destroy
public boolean destroy(final long intervalForcibly) {
//        清除资源
        this.shutdown(intervalForcibly);

        //如果清除完成
        if (this.isCleanupOver()) {
            try {
                //关闭channel
                this.fileChannel.close();
                log.info("close file channel " + this.fileName + " OK");

                long beginTime = System.currentTimeMillis();
//                删除文件
                boolean result = this.file.delete();
                log.info("delete file[REF:" + this.getRefCount() + "] " + this.fileName
                    + (result ? " OK, " : " Failed, ") + "W:" + this.getWrotePosition() + " M:"
                    + this.getFlushedPosition() + ", "
                    + UtilAll.computeEclipseTimeMilliseconds(beginTime));
            } catch (Exception e) {
                log.warn("close file channel " + this.fileName + " Failed. ", e);
            }

            return true;
        } else {
            log.warn("destroy mapped file[REF:" + this.getRefCount() + "] " + this.fileName
                + " Failed. cleanupOver: " + this.cleanupOver);
        }

        return false;
    }
清除资源 ReferenceResource#shutdown

this.shutdown(intervalForcibly)

public void shutdown(final long intervalForcibly) {
        if (this.available) {
            this.available = false;
            this.firstShutdownTimestamp = System.currentTimeMillis();
            //释放资源
            this.release();
        } else if (this.getRefCount() > 0) {
            if ((System.currentTimeMillis() - this.firstShutdownTimestamp) >= intervalForcibly) {
                this.refCount.set(-1000 - this.getRefCount());
                this.release();
            }
        }
    }
释放资源

this.release();

public void release() {
       long value = this.refCount.decrementAndGet();
       if (value > 0)
           return;

       synchronized (this) {

           this.cleanupOver = this.cleanup(value);
       }
   }
MappedFile#cleanup

this.cleanup(value);

public boolean cleanup(final long currentRef) {
       if (this.isAvailable()) {
           log.error("this file[REF:" + currentRef + "] " + this.fileName
               + " have not shutdown, stop unmapping.");
           return false;
       }

       if (this.isCleanupOver()) {
           log.error("this file[REF:" + currentRef + "] " + this.fileName
               + " have cleanup, do not do it again.");
           return true;
       }
//        清除映射缓冲区
       clean(this.mappedByteBuffer);
//        添加映射文件所占虚拟内存
       TOTAL_MAPPED_VIRTUAL_MEMORY.addAndGet(this.fileSize * (-1));
//        改变映射文件数量
       TOTAL_MAPPED_FILES.decrementAndGet();
       log.info("unmap file[REF:" + currentRef + "] " + this.fileName + " OK");
       return true;
   }
删除消息队列CommitLog#removeQueueFromTopicQueueTable

this.commitLog.removeQueueFromTopicQueueTable(cq.getTopic(), cq.getQueueId());

public void removeQueueFromTopicQueueTable(final String topic, final int queueId) {
       String key = topic + "-" + queueId;
       synchronized (this) {
           this.topicQueueTable.remove(key);
       }

       log.info("removeQueueFromTopicQueueTable OK Topic: {} QueueId: {}", topic, queueId);
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游语

对你有帮助,可以请我喝杯奶哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值