/** * 新添加一条记录 * * @return 返回记录ID */ public StoreTxLogPosition append(byte[] entry) throws IOException { int length = entry.length; if (length > storeConfig.getMaxxLogEntryLength()) { throw new DBException("Value size can not great than " + storeConfig.getMaxxLogEntryLength()); } // 检查当前文件容量是否足够 if (fileLength + length + ENTRY_HEAD_LENGTH > storeConfig.getTxLogFileSize()) { throw new CapacityNotEnoughException(); } StoreTxLogPosition result = new StoreTxLogPosition(); result.setRecordId(getNextRecordId()); boolean ok = false; try { entryBuffer.clear(); entryBuffer.put(magic); // 1 byte entryBuffer.putInt(length); // 4 byte entryBuffer.put(entry); // entry.length entryBuffer.flip(); fileChannel.position(fileLength); fileChannel.write(entryBuffer); int entryLength = (ENTRY_HEAD_LENGTH + length); fileLength += entryLength; ok = true; } finally { if (ok) { if (syncTimerTask == null || syncTimerTask.isDone()) { syncTimerTask = new FutureTimerTask("ltsdb-dblog-sync-timertask", syncCallable); syncTimer.schedule(syncTimerTask, storeConfig.getDbLogFlushInterval()); } } } return result; }
public StoreTxLog( StoreConfig storeConfig, File file, boolean readonly, boolean isNewFile, long firstRecordId) throws IOException { this.storeConfig = storeConfig; this.entryBuffer = ByteBuffer.allocate(storeConfig.getMaxxLogEntryLength() + 1 + 4); this.fileHeader = new StoreTxLogFileHeader(); if (!readonly) { syncTimer = new Timer("ltsdb-dblog-sync-timer", true); syncCallable = new FutureTimerTask.Callable() { @Override public void call() throws Exception { checkPoint(); } }; } if (isNewFile && file.exists()) { throw new IOException(file + " exists already"); } else { FileUtils.createFileIfNotExist(file); } fileChannel = FileUtils.newFileChannel(file, "rw"); if (isNewFile) { // 新文件长度为头部长度 fileLength = fileHeader.getLength(); fileHeader.setFirstRecordId(firstRecordId); fileHeader.write(fileChannel); } else { fileHeader.read(fileChannel); fileLength = fileChannel.size(); lastCheckPointLength = fileLength; } }