一步步往源码底层探索很有意思,不过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);
}