public long getMinOffset() { MapedFile mapedFile = this.mapedFileQueue.getFirstMapedFileOnLock(); if (mapedFile != null) { if (mapedFile.isAvailable()) { return mapedFile.getFileFromOffset(); } else { return this.rollNextFile(mapedFile.getFileFromOffset()); } } return -1; }
/** 正常退出时,数据恢复,所有内存数据都已经刷盘 */ public void recoverNormally() { boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); final List<MapedFile> mapedFiles = this.mapedFileQueue.getMapedFiles(); if (!mapedFiles.isEmpty()) { // 从倒数第三个文件开始恢复 int index = mapedFiles.size() - 3; if (index < 0) index = 0; MapedFile mapedFile = mapedFiles.get(index); ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); long processOffset = mapedFile.getFileFromOffset(); long mapedFileOffset = 0; while (true) { DispatchRequest dispatchRequest = this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); int size = dispatchRequest.getMsgSize(); // 正常数据 if (size > 0) { mapedFileOffset += size; } // 文件中间读到错误 else if (size == -1) { log.info("recover physics file end, " + mapedFile.getFileName()); break; } // 走到文件末尾,切换至下一个文件 // 由于返回0代表是遇到了最后的空洞,这个可以不计入truncate offset中 else if (size == 0) { index++; if (index >= mapedFiles.size()) { // 当前条件分支不可能发生 log.info( "recover last 3 physics file over, last maped file " + mapedFile.getFileName()); break; } else { mapedFile = mapedFiles.get(index); byteBuffer = mapedFile.sliceByteBuffer(); processOffset = mapedFile.getFileFromOffset(); mapedFileOffset = 0; log.info("recover next physics file, " + mapedFile.getFileName()); } } } processOffset += mapedFileOffset; this.mapedFileQueue.setCommittedWhere(processOffset); this.mapedFileQueue.truncateDirtyFiles(processOffset); } }
public void recoverAbnormally() { // 根据最小时间戳来恢复 boolean checkCRCOnRecover = this.defaultMessageStore.getMessageStoreConfig().isCheckCRCOnRecover(); final List<MapedFile> mapedFiles = this.mapedFileQueue.getMapedFiles(); if (!mapedFiles.isEmpty()) { // 寻找从哪个文件开始恢复 int index = mapedFiles.size() - 1; MapedFile mapedFile = null; for (; index >= 0; index--) { mapedFile = mapedFiles.get(index); if (this.isMapedFileMatchedRecover(mapedFile)) { log.info("recover from this maped file " + mapedFile.getFileName()); break; } } if (index < 0) { index = 0; mapedFile = mapedFiles.get(index); } ByteBuffer byteBuffer = mapedFile.sliceByteBuffer(); long processOffset = mapedFile.getFileFromOffset(); long mapedFileOffset = 0; while (true) { DispatchRequest dispatchRequest = this.checkMessageAndReturnSize(byteBuffer, checkCRCOnRecover); int size = dispatchRequest.getMsgSize(); // 正常数据 if (size > 0) { mapedFileOffset += size; this.defaultMessageStore.putDispatchRequest(dispatchRequest); } // 文件中间读到错误 else if (size == -1) { log.info("recover physics file end, " + mapedFile.getFileName()); break; } // 走到文件末尾,切换至下一个文件 // 由于返回0代表是遇到了最后的空洞,这个可以不计入truncate offset中 else if (size == 0) { index++; if (index >= mapedFiles.size()) { // 当前条件分支正常情况下不应该发生 log.info("recover physics file over, last maped file " + mapedFile.getFileName()); break; } else { mapedFile = mapedFiles.get(index); byteBuffer = mapedFile.sliceByteBuffer(); processOffset = mapedFile.getFileFromOffset(); mapedFileOffset = 0; log.info("recover next physics file, " + mapedFile.getFileName()); } } } processOffset += mapedFileOffset; this.mapedFileQueue.setCommittedWhere(processOffset); this.mapedFileQueue.truncateDirtyFiles(processOffset); // 清除ConsumeQueue的多余数据 this.defaultMessageStore.truncateDirtyLogicFiles(processOffset); } // 物理文件都被删除情况下 else { this.mapedFileQueue.setCommittedWhere(0); this.defaultMessageStore.destroyLogics(); } }
@Test public void test_findMapedFileByOffset() { final String fixedMsg = "abcd"; System.out.println("================================================================"); AllocateMapedFileService allocateMapedFileService = new AllocateMapedFileService(); allocateMapedFileService.start(); MapedFileQueue mapedFileQueue = new MapedFileQueue("./unit_test_store/b/", 1024, allocateMapedFileService); for (int i = 0; i < 1024; i++) { MapedFile mapedFile = mapedFileQueue.getLastMapedFile(); assertTrue(mapedFile != null); boolean result = mapedFile.appendMessage(fixedMsg.getBytes()); // System.out.println("appendMessage " + bytes); assertTrue(result); } MapedFile mapedFile = mapedFileQueue.findMapedFileByOffset(0); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 0); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(100); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 0); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(1024); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 1024); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(1024 + 100); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 1024); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(1024 * 2); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 1024 * 2); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(1024 * 2 + 100); assertTrue(mapedFile != null); assertEquals(mapedFile.getFileFromOffset(), 1024 * 2); System.out.println(mapedFile.getFileFromOffset()); mapedFile = mapedFileQueue.findMapedFileByOffset(1024 * 4); assertTrue(mapedFile == null); mapedFile = mapedFileQueue.findMapedFileByOffset(1024 * 4 + 100); assertTrue(mapedFile == null); mapedFileQueue.shutdown(1000); mapedFileQueue.destroy(); allocateMapedFileService.shutdown(); System.out.println("MapedFileQueue.findMapedFileByOffset() OK"); }