private void reportProblem(Exception e) {

    StringBuilder sb = new StringBuilder();
    sb.append("Halted log file reading at file 0x")
        .append(Long.toHexString(window.currentFileNum()))
        .append(" offset 0x")
        .append(Long.toHexString(nextEntryOffset))
        .append(" offset(decimal)=")
        .append(nextEntryOffset)
        .append(" prev=0x")
        .append(Long.toHexString(currentEntryPrevOffset));

    if (currentEntryHeader != null) {
      LogEntryType problemType = LogEntryType.findType(currentEntryHeader.getType());
      sb.append(":\nentry=")
          .append(problemType)
          .append("type=")
          .append(currentEntryHeader.getType())
          .append(",version=")
          .append(currentEntryHeader.getVersion())
          .append(")\nprev=0x")
          .append(Long.toHexString(currentEntryPrevOffset))
          .append("\nsize=")
          .append(currentEntryHeader.getItemSize())
          .append("\nNext entry should be at 0x")
          .append(
              Long.toHexString(
                  nextEntryOffset
                      + currentEntryHeader.getSize()
                      + currentEntryHeader.getItemSize()));
    }

    LoggerUtils.traceAndLogException(envImpl, "FileReader", "readNextEntry", sb.toString(), e);
  }
  /** Copy the required number of bytes into the save buffer. */
  private void copyToSaveBuffer(int bytesNeeded) {
    /* How much can we get from this current read buffer? */
    int bytesFromThisBuffer;

    if (bytesNeeded <= window.remaining()) {
      bytesFromThisBuffer = bytesNeeded;
    } else {
      bytesFromThisBuffer = window.remaining();
    }

    /* Gather it all into this save buffer. */
    ByteBuffer temp;

    /* Make sure the save buffer is big enough. */
    if (saveBuffer.capacity() - threadSafeBufferPosition(saveBuffer) < bytesFromThisBuffer) {
      /* Grow the save buffer. */
      temp = ByteBuffer.allocate(saveBuffer.capacity() + bytesFromThisBuffer);
      threadSafeBufferFlip(saveBuffer);
      temp.put(saveBuffer);
      saveBuffer = temp;
    }

    /*
     * Bulk copy only the required section from the read buffer into the
     * save buffer. We need from readBuffer.position() to
     * readBuffer.position() + bytesFromThisBuffer
     */
    temp = window.getBuffer().slice();
    temp.limit(bytesFromThisBuffer);
    saveBuffer.put(temp);
    window.incrementBufferPosition(bytesFromThisBuffer);
  }
  /**
   * Try to read a specified number of bytes.
   *
   * @param amountToRead is the number of bytes we need
   * @param collectData is true if we need to actually look at the data. If false, we know we're
   *     skipping this entry, and all we need to do is to count until we get to the right spot.
   * @return a byte buffer positioned at the head of the desired portion, or null if we reached eof.
   */
  private ByteBuffer readData(int amountToRead, boolean collectData)
      throws ChecksumException, EOFException, FileNotFoundException, DatabaseException {

    int alreadyRead = 0;
    ByteBuffer completeBuffer = null;
    saveBuffer.clear();

    while ((alreadyRead < amountToRead) && !eof) {

      int bytesNeeded = amountToRead - alreadyRead;
      if (window.hasRemaining()) {

        /* There's data in the window, process it. */
        if (collectData) {

          /*
           * Save data in a buffer for processing.
           */
          if ((alreadyRead > 0) || (window.remaining() < bytesNeeded)) {

            /* We need to piece an entry together. */
            copyToSaveBuffer(bytesNeeded);
            alreadyRead = threadSafeBufferPosition(saveBuffer);
            completeBuffer = saveBuffer;
          } else {

            /* A complete entry is available in this buffer. */
            completeBuffer = window.getBuffer();
            alreadyRead = amountToRead;
          }
        } else {

          /*
           * We're not processing the data, so need to save it. just
           * move buffer positions.
           */
          int positionIncrement =
              (window.remaining() > bytesNeeded) ? bytesNeeded : window.remaining();

          alreadyRead += positionIncrement;
          window.incrementBufferPosition(positionIncrement);
          completeBuffer = window.getBuffer();
        }
      } else {

        /*
         * Look for more data.
         */
        if (window.fillNext(singleFile, bytesNeeded)) {
          /* This call to fillNext slid the window to a new file. */
          nextEntryOffset = 0;
        }
      }
    }

    /* Flip the save buffer just in case we've been accumulating in it. */
    threadSafeBufferFlip(saveBuffer);

    return completeBuffer;
  }
Example #4
0
    void startSwitchingToReadMode(ReadWindow window) {
      readCacheStatus = READ_CACHE_STATUS.SWITCHINGTOREADMODE;
      i2cDevice.enableI2cReadMode(window.getIregFirst(), window.getCreg());
      enabledReadMode = true;

      // Remember what we actually told the controller
      readWindowSentToController = window;
      readWindowSentToControllerInitialized = true;

      setActionFlag = true; // causes an I2C read to happen
      queueFullWrite = true; // for just the mode bytes
      queueRead = true; // read the mode byte so we can tell when the switch is done

      dirtyModeCacheStatus();
    }
  /** 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);
    }
  }
 /** TBW */
 protected void handleGapInBackwardsScan(long prevFileNum) {
   throw new EnvironmentFailureException(
       envImpl,
       EnvironmentFailureReason.LOG_INTEGRITY,
       "Cannot read backward over cleaned file"
           + " from "
           + window.currentFileNum()
           + " to "
           + prevFileNum);
 }
  /**
   * 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();
      }
    }
  }
  /**
   * Add the entry bytes to the checksum and check the value. This method must be called with the
   * buffer positioned at the start of the entry.
   */
  private void validateChecksum(ByteBuffer dataBuffer, boolean isChecksumTarget)
      throws ChecksumException {

    if (!doChecksumOnRead) {
      return;
    }

    if (!isChecksumTarget) {
      return;
    }

    cksumValidator.update(dataBuffer, currentEntryHeader.getItemSize());
    cksumValidator.validate(
        currentEntryHeader.getChecksum(), window.currentFileNum(), currentEntryOffset);
  }
Example #9
0
  /** Set the set of registers that we will read and read and read again on every hardware cycle */
  @Override
  public void setReadWindow(ReadWindow newWindow) {
    synchronized (this.concurrentClientLock) {
      synchronized (this.callbackLock) {
        if (this.readWindow == null
            || !this.readWindow.isOkToRead()
            || !this.readWindow.sameAsIncludingMode(newWindow)) {
          // Remember the new window, but get a fresh copy so we can implement the read mode policy
          this.readWindow = newWindow.freshCopy();
          assertTrue(!BuildConfig.DEBUG || this.readWindow.isOkToRead());

          // Let others know of the update
          this.readWindowChanged = true;
        }
      }
    }
  }
 /** Returns the number of reads since the last time this method was called. */
 public int getAndResetNReads() {
   return window.getAndResetNReads();
 }
  /**
   * 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;
  }
 /** Get LSN of the last entry read. */
 public long getLastLsn() {
   return DbLsn.makeLsn(window.currentFileNum(), currentEntryOffset);
 }
 public long getNRepeatIteratorReads() {
   return window.getNRepeatIteratorReads();
 }