Exemple #1
0
  /**
   * Something is wrong with this file. If there is no data in this file (the header is <= the file
   * header size) then move this last file aside and search the next "last" file. If the last file
   * does have data in it, return null and throw an exception back to the application, since we're
   * not sure what to do now.
   *
   * @param cause is a DatabaseException or ChecksumException.
   */
  private Long attemptToMoveBadFile(Exception cause)
      throws IOException, ChecksumException, DatabaseException {

    String fileName = fileManager.getFullFileNames(window.currentFileNum())[0];
    File problemFile = new File(fileName);

    if (problemFile.length() <= FileManager.firstLogEntryOffset()) {
      fileManager.clear(); // close all existing files
      /* Move this file aside. */
      Long lastNum = fileManager.getFollowingFileNum(window.currentFileNum(), false);
      if (!fileManager.renameFile(window.currentFileNum(), FileManager.BAD_SUFFIX)) {
        throw EnvironmentFailureException.unexpectedState(
            "Could not rename file: 0x" + Long.toHexString(window.currentFileNum()));
      }

      return lastNum;
    }
    /* There's data in this file, throw up to the app. */
    if (cause instanceof DatabaseException) {
      throw (DatabaseException) cause;
    }
    if (cause instanceof ChecksumException) {
      throw (ChecksumException) cause;
    }
    throw EnvironmentFailureException.unexpectedException(cause);
  }
Exemple #2
0
  /** Override so that we always start at the last file. */
  protected void initStartingPosition(long endOfFileLsn, Long singleFileNum)
      throws IOException, DatabaseException {

    eof = false;

    /*
     * 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;
    readBufferFileEnd = 0;

    long fileLen = 0;
    while ((fileHandle == null) && !eof) {
      if (lastNum == null) {
        eof = true;
      } else {
        try {
          readBufferFileNum = lastNum.longValue();
          fileHandle = fileManager.getFileHandle(readBufferFileNum);

          /*
           * 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.longValue(), false);
            if (lastNum != null) {
              fileHandle.release();
              fileHandle = null;
            }
          }
        } catch (DatabaseException e) {
          lastNum = attemptToMoveBadFile(e);
          fileHandle = null;
        } finally {
          if (fileHandle != null) {
            fileHandle.release();
          }
        }
      }
    }

    nextEntryOffset = 0;
  }
Exemple #3
0
  /**
   * Something is wrong with this file. If there is no data in this file (the header is <= the file
   * header size) then move this last file aside and search the next "last" file. If the last file
   * does have data in it, throw an exception back to the application, since we're not sure what to
   * do now.
   */
  private Long attemptToMoveBadFile(DatabaseException origException)
      throws DatabaseException, IOException {

    String fileName = fileManager.getFullFileNames(readBufferFileNum)[0];
    File problemFile = new File(fileName);
    Long lastNum = null;

    if (problemFile.length() <= FileManager.firstLogEntryOffset()) {
      fileManager.clear(); // close all existing files
      /* Move this file aside. */
      lastNum = fileManager.getFollowingFileNum(readBufferFileNum, false);
      fileManager.renameFile(readBufferFileNum, FileManager.BAD_SUFFIX);

    } else {
      /* There's data in this file, throw up to the app. */
      throw origException;
    }
    return lastNum;
  }
Exemple #4
0
  public void testTruncatedHeader() throws IOException, DatabaseException {

    /* Create a log file */
    FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);

    /* Truncate the header */
    RandomAccessFile file0 =
        new RandomAccessFile(
            fileManager.getFullFileName(0, FileManager.JE_SUFFIX),
            FileManager.FileMode.READWRITE_MODE.getModeValue());
    file0.getChannel().truncate(FileManager.firstLogEntryOffset() / 2);
    file0.close();

    try {
      fileManager.getFileHandle(0);
      fail("Should see assertion");
    } catch (DatabaseException e) {
    }
  }
Exemple #5
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());
  }
Exemple #6
0
  /** See if we can catch a file with an invalid header. */
  public void testBadHeader() throws IOException, DatabaseException {

    /* First try a bad environment r/w. */
    try {
      FileManager test = new FileManager(envImpl, new File("xxyy"), true);
      fail("expect creation of " + test + "to fail.");
    } catch (LogException e) {
      /* should throw */
    }

    /* Next try a bad environment r/o. */
    try {
      FileManager test = new FileManager(envImpl, new File("xxyy"), false);
      fail("expect creation of " + test + "to fail.");
    } catch (DatabaseException e) {
      /* should throw */
    }

    /* Now create a file, but mess up the header. */
    FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);

    byte[] badData = new byte[] {1, 1};
    int headerSize = FileManager.firstLogEntryOffset();
    RandomAccessFile file0 =
        new RandomAccessFile(
            fileManager.getFullFileName(0, FileManager.JE_SUFFIX),
            FileManager.FileMode.READWRITE_MODE.getModeValue());
    file0.write(badData);
    file0.close();
    fileManager.clear();

    try {
      FileHandle file0Handle = fileManager.getFileHandle(0L);
      fail("expect to catch a checksum error");
    } catch (DbChecksumException e) {
    }
  }
Exemple #7
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;
  }
Exemple #8
0
  /** 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;
    }
  }