com.alibaba.rocketmq.store.StoreCheckpoint Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2013 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.
*/
package com.alibaba.rocketmq.store;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.rocketmq.common.UtilAll;
import com.alibaba.rocketmq.common.constant.LoggerName;
/**
* 记录存储模型最终一致的时间点
*
* @author shijia.wxr
* @since 2013-7-21
*/
public class StoreCheckpoint {
private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName);
private final RandomAccessFile randomAccessFile;
private final FileChannel fileChannel;
private final MappedByteBuffer mappedByteBuffer;
private volatile long physicMsgTimestamp = 0;
private volatile long logicsMsgTimestamp = 0;
private volatile long indexMsgTimestamp = 0;
public StoreCheckpoint(final String scpPath) throws IOException {
File file = new File(scpPath);
MapedFile.ensureDirOK(file.getParent());
boolean fileExists = file.exists();
this.randomAccessFile = new RandomAccessFile(file, "rw");
this.fileChannel = this.randomAccessFile.getChannel();
this.mappedByteBuffer = fileChannel.map(MapMode.READ_WRITE, 0, MapedFile.OS_PAGE_SIZE);
if (fileExists) {
log.info("store checkpoint file exists, " + scpPath);
this.physicMsgTimestamp = this.mappedByteBuffer.getLong(0);
this.logicsMsgTimestamp = this.mappedByteBuffer.getLong(8);
this.indexMsgTimestamp = this.mappedByteBuffer.getLong(16);
log.info("store checkpoint file physicMsgTimestamp " + this.physicMsgTimestamp + ", "
+ UtilAll.timeMillisToHumanString(this.physicMsgTimestamp));
log.info("store checkpoint file logicsMsgTimestamp " + this.logicsMsgTimestamp + ", "
+ UtilAll.timeMillisToHumanString(this.logicsMsgTimestamp));
log.info("store checkpoint file indexMsgTimestamp " + this.indexMsgTimestamp + ", "
+ UtilAll.timeMillisToHumanString(this.indexMsgTimestamp));
}
else {
log.info("store checkpoint file not exists, " + scpPath);
}
}
public void shutdown() {
this.flush();
// unmap mappedByteBuffer
MapedFile.clean(this.mappedByteBuffer);
try {
this.fileChannel.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public void flush() {
this.mappedByteBuffer.putLong(0, this.physicMsgTimestamp);
this.mappedByteBuffer.putLong(8, this.logicsMsgTimestamp);
this.mappedByteBuffer.putLong(16, this.indexMsgTimestamp);
this.mappedByteBuffer.force();
}
public long getPhysicMsgTimestamp() {
return physicMsgTimestamp;
}
public void setPhysicMsgTimestamp(long physicMsgTimestamp) {
this.physicMsgTimestamp = physicMsgTimestamp;
}
public long getLogicsMsgTimestamp() {
return logicsMsgTimestamp;
}
public void setLogicsMsgTimestamp(long logicsMsgTimestamp) {
this.logicsMsgTimestamp = logicsMsgTimestamp;
}
public long getMinTimestampIndex() {
return Math.min(this.getMinTimestamp(), this.indexMsgTimestamp);
}
public long getMinTimestamp() {
long min = Math.min(this.physicMsgTimestamp, this.logicsMsgTimestamp);
// 向前倒退3s,防止因为时间精度问题导致丢数据
// fixed https://github.com/alibaba/RocketMQ/issues/467
min -= 1000 * 3;
if (min < 0)
min = 0;
return min;
}
public long getIndexMsgTimestamp() {
return indexMsgTimestamp;
}
public void setIndexMsgTimestamp(long indexMsgTimestamp) {
this.indexMsgTimestamp = indexMsgTimestamp;
}
}