예제 #1
0
  /**
   * 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;
  }
예제 #2
0
  /**
   * Returns whether a given obsolete LSN has already been counted in the utilization profile. If
   * true is returned, it should not be counted again, to prevent double-counting.
   */
  private boolean isObsoleteLsnAlreadyCounted(long oldLsn, long newLsn) {

    /* If the file summary follows the new LSN, it was already counted. */
    Long fileNum = new Long(DbLsn.getFileNumber(oldLsn));
    long fileSummaryLsn = DbLsn.longToLsn((Long) fileSummaryLsns.get(fileNum));
    int cmpFsLsnToNewLsn =
        (fileSummaryLsn != DbLsn.NULL_LSN) ? DbLsn.compareTo(fileSummaryLsn, newLsn) : -1;
    return (cmpFsLsnToNewLsn >= 0);
  }
예제 #3
0
  /*
   * A checksum error has been encountered.  Go to the start of this log file
   * and read forward until the lower side of the corrupted area has been
   * found.
   */
  @Override
  protected boolean resyncReader(long nextGoodRecordPostCorruption, boolean showCorruptedBounds)
      throws DatabaseException {

    LastFileReader reader = null;
    long tryReadBufferFileNum = DbLsn.getFileNumber(nextGoodRecordPostCorruption);

    while (tryReadBufferFileNum >= 0) {
      try {
        reader = new LastFileReader(envImpl, readBufferSize, Long.valueOf(tryReadBufferFileNum));
        break;
      } catch (ChecksumException e) {

        /*
         * We encountered a problem opening this file so skip to an
         * earlier file.
         */
        tryReadBufferFileNum--;
        continue;
      }
    }

    boolean switchedFiles =
        tryReadBufferFileNum != DbLsn.getFileNumber(nextGoodRecordPostCorruption);

    if (!switchedFiles) {

      /*
       * Read forward until a checksum fails.  This reader will not throw
       * an exception if a checksum error is hit -- it will just return
       * false.
       */
      while (reader.readNextEntry()) {}
    }

    long lastUsedLsn = reader.getLastValidLsn();
    long nextAvailableLsn = reader.getEndOfLog();
    if (showCorruptedBounds) {
      System.err.println("A checksum error was found in the log.");
      System.err.println("Corruption begins at LSN:\n   " + DbLsn.toString(nextAvailableLsn));
      System.err.println(
          "Last known good record before corruption is at LSN:\n   " + DbLsn.toString(lastUsedLsn));
      System.err.println(
          "Next known good record after corruption is at LSN:\n   "
              + DbLsn.toString(nextGoodRecordPostCorruption));
    }

    startLsn = lastUsedLsn;
    initStartingPosition(nextAvailableLsn, null);
    if (switchedFiles) {
      currentEntryPrevOffset = 0;
    }
    /* Indicate resync is permitted so don't throw exception. */
    return true;
  }
  /**
   * 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();
      }
    }
  }
예제 #5
0
  /** 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*/);
    }
  }
    /* Position the readBuffer to the targetOffset. */
    public void positionBuffer(long targetOffset) {

      assert containsOffset(targetOffset)
          : this + " doesn't contain " + DbLsn.getNoFormatString(targetOffset);

      threadSafeBufferPosition(readBuffer, (int) (targetOffset - startOffset));
    }
예제 #7
0
파일: ReplayTxn.java 프로젝트: geniot/elex
  /**
   * Rollback all write operations that are logged with an LSN > the matchpointLsn parameter. This
   * is logically a truncation of the log entries written by this transaction. Any log entries
   * created by this transaction are marked obsolete.
   *
   * <p>Note that this is by no means a complete implementation of what would be needed to support
   * user visible savepoints. This method only rolls back write operations and doesn't handle other
   * types of state, like read locks and open cursors.
   *
   * <p>There are several key assumptions: - the transaction does not hold read locks. - the
   * transaction will either be resumed, and any rolled back operations will be repeated, or the
   * transaction will be aborted in its entirety.
   *
   * <p>If all operations in the transaction are rolled back, this transaction is also unregistered
   * and closed.
   *
   * <p>Rolling back a log entry through rollback is akin to truncating the transactional log. The
   * on-disk entries should not be referred to by anything in the in-memory tree or the transaction
   * chain. JE's append only storage and the fact that the transactional log entries are intertwined
   * through the physical log prohibits any log truncation. To mimic log truncation, any rolled back
   * log entry is marked as obsolete. Since only the last version of any data record is alive, any
   * future uses of this transaction must use the obsoleteDupsAllowed option (see
   * Txn.countObsoleteExact) to prevent asserts about duplicate obsolete offsets. For example,
   * suppose the transaction logs this:
   *
   * <p>100 LNa (version1) 200 LNa (version2) 300 LNa (version3)
   *
   * <p>At this point in time, LSN 100 and 200 are obsolete.
   *
   * <p>Now, suppose we roll back to LSN 100. LSNs 200 and 300 are marked obsolete by the
   * rollback.(although LSN 200 was already obsolete). It is true that for an instance in time LSN
   * 100 is incorrectly marked as obsolete, when it's really alive. But this transaction is going to
   * either abort or resume exactly as it was before, so LSN 100 is going to be obsolete again.
   *
   * <p>Suppose txn.abort() is called. The abort() logic will mark LSN 100 as obsolete, since it is
   * the latest version of the record in the transaction. Using the obsoleteDupsAllowed option
   * avoids an assertion on the double recording of LSN 100.
   *
   * <p>Alternatively, suppose LNa (version2) is retransmitted and logged as LSN 400. Normal
   * execution of LN.log() marks LSN 100 as obsolete, which would trigger the assertion were it not
   * for obsoleteDupsAllowed.
   *
   * @return list of LSNs that were rolled back
   */
  public Collection<Long> rollback(long matchpointLsn) throws DatabaseException {

    List<Long> rollbackLsns = new ArrayList<Long>();
    LoggerUtils.finest(logger, envImpl, "Partial Rollback of " + this);
    synchronized (this) {
      checkState(true);

      /* This transaction didn't log anything, nothing to rollback. */
      if (lastLoggedLsn == NULL_LSN) {
        return rollbackLsns;
      }

      /*
       * This transaction doesn't include any operations that are after
       * the matchpointLsn. There is nothing to rollback.
       */
      if (DbLsn.compareTo(lastLoggedLsn, matchpointLsn) <= 0) {
        return rollbackLsns;
      }

      setRollback();
      undoWrites(matchpointLsn, rollbackLsns);
    }

    /*
     * The call to undoWrites() may have rolled everything back, and set
     * lastLoggedLsn to NULL_LSN.
     */
    if (lastLoggedLsn == NULL_LSN) {
      /* Everything was rolled back. */
      try {

        /*
         * Purge any databaseImpls not needed as a result of the abort.
         * Be sure to do this outside the synchronization block, to
         * avoid conflict w/checkpointer.
         */
        cleanupDatabaseImpls(false);
      } finally {
        close(false /* isCommit */);
      }
    }

    /*
     * We don't expect there to be any database handles associated with
     * a ReplayTxn, because only DatabaseImpls are used. Because of that,
     * there should be no cleanup needed.
     */
    if (handleToHandleLockMap != null) {
      throw EnvironmentFailureException.unexpectedState(
          "Replay Txn " + getId() + " has a handleToHandleLockMap");
    }

    /*
     * There is no need to call cleanupDatabaseImpls if the txn still holds
     * locks. The operations in this txn will either be entirely aborted,
     * or will be repeated, so any cleanup will happen when the txn ends.
     */
    return rollbackLsns;
  }
예제 #8
0
 /** Print out the contents of an entry. */
 @Override
 public StringBuilder dumpEntry(StringBuilder sb, boolean verbose) {
   in.dumpLog(sb, verbose);
   dbId.dumpLog(sb, verbose);
   if (prevFullLsn != DbLsn.NULL_LSN) {
     sb.append("<prevFullLsn>");
     sb.append(DbLsn.getNoFormatString(prevFullLsn));
     sb.append("</prevFullLsn>");
   }
   if (prevDeltaLsn != DbLsn.NULL_LSN) {
     sb.append("<prevDeltaLsn>");
     sb.append(DbLsn.getNoFormatString(prevDeltaLsn));
     sb.append("</prevDeltaLsn>");
   }
   return sb;
 }
  /** 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);
    }
  }
예제 #10
0
 /** @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;
   }
 }
예제 #11
0
파일: ReplayTxn.java 프로젝트: geniot/elex
 /* Wrap the call to logger to reduce runtime overhead. */
 private void logFinest(long lsn, UndoReader undo, RevertInfo revertTo) {
   if ((logger != null) && (logger.isLoggable(Level.FINEST))) {
     LoggerUtils.finest(
         logger,
         envImpl,
         "undoLsn=" + DbLsn.getNoFormatString(lsn) + " undo=" + undo + " revertInfo=" + revertTo);
   }
 }
예제 #12
0
 /** @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;
   }
 }
예제 #13
0
  /** 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());
  }
  /** Force a rewrite of the map tree root if required. */
  public void rewriteMapTreeRoot(long cleanerTargetLsn) throws DatabaseException {

    if (DbLsn.compareTo(cleanerTargetLsn, mapTreeRootLsn) == 0) {

      /*
       * The root entry targetted for cleaning is in use. Write a new
       * copy.
       */
      mapTreeRootLsn = logManager.log(dbMapTree);
    }
  }
    /*
     * 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();
      }
    }
예제 #16
0
  /**
   * 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;
  }
예제 #17
0
  void setPosition(long startLsn)
      throws ChecksumException, FileNotFoundException, DatabaseException {

    if (startLsn == DbLsn.NULL_LSN) {
      return;
    }

    /*
     * An assertion: a reposition should never make the reader lose ground.
     */
    if (forward) {
      if (DbLsn.compareTo(getLastLsn(), startLsn) > 0) {
        throw EnvironmentFailureException.unexpectedState(
            "Feeder forward scanning should not be repositioned to "
                + " a position earlier than the current position. Current"
                + " lsn = "
                + DbLsn.getNoFormatString(getLastLsn())
                + " reposition = "
                + DbLsn.getNoFormatString(startLsn));
      }
    } else {
      if (DbLsn.compareTo(getLastLsn(), startLsn) < 0) {
        throw EnvironmentFailureException.unexpectedState(
            "Feeder backward scanning should not be repositioned to "
                + " a position later than the current position. Current"
                + " lsn = "
                + DbLsn.getNoFormatString(getLastLsn())
                + " reposition = "
                + DbLsn.getNoFormatString(startLsn));
      }
    }

    long fileNum = DbLsn.getFileNumber(startLsn);
    long offset = DbLsn.getFileOffset(startLsn);

    if (window.containsLsn(fileNum, offset)) {
      window.positionBuffer(offset);
    } else {
      window.slideAndFill(fileNum, offset, offset);
    }

    if (forward) {
      nextEntryOffset = offset;
    } else {
      currentEntryPrevOffset = offset;
    }
    nReposition++;
  }
예제 #18
0
 /*
  * 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();
   }
 }
예제 #19
0
  /** @see Loggable#dumpLog */
  public void dumpLog(StringBuilder sb, boolean verbose) {
    sb.append(" matchpointVLSN=").append(matchpointVLSN.getSequence());
    sb.append(" matchpointLSN=");
    sb.append(DbLsn.getNoFormatString(matchpointLSN));

    /* Make sure the active txns are listed in order, partially for the sake
     * of the LoggableTest unit test, which expects the toString() for two
     * equivalent objects to always display the same, and partially for
     * ease of debugging.
     */
    List<Long> displayTxnIds = new ArrayList<Long>(activeTxnIds);
    Collections.sort(displayTxnIds);
    sb.append(" activeTxnIds=").append(displayTxnIds);
    sb.append("\" time=\"").append(time);
  }
 @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();
 }
  /**
   * Converts the bin/index slot, whether a singleton LN or a DIN root.
   *
   * <p>Enter/leave with bin field latched, although bin field may change.
   *
   * <p>When a singleton LN is converted, leaves with bin/index fields unchanged.
   *
   * <p>When a dup tree is converted, leaves with bin/index fields set to last inserted slot. This
   * is the slot of the highest key in the dup tree.
   */
  private void convertBinSlot() {
    if (DEBUG) {
      System.out.println(
          "DupConvert BIN LSN "
              + DbLsn.getNoFormatString(bin.getLsn(index))
              + " index "
              + index
              + " nEntries "
              + bin.getNEntries());
    }
    /* Delete slot if LN is deleted. */
    final boolean isDeleted;
    if (isLNDeleted(bin, index)) {
      deleteSlot();
      return;
    }

    final Node node = bin.fetchLNOrDIN(index, CacheMode.DEFAULT);

    if (!node.containsDuplicates()) {
      if (DEBUG) {
        System.out.println("DupConvert BIN LN " + Key.dumpString(bin.getKey(index), 0));
      }
      /* Fetching a non-deleted LN updates the slot key; we're done. */
      assert node instanceof LN;
      nConverted += 1;
      return;
    }

    /*
     * Delete the slot containing the DIN before re-inserting the dup tree,
     * so that the DIN slot key doesn't interfere with insertions.
     *
     * The DIN is evicted and memory usage is decremented. This is not
     * exactly correct because we keep a local reference to the DIN until
     * the dup tree is converted, but we tolerate this temporary
     * inaccuracy.
     */
    final byte[] binKey = bin.getKey(index);
    final DIN din = (DIN) node;
    deleteSlot();
    convertDin(din, binKey);
  }
  /**
   * Transfer a lock from another transaction to this one. Used for master-> replica transitions,
   * when a node has to transform a MasterTxn into a ReplayTxn. Another approach would be to have
   * this importunate ReplayTxn call lock() on the lsn, but that path is not available because we do
   * not have a handle on a databaseImpl.
   */
  public void stealLockFromMasterTxn(Long lsn) {

    LockAttemptResult result = lockManager.stealLock(lsn, this, LockType.WRITE);

    /*
     * Assert, and if something strange happened, opt to invalidate
     * the environment and wipe the slate clean.
     */
    if (!result.success) {
      throw EnvironmentFailureException.unexpectedState(
          envImpl,
          "Transferring from master to replica state, txn "
              + getId()
              + " was unable to transfer lock for "
              + DbLsn.getNoFormatString(lsn)
              + ", lock grant type="
              + result.lockGrant);
    }

    addLock(Long.valueOf(lsn), LockType.WRITE, result.lockGrant);
    addLogInfo(lsn);
  }
예제 #23
0
  public void testFlipFile() throws Throwable {

    /*
     * The setUp() method opens a standalone FileManager, but in this test
     * case we need a regular Environment.  On Windows, we can't lock the
     * file range twice in FileManager.lockEnvironment, so we must close
     * the standalone FileManager here before opening a regular
     * environment.
     */
    fileManager.clear();
    fileManager.close();
    fileManager = null;

    EnvironmentConfig envConfig = TestUtils.initEnvConfig();
    envConfig.setAllowCreate(true);
    envConfig.setTransactional(true);
    Environment env = new Environment(envHome, envConfig);
    EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
    FileManager fileManager = envImpl.getFileManager();

    DatabaseConfig dbConfig = new DatabaseConfig();
    dbConfig.setAllowCreate(true);
    Database exampleDb = env.openDatabase(null, "simpleDb", dbConfig);

    assertEquals("Should have 0 as current file", 0L, fileManager.getCurrentFileNum());
    long flipLsn = envImpl.forceLogFileFlip();
    assertEquals("LSN should be 1 post-flip", 1L, DbLsn.getFileNumber(flipLsn));
    DatabaseEntry key = new DatabaseEntry();
    DatabaseEntry data = new DatabaseEntry();
    key.setData("key".getBytes());
    data.setData("data".getBytes());
    exampleDb.put(null, key, data);
    assertEquals("Should have 1 as last file", 1L, fileManager.getCurrentFileNum());
    exampleDb.close();
    env.close();
  }
예제 #24
0
 @Override
 public String toString() {
   return "lsn=" + DbLsn.getNoFormatString(lsn) + " node=" + nodeId;
 }
 /*
  * Position this window at this LSN, but leave it empty, it has no data
  * yet.
  */
 public void initAtFileStart(long startLsn) {
   setFileNum(DbLsn.getFileNumber(startLsn), LogEntryType.UNKNOWN_FILE_HEADER_VERSION);
   startOffset = DbLsn.getFileOffset(startLsn);
   endOffset = startOffset;
 }
예제 #26
0
 /** @return The LSN to be used for the next log entry. */
 public long getEndOfLog() {
   return DbLsn.makeLsn(readBufferFileNum, nextUnprovenOffset);
 }
예제 #27
0
 public long getLastValidLsn() {
   return DbLsn.makeLsn(window.currentFileNum(), lastValidOffset);
 }
예제 #28
0
 /** @return The LSN to be used for the next log entry. */
 public long getEndOfLog() {
   return DbLsn.makeLsn(window.currentFileNum(), nextUnprovenOffset);
 }
예제 #29
0
  /** 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;
  }
예제 #30
0
 public long getLastValidLsn() {
   return DbLsn.makeLsn(readBufferFileNum, lastValidOffset);
 }