提交 04e97de8 编写于 作者: Y yukon

[ROCKETMQ-332] Fix concurrent bug in MappedFileQueue#findMappedFileByOffset,...

[ROCKETMQ-332] Fix concurrent bug in MappedFileQueue#findMappedFileByOffset, which may cause message loss
上级 d849e0ad
......@@ -461,26 +461,38 @@ public class MappedFileQueue {
*/
public MappedFile findMappedFileByOffset(final long offset, final boolean returnFirstOnNotFound) {
try {
MappedFile mappedFile = this.getFirstMappedFile();
if (mappedFile != null) {
int index = (int) ((offset / this.mappedFileSize) - (mappedFile.getFileFromOffset() / this.mappedFileSize));
MappedFile firstMappedFile = this.getFirstMappedFile();
if (firstMappedFile != null) {
int index = (int) ((offset / this.mappedFileSize) - (firstMappedFile.getFileFromOffset() / this.mappedFileSize));
if (index < 0 || index >= this.mappedFiles.size()) {
LOG_ERROR.warn("Offset for {} not matched. Request offset: {}, index: {}, " +
"mappedFileSize: {}, mappedFiles count: {}",
mappedFile,
LOG_ERROR.warn("Offset for {} not matched. Request offset: {}, index: {}, mappedFileSize: {}, mappedFiles count: {}",
firstMappedFile,
offset,
index,
this.mappedFileSize,
this.mappedFiles.size());
} else {
MappedFile targetFile = null;
try {
targetFile = this.mappedFiles.get(index);
} catch (Exception ignored) {
}
try {
return this.mappedFiles.get(index);
} catch (Exception e) {
if (returnFirstOnNotFound) {
return mappedFile;
if (targetFile != null && offset >= targetFile.getFileFromOffset()
&& offset < targetFile.getFileFromOffset() + this.mappedFileSize) {
return targetFile;
}
for (MappedFile tmpMappedFile : this.mappedFiles) {
if (offset >= tmpMappedFile.getFileFromOffset()
&& offset < tmpMappedFile.getFileFromOffset() + this.mappedFileSize) {
return tmpMappedFile;
}
}
LOG_ERROR.warn("findMappedFileByOffset failure. ", e);
}
if (returnFirstOnNotFound) {
return firstMappedFile;
}
}
} catch (Exception e) {
......
......@@ -229,6 +229,24 @@ public class MappedFileQueueTest {
assertThat(mappedFileQueue.getMappedFiles().size()).isEqualTo(45);
}
@Test
public void testFindMappedFile_ByIteration() {
MappedFileQueue mappedFileQueue =
new MappedFileQueue("target/unit_test_store/g/", 1024, null);
for (int i =0 ; i < 3; i++) {
MappedFile mappedFile = mappedFileQueue.getLastMappedFile(1024 * i);
mappedFile.wrotePosition.set(1024);
}
assertThat(mappedFileQueue.findMappedFileByOffset(1028).getFileFromOffset()).isEqualTo(1024);
// Switch two MappedFiles and verify findMappedFileByOffset method
MappedFile tmpFile = mappedFileQueue.getMappedFiles().get(1);
mappedFileQueue.getMappedFiles().set(1, mappedFileQueue.getMappedFiles().get(2));
mappedFileQueue.getMappedFiles().set(2, tmpFile);
assertThat(mappedFileQueue.findMappedFileByOffset(1028).getFileFromOffset()).isEqualTo(1024);
}
@After
public void destory() {
File file = new File("target/unit_test_store");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册