/** * readNextEntry will stop at a bad entry. * * @return true if an element has been read. */ public boolean readNextEntry() throws DatabaseException, IOException { boolean foundEntry = false; try { /* * At this point, * currentEntryOffset is the entry we just read. * nextEntryOffset is the entry we're about to read. * currentEntryPrevOffset is 2 entries ago. * Note that readNextEntry() moves all the offset pointers up. */ foundEntry = super.readNextEntry(); /* * Note that initStartingPosition() makes sure that the file header * entry is valid. So by the time we get to this method, we know * we're at a file with a valid file header entry. */ lastValidOffset = currentEntryOffset; nextUnprovenOffset = nextEntryOffset; } catch (DbChecksumException e) { Tracer.trace( Level.INFO, envImpl, "Found checksum exception while searching " + " for end of log. Last valid entry is at " + DbLsn.toString(DbLsn.makeLsn(readBufferFileNum, lastValidOffset)) + " Bad entry is at " + DbLsn.makeLsn(readBufferFileNum, nextUnprovenOffset)); } return foundEntry; }
/* * Reposition to the specified file, and fill starting at * startOffset. Position the window's buffer to point at the log entry * indicated by targetOffset */ public void slideAndFill( long windowfileNum, long windowStartOffset, long targetOffset, boolean forward) throws ChecksumException, FileNotFoundException, DatabaseException { FileHandle fileHandle = fileManager.getFileHandle(windowfileNum); try { startOffset = windowStartOffset; setFileNum(windowfileNum, fileHandle.getLogVersion()); boolean foundData = fillFromFile(fileHandle, targetOffset); /* * When reading backwards, we need to guarantee there is no log * gap, throws out an EnvironmentFailreException if it exists. */ if (!foundData && !forward) { throw EnvironmentFailureException.unexpectedState( "Detected a log file gap when reading backwards. " + "Target position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, targetOffset)) + " starting position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, windowStartOffset)) + " end position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, endOffset))); } } finally { fileHandle.release(); } }
@Override public String toString() { StringBuilder sb = new StringBuilder(); long start = DbLsn.makeLsn(fileNum, startOffset); long end = DbLsn.makeLsn(fileNum, endOffset); sb.append("window covers "); sb.append(DbLsn.getNoFormatString(start)).append(" to "); sb.append(DbLsn.getNoFormatString(end)); sb.append(" positioned at "); long target = DbLsn.makeLsn(fileNum, startOffset + readBuffer.position()); sb.append(DbLsn.getNoFormatString(target)); return sb.toString(); }
/** Read in an IN entry. */ public void readEntry(EnvironmentImpl envImpl, LogEntryHeader header, ByteBuffer entryBuffer) { int logVersion = header.getVersion(); boolean version6OrLater = (logVersion >= 6); if (version6OrLater) { dbId = new DatabaseId(); dbId.readFromLog(entryBuffer, logVersion); prevFullLsn = LogUtils.readLong(entryBuffer, false /*unpacked*/); if (logVersion >= 8) { prevDeltaLsn = LogUtils.readPackedLong(entryBuffer); } } /* Read IN. */ in = newInstanceOfType(); in.readFromLog(entryBuffer, logVersion); if (!version6OrLater) { dbId = new DatabaseId(); dbId.readFromLog(entryBuffer, logVersion); } if (logVersion < 1) { prevFullLsn = DbLsn.NULL_LSN; } else if (logVersion == 1) { long fileNum = LogUtils.readUnsignedInt(entryBuffer); if (fileNum == 0xffffffffL) { prevFullLsn = DbLsn.NULL_LSN; } else { prevFullLsn = DbLsn.makeLsn(fileNum, 0); } } else if (!version6OrLater) { prevFullLsn = LogUtils.readLong(entryBuffer, true /*unpacked*/); } }
/** @return The last LSN seen in the log for this kind of entry, or null. */ public long getLastSeen(LogEntryType type) { Long typeNumber = (Long) lastOffsetSeen.get(type); if (typeNumber != null) { return DbLsn.makeLsn(readBufferFileNum, typeNumber.longValue()); } else { return DbLsn.NULL_LSN; } }
/** @return The last LSN seen in the log for this kind of entry, or null. */ public long getLastSeen(LogEntryType type) { Long typeNumber = lastOffsetSeen.get(type); if (typeNumber != null) { return DbLsn.makeLsn(window.currentFileNum(), typeNumber.longValue()); } else { return DbLsn.NULL_LSN; } }
/** Test initializing the last position in the logs. */ public void testSetLastPosition() throws DatabaseException { /* * Pretend that the last file is file 79. */ fileManager.setLastPosition( // next available LSN DbLsn.makeLsn(79L, 88L), DbLsn.makeLsn(79L, 77), 66L); /* Put an entry down, should fit within file 79. */ fileManager.bumpLsn(11L); assertEquals(DbLsn.makeLsn(79L, 88L), fileManager.getLastUsedLsn()); assertEquals(77L, fileManager.getPrevEntryOffset()); /* Put another entry in, should go to the next file. */ fileManager.bumpLsn(22L); assertEquals( DbLsn.makeLsn(80L, FileManager.firstLogEntryOffset()), fileManager.getLastUsedLsn()); assertEquals(0, fileManager.getPrevEntryOffset()); }
/** * Ensure that the next target is in the window. The default behavior is that the next target is * the next, following entry, so we can assume that it's in the window. All we have to do is to * check if we've gone past the specified end point. * * @throws DatabaseException * @throws FileNotFoundException * @throws ChecksumException */ protected void setForwardPosition() throws EOFException, DatabaseException, ChecksumException, FileNotFoundException { if (finishLsn != DbLsn.NULL_LSN) { /* The next log entry has passed the end LSN. */ long nextLsn = DbLsn.makeLsn(window.currentFileNum(), nextEntryOffset); if (DbLsn.compareTo(nextLsn, finishLsn) >= 0) { throw new EOFException(); } } }
/** * readNextEntry will stop at a bad entry. * * @return true if an element has been read. */ @Override public boolean readNextEntry() { boolean foundEntry = false; try { /* * At this point, * currentEntryOffset is the entry we just read. * nextEntryOffset is the entry we're about to read. * currentEntryPrevOffset is 2 entries ago. * Note that readNextEntry() moves all the offset pointers up. */ foundEntry = super.readNextEntryAllowExceptions(); /* * Note that initStartingPosition() makes sure that the file header * entry is valid. So by the time we get to this method, we know * we're at a file with a valid file header entry. */ lastValidOffset = currentEntryOffset; nextUnprovenOffset = nextEntryOffset; } catch (FileNotFoundException e) { throw new EnvironmentFailureException( envImpl, EnvironmentFailureReason.LOG_FILE_NOT_FOUND, e); } catch (ChecksumException e) { LoggerUtils.fine( logger, envImpl, "Found checksum exception while searching for end of log. " + "Last valid entry is at " + DbLsn.toString(DbLsn.makeLsn(window.currentFileNum(), lastValidOffset)) + " Bad entry is at " + DbLsn.makeLsn(window.currentFileNum(), nextUnprovenOffset)); } return foundEntry; }
/* * Read the next entry. If a checksum exception is encountered, attempt * to find the other side of the corrupted area and try to re-read this * file. */ @Override public boolean readNextEntry() { long saveCurrentEntryOffset = currentEntryOffset; try { return super.readNextEntryAllowExceptions(); } catch (FileNotFoundException e) { throw new EnvironmentFailureException( envImpl, EnvironmentFailureReason.LOG_FILE_NOT_FOUND, e); } catch (ChecksumException e) { resyncReader( DbLsn.makeLsn(window.currentFileNum(), saveCurrentEntryOffset), dumpCorruptedBounds); return super.readNextEntry(); } }
/** Helper for determining the starting position and opening up a file at the desired location. */ protected void initStartingPosition(long endOfFileLsn, Long ignoreSingleFileNumber) { eof = false; if (forward) { /* * Start off at the startLsn. If that's null, start at the * beginning of the log. If there are no log files, set eof. */ if (startLsn != DbLsn.NULL_LSN) { window.initAtFileStart(startLsn); } else { Long firstNum = fileManager.getFirstFileNum(); if (firstNum == null) { eof = true; } else { window.initAtFileStart(DbLsn.makeLsn(firstNum, 0)); } } /* * After we read the first entry, the currentEntry will point here. */ nextEntryOffset = window.getEndOffset(); } else { /* * Make the read buffer look like it's positioned off the end of * the file. Initialize the first LSN we want to read. When * traversing the log backwards, we always start at the very end. */ assert startLsn != DbLsn.NULL_LSN; window.initAtFileStart(endOfFileLsn); /* * currentEntryPrevOffset points to the entry we want to start out * reading when going backwards. If it's 0, the entry we want to * read is in a different file. */ if (DbLsn.getFileNumber(startLsn) == DbLsn.getFileNumber(endOfFileLsn)) { currentEntryPrevOffset = DbLsn.getFileOffset(startLsn); } else { currentEntryPrevOffset = 0; } currentEntryOffset = DbLsn.getFileOffset(endOfFileLsn); } }
/** Initialize starting position to the last file with a complete header with a valid checksum. */ private void startAtLastGoodFile(Long singleFileNum) throws ChecksumException { eof = false; window.initAtFileStart(DbLsn.makeLsn(0, 0)); /* * Start at what seems like the last file. If it doesn't exist, we're * done. */ Long lastNum = ((singleFileNum != null) && (singleFileNum.longValue() >= 0)) ? singleFileNum : fileManager.getLastFileNum(); FileHandle fileHandle = null; long fileLen = 0; while ((fileHandle == null) && !eof) { if (lastNum == null) { eof = true; } else { try { try { window.initAtFileStart(DbLsn.makeLsn(lastNum, 0)); fileHandle = fileManager.getFileHandle(lastNum); /* * Check the size of this file. If it opened * successfully but only held a header or is 0 length, * backup to the next "last" file unless this is the * only file in the log. Note that an incomplete header * will end up throwing a checksum exception, but a 0 * length file will open successfully in read only * mode. */ fileLen = fileHandle.getFile().length(); if (fileLen <= FileManager.firstLogEntryOffset()) { lastNum = fileManager.getFollowingFileNum(lastNum, false); if (lastNum != null) { fileHandle.release(); fileHandle = null; } } } catch (DatabaseException e) { lastNum = attemptToMoveBadFile(e); fileHandle = null; } catch (ChecksumException e) { lastNum = attemptToMoveBadFile(e); fileHandle = null; } finally { if (fileHandle != null) { fileHandle.release(); } } } catch (IOException e) { throw new EnvironmentFailureException(envImpl, EnvironmentFailureReason.LOG_READ, e); } } } nextEntryOffset = 0; }
public long getLastValidLsn() { return DbLsn.makeLsn(readBufferFileNum, lastValidOffset); }
/** Get LSN of the last entry read. */ public long getLastLsn() { return DbLsn.makeLsn(window.currentFileNum(), currentEntryOffset); }
/** Test LSN administration. */ public void testLsnBumping() throws Exception { /* We are adding these entries: +----+------+---------+--------+ file 0: |hdr | 30 | 50 |empty | +----+------+---------+--------+ 0 hdr hdr+30 hdr+80 99 +----+--------+-------+-------+-----+-------+ file 1: |hdr | 40 | 20 | 10 | 5 | empty | +----+--------+-------+-------+-----+-------+ 0 hdr hdr+40 hdr+60 hdr+70 hdr+75 +-----+-----+--------+ file 2: | hdr | 75 | empty | +-----+-----+--------+ 0 hdr hdr+75 +-----+-------------------------------+ file 3: | hdr | 125 | +-----+-------------------------------+ 0 hdr +-----+-----+------+-----+--------------+ file 4: | hdr | 10 | 20 | 30 | empty +-----+-----+------+-----+--------------+ 0 hdr hdr+10 hdr+30 */ try { /* Should start out at LSN 0. */ /* "add" some entries to the log. */ long hdrSize = FileManager.firstLogEntryOffset(); fileManager.bumpLsn(30L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(0, hdrSize), fileManager.getLastUsedLsn()); /* prev entry. */ assertEquals(0, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(50L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(0, (hdrSize + 30)), fileManager.getLastUsedLsn()); assertEquals(hdrSize, fileManager.getPrevEntryOffset()); /* bump over to a file 1. */ fileManager.bumpLsn(40L); /* item placed here. */ assertEquals(DbLsn.makeLsn(1, hdrSize), fileManager.getLastUsedLsn()); assertEquals(0, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(20L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(1, (hdrSize + 40)), fileManager.getLastUsedLsn()); assertEquals(hdrSize, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(10L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(1, (hdrSize + 60)), fileManager.getLastUsedLsn()); assertEquals(hdrSize + 40, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(5L); /* item placed here. */ assertEquals(DbLsn.makeLsn(1, (hdrSize + 70)), fileManager.getLastUsedLsn()); assertEquals(hdrSize + 60, fileManager.getPrevEntryOffset()); /* bump over to file 2. */ fileManager.bumpLsn(75L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(2, hdrSize), fileManager.getLastUsedLsn()); assertEquals(0, fileManager.getPrevEntryOffset()); /* Ask for something bigger than a file: bump over to file 3. */ fileManager.bumpLsn(125L); /* item placed here. */ assertEquals(DbLsn.makeLsn(3, hdrSize), fileManager.getLastUsedLsn()); assertEquals(0, fileManager.getPrevEntryOffset()); /* bump over to file 4. */ fileManager.bumpLsn(10L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(4, hdrSize), fileManager.getLastUsedLsn()); assertEquals(0, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(20L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(4, (hdrSize + 10)), fileManager.getLastUsedLsn()); assertEquals(hdrSize, fileManager.getPrevEntryOffset()); fileManager.bumpLsn(30L); /* Item placed here. */ assertEquals(DbLsn.makeLsn(4, (hdrSize + 30)), fileManager.getLastUsedLsn()); assertEquals((hdrSize + 10), fileManager.getPrevEntryOffset()); } catch (Exception e) { e.printStackTrace(); throw e; } }
/** @return The LSN to be used for the next log entry. */ public long getEndOfLog() { return DbLsn.makeLsn(window.currentFileNum(), nextUnprovenOffset); }
public long getLastValidLsn() { return DbLsn.makeLsn(window.currentFileNum(), lastValidOffset); }
/** * Ensure that the next target is in the window. The default behavior is that the next target is * the next previous entry. * * @throws DatabaseException */ protected void setBackwardPosition() throws ChecksumException, FileNotFoundException, EOFException, DatabaseException { /* * currentEntryPrevOffset is the entry before the current entry. * currentEntryOffset is the entry we just read (or the end of the * file if we're starting out. */ if ((currentEntryPrevOffset != 0) && window.containsOffset(currentEntryPrevOffset)) { /* The next log entry has passed the start LSN. */ long nextLsn = DbLsn.makeLsn(window.currentFileNum(), currentEntryPrevOffset); if (finishLsn != DbLsn.NULL_LSN) { if (DbLsn.compareTo(nextLsn, finishLsn) == -1) { throw new EOFException( "finish=" + DbLsn.getNoFormatString(finishLsn) + "next=" + DbLsn.getNoFormatString(nextLsn)); } } /* This log entry starts in this buffer, just reposition. */ window.positionBuffer(currentEntryPrevOffset); } else { /* * The start of the log entry is not in this read buffer so * we must fill the buffer again. * * 1) The target log entry is in a different file from the * current window's file. Move the window to the previous * file and start the read from the target LSN. * * 2) The target log entry is the same file but the log entry * is larger than the read chunk size. Start the next read * buffer from the target LSN. It's going to take multiple * reads to get the log entry, and we might as well get as * much as possible. * * 3) In the same file, and the log entry fits within one * read buffer. Try to position the next buffer chunk so the * target entry is held within the buffer, all the way at the * end. That way, since we're reading backwards, there will be * more buffered data available for following reads. */ long nextFile; long nextWindowStart; long nextTarget; if (currentEntryPrevOffset == 0) { /* Case 1: Go to another file. */ currentEntryPrevOffset = fileManager.getFileHeaderPrevOffset(window.currentFileNum()); Long prevFileNum = fileManager.getFollowingFileNum(window.currentFileNum(), false); if (prevFileNum == null) { throw new EOFException("No file following " + window.currentFileNum()); } /* * Check finishLSN before proceeding, in case we should stop * the search before attempting to set the file reader to a * position in the previous file. In [#22407] we threw a * spurious EFE complaining that we cannot read backwards over * a cleaned file because the previous file had been cleaned * away. */ if (finishLsn != DbLsn.NULL_LSN && prevFileNum < DbLsn.getFileNumber(finishLsn)) { throw new EOFException( "finish=" + DbLsn.getNoFormatString(finishLsn) + " nextFile=0x" + Long.toHexString(prevFileNum)); } if (window.currentFileNum() - prevFileNum.longValue() != 1) { handleGapInBackwardsScan(prevFileNum); } nextFile = prevFileNum; nextWindowStart = currentEntryPrevOffset; nextTarget = currentEntryPrevOffset; } else if ((currentEntryOffset - currentEntryPrevOffset) > window.capacity()) { /* * Case 2: The entry is in the same file, but is bigger * than one buffer. Position it at the front of the buffer. */ nextFile = window.currentFileNum(); nextWindowStart = currentEntryPrevOffset; nextTarget = currentEntryPrevOffset; } else { /* * Case 3: In same file, but not in this buffer. The target * entry will fit in one buffer. */ nextFile = window.currentFileNum(); long newPosition = currentEntryOffset - window.capacity(); nextWindowStart = (newPosition < 0) ? 0 : newPosition; nextTarget = currentEntryPrevOffset; } /* The next log entry has passed the start LSN. */ long nextLsn = DbLsn.makeLsn(nextFile, currentEntryPrevOffset); if (finishLsn != DbLsn.NULL_LSN) { if (DbLsn.compareTo(nextLsn, finishLsn) == -1) { throw new EOFException( "finish=" + DbLsn.getNoFormatString(finishLsn) + " next=" + DbLsn.getNoFormatString(nextLsn)); } } window.slideAndFill(nextFile, nextWindowStart, nextTarget, forward); } /* The current entry will start at this offset. */ currentEntryOffset = currentEntryPrevOffset; }
/** @return The LSN to be used for the next log entry. */ public long getEndOfLog() { return DbLsn.makeLsn(readBufferFileNum, nextUnprovenOffset); }
public void testEntryData() throws Throwable { try { ByteBuffer buffer = ByteBuffer.allocate(1000); database = new DatabaseImpl("foo", new DatabaseId(1), env, new DatabaseConfig()); /* * For each loggable object, can we write the entry data out? */ /* * Tracer records. */ Tracer dMsg = new Tracer("Hello there"); writeAndRead(buffer, LogEntryType.LOG_TRACE, dMsg, new Tracer()); /* * LNs */ String data = "abcdef"; LN ln = new LN(data.getBytes()); LN lnFromLog = new LN(); writeAndRead(buffer, LogEntryType.LOG_LN, ln, lnFromLog); lnFromLog.verify(null); assertTrue(LogEntryType.LOG_LN.marshallOutsideLatch()); FileSummaryLN fsLN = new FileSummaryLN(new FileSummary()); FileSummaryLN fsLNFromLog = new FileSummaryLN(); writeAndRead(buffer, LogEntryType.LOG_FILESUMMARYLN, fsLN, fsLNFromLog); assertFalse(LogEntryType.LOG_FILESUMMARYLN.marshallOutsideLatch()); /* * INs */ IN in = new IN(database, new byte[] {1, 0, 1, 0}, 7, 5); in.latch(); in.insertEntry(new ChildReference(null, new byte[] {1, 0, 1, 0}, DbLsn.makeLsn(12, 200))); in.insertEntry(new ChildReference(null, new byte[] {1, 1, 1, 0}, DbLsn.makeLsn(29, 300))); in.insertEntry(new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(35, 400))); /* Write it. */ IN inFromLog = new IN(); inFromLog.latch(); writeAndRead(buffer, LogEntryType.LOG_IN, in, inFromLog); inFromLog.releaseLatch(); in.releaseLatch(); /* * IN - long form */ in = new IN(database, new byte[] {1, 0, 1, 0}, 7, 5); in.latch(); in.insertEntry(new ChildReference(null, new byte[] {1, 0, 1, 0}, DbLsn.makeLsn(12, 200))); in.insertEntry(new ChildReference(null, new byte[] {1, 1, 1, 0}, DbLsn.makeLsn(29, 300))); in.insertEntry(new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(1235, 400))); in.insertEntry( new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(0xFFFFFFF0L, 400))); /* Write it. */ inFromLog = new IN(); inFromLog.latch(); writeAndRead(buffer, LogEntryType.LOG_IN, in, inFromLog); inFromLog.releaseLatch(); in.releaseLatch(); /* * BINs */ BIN bin = new BIN(database, new byte[] {3, 2, 1}, 8, 5); bin.latch(); bin.insertEntry(new ChildReference(null, new byte[] {1, 0, 1, 0}, DbLsn.makeLsn(212, 200))); bin.insertEntry(new ChildReference(null, new byte[] {1, 1, 1, 0}, DbLsn.makeLsn(229, 300))); bin.insertEntry(new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(235, 400))); BIN binFromLog = new BIN(); binFromLog.latch(); writeAndRead(buffer, LogEntryType.LOG_BIN, bin, binFromLog); binFromLog.verify(null); binFromLog.releaseLatch(); bin.releaseLatch(); /* * DINs */ DIN din = new DIN( database, new byte[] {1, 0, 0, 1}, 7, new byte[] {0, 1, 1, 0}, new ChildReference(null, new byte[] {1, 0, 0, 1}, DbLsn.makeLsn(10, 100)), 5); din.latch(); din.insertEntry(new ChildReference(null, new byte[] {1, 0, 1, 0}, DbLsn.makeLsn(12, 200))); din.insertEntry(new ChildReference(null, new byte[] {1, 1, 1, 0}, DbLsn.makeLsn(29, 300))); din.insertEntry(new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(35, 400))); /* Write it. */ DIN dinFromLog = new DIN(); dinFromLog.latch(); writeAndRead(buffer, LogEntryType.LOG_DIN, din, dinFromLog); din.releaseLatch(); dinFromLog.releaseLatch(); /* * DBINs */ DBIN dbin = new DBIN(database, new byte[] {3, 2, 1}, 8, new byte[] {1, 2, 3}, 5); dbin.latch(); dbin.insertEntry(new ChildReference(null, new byte[] {1, 0, 1, 0}, DbLsn.makeLsn(212, 200))); dbin.insertEntry(new ChildReference(null, new byte[] {1, 1, 1, 0}, DbLsn.makeLsn(229, 300))); dbin.insertEntry(new ChildReference(null, new byte[] {0, 0, 1, 0}, DbLsn.makeLsn(235, 400))); DBIN dbinFromLog = new DBIN(); dbinFromLog.latch(); writeAndRead(buffer, LogEntryType.LOG_DBIN, dbin, dbinFromLog); dbinFromLog.verify(null); dbin.releaseLatch(); dbinFromLog.releaseLatch(); /* * Root */ DbTree dbTree = new DbTree(env); DbTree dbTreeFromLog = new DbTree(); writeAndRead(buffer, LogEntryType.LOG_ROOT, dbTree, dbTreeFromLog); /* * MapLN */ MapLN mapLn = new MapLN(database); MapLN mapLnFromLog = new MapLN(); writeAndRead(buffer, LogEntryType.LOG_MAPLN, mapLn, mapLnFromLog); /* * UserTxn */ /* * Disabled for now because these txns don't compare equal, * because one has a name of "main" and the other has a name of * null because it was read from the log. Txn txn = new Txn(env, new TransactionConfig()); Txn txnFromLog = new Txn(); writeAndRead(buffer, LogEntryType.TXN_COMMIT, txn, txnFromLog); txn.commit(); */ /* * TxnCommit */ TxnCommit commit = new TxnCommit(111, DbLsn.makeLsn(10, 10)); TxnCommit commitFromLog = new TxnCommit(); writeAndRead(buffer, LogEntryType.LOG_TXN_COMMIT, commit, commitFromLog); /* * TxnAbort */ TxnAbort abort = new TxnAbort(111, DbLsn.makeLsn(11, 11)); TxnAbort abortFromLog = new TxnAbort(); writeAndRead(buffer, LogEntryType.LOG_TXN_ABORT, abort, abortFromLog); /* * TxnPrepare */ byte[] gid = new byte[64]; byte[] bqual = new byte[64]; TxnPrepare prepare = new TxnPrepare(111, new LogUtils.XidImpl(1, gid, bqual)); TxnPrepare prepareFromLog = new TxnPrepare(); writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare, prepareFromLog); prepare = new TxnPrepare(111, new LogUtils.XidImpl(1, null, bqual)); prepareFromLog = new TxnPrepare(); writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare, prepareFromLog); prepare = new TxnPrepare(111, new LogUtils.XidImpl(1, gid, null)); prepareFromLog = new TxnPrepare(); writeAndRead(buffer, LogEntryType.LOG_TXN_PREPARE, prepare, prepareFromLog); /* * IN delete info */ INDeleteInfo info = new INDeleteInfo(77, new byte[1], new DatabaseId(100)); INDeleteInfo infoFromLog = new INDeleteInfo(); writeAndRead(buffer, LogEntryType.LOG_IN_DELETE_INFO, info, infoFromLog); /* * Checkpoint start */ CheckpointStart start = new CheckpointStart(177, "test"); CheckpointStart startFromLog = new CheckpointStart(); writeAndRead(buffer, LogEntryType.LOG_CKPT_START, start, startFromLog); /* * Checkpoint end */ CheckpointEnd end = new CheckpointEnd( "test", DbLsn.makeLsn(20, 55), env.getRootLsn(), env.getTxnManager().getFirstActiveLsn(), Node.getLastId(), env.getDbMapTree().getLastDbId(), env.getTxnManager().getLastTxnId(), 177); CheckpointEnd endFromLog = new CheckpointEnd(); writeAndRead(buffer, LogEntryType.LOG_CKPT_END, end, endFromLog); } catch (Throwable t) { t.printStackTrace(); throw t; } }