Package org.apache.derby.impl.store.raw.log

Examples of org.apache.derby.impl.store.raw.log.LogRecord


      int peekAmount = LogRecord.formatOverhead() + LogRecord.maxGroupStoredSize();
      if (tranId != null)
        peekAmount += LogRecord.maxTransactionIdStoredSize(tranId);
      int readAmount;    // the number of bytes actually read

      LogRecord lr;

      do
      {
        if (!open || !positionToNextRecord())
          return null;

        int checkLength;

        // this log record is a candidate unless proven otherwise
        lr = null;
        candidate = true;
        readAmount = -1;

        currentInstant = scan.readLong();
        byte[] data = input.getData();
        if (data.length < nextRecordLength)
        {
          // make a new array of sufficient size and reset the arrary
          // in the input stream
          data = new byte[nextRecordLength];
          input.setData(data);
        }

        if (logFactory.databaseEncrypted())
        {
          scan.readFully(data, 0, nextRecordLength);
          int len = logFactory.decrypt(data, 0, nextRecordLength, data, 0);
          if (SanityManager.DEBUG)
            SanityManager.ASSERT(len == nextRecordLength);
          input.setLimit(0, len);

        }
        else // no need to decrypt, only get the group and tid if we filter
        {
          if (groupmask == 0 && tranId == null)
          {
            // no filter, get the whole thing
            scan.readFully(data, 0, nextRecordLength);
            input.setLimit(0, nextRecordLength);
          }
          else
          {
            // Read only enough so that group and the tran id is in
            // the data buffer.  Group is stored as compressed int
            // and tran id is stored as who knows what.  read min
            // of peekAmount or nextRecordLength
            readAmount = (nextRecordLength > peekAmount) ?
              peekAmount : nextRecordLength;

            // in the data buffer, we now have enough to peek
            scan.readFully(data, 0, readAmount);
            input.setLimit(0, readAmount);

          }
        }

        lr = (LogRecord) input.readObject();

        if (groupmask != 0 || tranId != null)
        {
          if (groupmask != 0 && (groupmask & lr.group()) == 0)
            candidate = false; // no match, throw this log record out

          if (candidate && tranId != null)
          {
            TransactionId tid = lr.getTransactionId();
            if (!tid.equals(tranId)) // nomatch
              candidate = false; // throw this log record out
          }

          // if this log record is not filtered out, we need to read
View Full Code Here


      return null;

    if (SanityManager.DEBUG)
      SanityManager.ASSERT(scanDirection != 0, "scan has been secretly closed!");

    LogRecord lr = null;
    try
    {
      if (scanDirection == BACKWARD)
        lr = getNextRecordBackward(input, tranId, groupmask);
      else if (scanDirection == FORWARD)
View Full Code Here

    if (tranId != null)
      peekAmount += LogRecord.maxTransactionIdStoredSize(tranId);

    int readAmount;      // the number of bytes actually read

    LogRecord lr;
    long curpos = scan.getFilePointer();

    do
    {
      // this log record is a candidate unless proven otherwise
      candidate = true;
      lr = null;
      readAmount = -1;

      if (curpos == LogToFile.LOG_FILE_HEADER_SIZE)
      {
        // don't go thru the trouble of switching log file if we
        // will have gone past stopAt
        if (stopAt != LogCounter.INVALID_LOG_INSTANT &&
          LogCounter.getLogFileNumber(stopAt) == currentLogFileNumber)
        {
          if (SanityManager.DEBUG)
                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                        {
                            SanityManager.DEBUG(LogToFile.DBG_FLAG,
                                "stopping at " + currentLogFileNumber);
                        }
                    }

          return null// no more log record
        }
       
        // figure out where the last log record is in the previous
        // log file
        scan.seek(LogToFile.LOG_FILE_HEADER_PREVIOUS_LOG_INSTANT_OFFSET);
        long previousLogInstant = scan.readLong();
        scan.close();

        if (SanityManager.DEBUG)
        {
          SanityManager.ASSERT(previousLogInstant != LogCounter.INVALID_LOG_INSTANT,
                   "scanning backward beyond the first log file");
          if (currentLogFileNumber !=
              LogCounter.getLogFileNumber(previousLogInstant) + 1)
            SanityManager.THROWASSERT(
            "scanning backward but get incorrect log file number " +
             "expected " + (currentLogFileNumber -1) +
             "get " +
             LogCounter.getLogFileNumber(previousLogInstant));

          SanityManager.ASSERT(LogCounter.getLogFilePosition(previousLogInstant) >
                   LogToFile.LOG_FILE_HEADER_SIZE,
                   "scanning backward encounter completely empty log file");

          SanityManager.DEBUG(LogToFile.DBG_FLAG,
                  "scanning backwards from log file " +
                  currentLogFileNumber + ", switch to (" +
                  LogCounter.getLogFileNumber(previousLogInstant) + "," +
                  LogCounter.getLogFilePosition(previousLogInstant) + ")"
                  );
        }

        // log file switch, set this.currentLogFileNumber
        currentLogFileNumber = LogCounter.getLogFileNumber(previousLogInstant);

        scan = logFactory.getLogFileAtPosition(previousLogInstant);

        // scan is located right past the last byte of the last log
        // record in the previous log file.  currentLogFileNumber is
        // set.  We asserted that the scan is not located right at the
        // end of the file header, in other words, there is at least
        // one log record in this log file.
        curpos = scan.getFilePointer();

        // if the log file happens to be empty skip and proceed.
        // ideally this case should never occur because log switch is
        // not suppose to happen on an empty log file.
        // But it is safer to put following check incase if it ever
        // happens to avoid any recovery issues.
        if (curpos == LogToFile.LOG_FILE_HEADER_SIZE)
          continue;
      }

      scan.seek(curpos - 4);
      int recordLength = scan.readInt(); // get the length after the log record

      // calculate where this log record started.
      // include the eight bytes for the long log instant at the front
      // the four bytes of length in the front and the four bytes we just read
      long recordStartPosition = curpos - recordLength -
        LogToFile.LOG_RECORD_OVERHEAD;

      if (SanityManager.DEBUG)
      {
        if (recordStartPosition < LogToFile.LOG_FILE_HEADER_SIZE)
          SanityManager.THROWASSERT(
                 "next position " + recordStartPosition +
                 " recordLength " + recordLength +
                 " current file position " + scan.getFilePointer());

        scan.seek(recordStartPosition);

        // read the length before the log record and check it against the
        // length after the log record
        int checkLength = scan.readInt();

        if (checkLength != recordLength)
        {
          long inst = LogCounter.makeLogInstantAsLong(currentLogFileNumber, recordStartPosition);

          throw logFactory.markCorrupt(
                        StandardException.newException(
                            SQLState.LOG_RECORD_CORRUPTED,
                            new Long(checkLength),
                            new Long(recordLength),
                            new Long(inst),
                            new Long(currentLogFileNumber)));
        }
      }
      else
      {
        // skip over the length in insane
        scan.seek(recordStartPosition+4);
      }

      // scan is positioned just before the log instant
      // read the current log instant - this is the currentInstant if we have not
      // exceeded the scan limit
      currentInstant = scan.readLong();

      if (SanityManager.DEBUG)
      {
        // sanity check the current instant against the scan position
        if (LogCounter.getLogFileNumber(currentInstant) !=
          currentLogFileNumber ||
          LogCounter.getLogFilePosition(currentInstant) !=
          recordStartPosition)
          SanityManager.THROWASSERT(
                 "Wrong LogInstant on log record " +
                LogCounter.toDebugString(currentInstant) +
                 " version real position (" +
                 currentLogFileNumber + "," +
                 recordStartPosition + ")");
      }


      // if stopAt == INVALID_LOG_INSTANT, no stop instant, read till
      // nothing more can be read.  Else check scan limit
      if (currentInstant < stopAt && stopAt != LogCounter.INVALID_LOG_INSTANT)
      {
        currentInstant = LogCounter.INVALID_LOG_INSTANT;
        return null// we went past the stopAt
      }


      byte[] data = input.getData();

      if (data.length < recordLength)
      {
        // make a new array of sufficient size and reset the arrary
        // in the input stream
        data = new byte[recordLength];
        input.setData(data);
      }

      // If the log is encrypted, we must do the filtering after reading
      // and decrypting the record.
      if (logFactory.databaseEncrypted())
      {
        scan.readFully(data, 0, recordLength);
        int len = logFactory.decrypt(data, 0, recordLength, data, 0);
        if (SanityManager.DEBUG)
          SanityManager.ASSERT(len == recordLength);
        input.setLimit(0, recordLength);
      }
      else // no need to decrypt, only get the group and tid if we filter
      {
        if (groupmask == 0 && tranId == null)
        {
          // no filter, get the whole thing
          scan.readFully(data, 0, recordLength);
          input.setLimit(0, recordLength);
        }
        else
        {
          // Read only enough so that group and the tran id is in
          // the data buffer.  Group is stored as compressed int
          // and tran id is stored as who knows what.  read min
          // of peekAmount or recordLength
          readAmount = (recordLength > peekAmount) ?
            peekAmount : recordLength;

          // in the data buffer, we now have enough to peek
          scan.readFully(data, 0, readAmount);
          input.setLimit(0, readAmount);
        }
      }

      lr = (LogRecord) input.readObject();

      // skip the checksum log records, there is no need to look at them
      // during backward scans. They are used only in forwardscan during recovery.
      if(lr.isChecksum())
      {
        candidate = false;
      }else if (groupmask != 0 || tranId != null)
      {

        // skip the checksum log records 
        if(lr.isChecksum())
          candidate = false;

        if (candidate && groupmask != 0 && (groupmask & lr.group()) == 0)
          candidate = false; // no match, throw this log record out

        if (candidate && tranId != null)
        {
          TransactionId tid = lr.getTransactionId();
          if (!tid.equals(tranId)) // nomatch
            candidate = false; // throw this log record out
        }

        // if this log record is not filtered out, we need to read
View Full Code Here

    if (tranId != null)
      peekAmount += LogRecord.maxTransactionIdStoredSize(tranId);

    int readAmount;      // the number of bytes actually read

    LogRecord lr;

    do
    {
      // this log record is a candidate unless proven otherwise
      candidate = true;
      lr = null;
      readAmount = -1;

      // if we are not right at the end but this position + 4 is at
      // or exceeds the end, we know we don't have a complete log
      // record.  This is the log file and chalk it up as the fuzzy
      // end.
      if (recordStartPosition + 4 > currentLogFileLength)
      {
        // since there is no end of log file marker, we are at the
        // end of the log.
        if (SanityManager.DEBUG)
                {
                    if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                    {
                        SanityManager.DEBUG(LogToFile.DBG_FLAG,
                            "detected fuzzy log end on log file " +
                                currentLogFileNumber +
                            " record start position " + recordStartPosition +
                            " file length " + currentLogFileLength);
                    }
                }
       
        //if  recordStartPosition == currentLogFileLength
        //there is NO fuzz, it just a properly ended log
        //without the end marker.
        if(recordStartPosition != currentLogFileLength)
          fuzzyLogEnd = true ;

        // don't bother to write the end of log file marker because
        // if it is not overwritten by the next log record then
        // the next time the database is recovered it will come
        // back right here
        return null;
      }

      // read in the length before the log record
      int recordLength = scan.readInt();

      while (recordLength == 0 || recordStartPosition + recordLength +
           LogToFile.LOG_RECORD_OVERHEAD > currentLogFileLength)
      {
        // if recordLength is zero or the log record goes beyond the
        // current file, then we have detected the end of a log file.
        //
        // If recordLength == 0 then we know that this log file has either
        // been properly switched or it had a 1/2 written log record which
        // was subsequently cleared by clearFuzzyEnd.
        //
        // If recordLength != 0 but log record goes beyond the current log
        // file, we have detected a fuzzy end.  This is the last log file
        // since we will clear it by clearFuzzyEnd.

        if (recordLength != 0) // this is a fuzzy log end
        {
          if (SanityManager.DEBUG)
                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                        {
                            SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                "detected fuzzy log end on log file " +
                                    currentLogFileNumber +
                                " record start position " +
                                    recordStartPosition +
                                " file length " + currentLogFileLength +
                " recordLength=" + recordLength );
                        }
                    }

          fuzzyLogEnd = true;
          scan.close();
          scan = null;

          return null;
        }

        // recordLength == 0

        if (SanityManager.DEBUG)
                {
                    if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                    {
                        if (recordStartPosition + 4 == currentLogFileLength)
                        {
                            SanityManager.DEBUG(LogToFile.DBG_FLAG,
                                "detected proper log end on log file " +
                                currentLogFileNumber);
                        }
                        else
                        {
                            SanityManager.DEBUG(LogToFile.DBG_FLAG,
                                    "detected zapped log end on log file " +
                                        currentLogFileNumber +
                                    " end marker at " +
                                        recordStartPosition +
                                    " real end at " + currentLogFileLength);
                        }
                    }
        }
       
        // don't go thru the trouble of switching log file if we
        // have will have gone past stopAt if we want to stop here
        if (stopAt != LogCounter.INVALID_LOG_INSTANT &&
          LogCounter.getLogFileNumber(stopAt) == currentLogFileNumber)
        {
          return null;
        }

        //
        // we have a log end marker and we don't want to stop yet, switch
        // log file
        //
        scan.close();

        // set this.currentLogFileNumber
        scan = logFactory.getLogFileAtBeginning(++currentLogFileNumber);
        if (scan == null) // we have seen the last log file
        {
          return null;
        }

        // scan is position just past the log header
        recordStartPosition = scan.getFilePointer();

                // Verify that the header of the new log file refers
                // to the end of the log record of the previous file
                // (Rest of header has been verified by getLogFileAtBeginning)
        scan.seek(LogToFile
                          .LOG_FILE_HEADER_PREVIOUS_LOG_INSTANT_OFFSET);
                long previousLogInstant = scan.readLong();
                if (previousLogInstant != knownGoodLogEnd) {
                    // If there is a mismatch, something is wrong and
                    // we return null to stop the scan.  The same
                    // behavior occurs when getLogFileAtBeginning
                    // detects an error in the other fields of the header.
                    if (SanityManager.DEBUG) {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG)) {
                            SanityManager.DEBUG(LogToFile.DBG_FLAG,
                                                "log file "
                                                + currentLogFileNumber 
                                                + ": previous log record: "
                                                + previousLogInstant
                                                + " known previous log record: "
                                                + knownGoodLogEnd);
                        }
                    }
                    return null;
        }


        scan.seek(recordStartPosition);

        if (SanityManager.DEBUG)
                {
                    if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                    {
                        SanityManager.DEBUG(LogToFile.DBG_FLAG,
                            "switched to next log file " +
                            currentLogFileNumber);
                    }
                }

                // Advance knownGoodLogEnd to make sure that if this
                // log file is the last log file and empty, logging
                // continues in this file, not the old file.
                knownGoodLogEnd = LogCounter.makeLogInstantAsLong
                    (currentLogFileNumber, recordStartPosition);

        // set this.currentLogFileLength
        currentLogFileLength = scan.length();

        if (recordStartPosition+4 >= currentLogFileLength) // empty log file
        {
          if (SanityManager.DEBUG)
                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                        {
                            SanityManager.DEBUG(LogToFile.DBG_FLAG,
                                "log file " + currentLogFileNumber +
                                " is empty");
                        }
                    }

          return null;
        }

        // we have successfully switched to the next log file.
        // scan is positioned just before the next log record
        // see if this one is written in entirety
        recordLength = scan.readInt();
      }

      // we know the entire log record is on this log file

      // read the current log instant
      currentInstant = scan.readLong();

      /*check if the current instant happens is less than the last one.
       *This can happen if system crashed before writing the log instant
       *completely. If the instant is partially written it will be less
       *than the last one and should be the last record that was suppose to
       *get written. Currentlt preallocated files are filled with zeros,
       *this should hold good.
       *Note: In case of Non-preallocated files earlier check with log
       * file lengths should have found the end. But in prellocated files, log file
       *length is not sufficiant to find the log end. This check
       *is must to find the end in preallocated log files.
       */
      if(currentInstant < knownGoodLogEnd)
      {
        fuzzyLogEnd = true ;
        return null;
      }

      // sanity check it
      if (SanityManager.DEBUG)
      {
        if (LogCounter.getLogFileNumber(currentInstant) !=
          currentLogFileNumber ||
          LogCounter.getLogFilePosition(currentInstant) !=
          recordStartPosition)
          SanityManager.THROWASSERT(
                "Wrong LogInstant on log record " +
                LogCounter.toDebugString(currentInstant) +
                 " version real position (" +
                 currentLogFileNumber + "," +
                 recordStartPosition + ")");
      }


      // if stopAt == INVALID_LOG_INSTANT, no stop instant, read till
      // nothing more can be read.  Else check scan limit
      if (stopAt != LogCounter.INVALID_LOG_INSTANT && currentInstant > stopAt)
      {
        currentInstant = LogCounter.INVALID_LOG_INSTANT;
        return null;      // we went past the stopAt
      }

      // read in the log record
      byte[] data = input.getData();

      if (data.length < recordLength)
      {
        // make a new array of sufficient size and reset the arrary
        // in the input stream
        data = new byte[recordLength];
        input.setData(data);
      }

      // If the log is encrypted, we must do the filtering after
      // reading and decryptiong the record.

      if (logFactory.databaseEncrypted())
      {
        scan.readFully(data, 0, recordLength);
        int len = logFactory.decrypt(data, 0, recordLength, data, 0);
        if (SanityManager.DEBUG)
          SanityManager.ASSERT(len == recordLength);

        input.setLimit(0, len);
      }
      else // no need to decrypt, only get the group and tid if we filter
      {
        if (groupmask == 0 && tranId == null)
        {
          // no filter, get the whole thing
          scan.readFully(data, 0, recordLength);
          input.setLimit(0, recordLength);
        }
        else
        {
          // Read only enough so that group and the tran id is in
          // the data buffer.  Group is stored as compressed int
          // and tran id is stored as who knows what.  read min
          // of peekAmount or recordLength
          readAmount = (recordLength > peekAmount) ?
            peekAmount : recordLength;

          // in the data buffer, we now have enough to peek
          scan.readFully(data, 0, readAmount);
          input.setLimit(0, readAmount);
        }
      }

      lr = (LogRecord) input.readObject();
      if (groupmask != 0 || tranId != null)
      {
        if (groupmask != 0 && (groupmask & lr.group()) == 0)
          candidate = false; // no match, throw this log record out

        if (candidate && tranId != null)
        {
          TransactionId tid = lr.getTransactionId();
          if (!tid.equals(tranId)) // nomatch
            candidate = false; // throw this log record out
        }

        // if this log record is not filtered out, we need to read
        // in the rest of the log record to the input buffer.
        // Except if it is an encrypted database, in which case the
        // entire log record have already be read in for
        // decryption.
        if (candidate && !logFactory.databaseEncrypted())
        {
          // read the rest of the log into the buffer
          if (SanityManager.DEBUG)
            SanityManager.ASSERT(readAmount > 0);

          if (readAmount < recordLength)
          {
            // Need to remember where we are because the log
            // record may have read part of it off the input
            // stream already and that position is lost when we
            // set limit again.
            int inputPosition = input.getPosition();

            scan.readFully(data, readAmount,
                     recordLength-readAmount);

            input.setLimit(0, recordLength);
            input.setPosition(inputPosition);
          }
        }
      }

      /*check if the logrecord length written before and after the
       *log record are equal, if not the end of of the log is reached.
       *This can happen if system crashed before writing the length field
       *in the end of the records completely. If the length is partially
       *written or not written at all  it will not match with length written
       *in the beginning of the log record. Currentlt preallocated files
       *are filled with zeros, log record length can never be zero;
       *if the lengths are not matching, end of the properly written log
       *is reached.
       *Note: In case of Non-preallocated files earlier fuzzy case check with log
       * file lengths should have found the end. But in prellocated files, log file
       *length is not sufficiant to find the log end. This check
       *is must to find the end in preallocated log files.
       */
      // read the length after the log record and check it against the
      // length before the log record, make sure we go to the correct
      // place for skipped log record.
      if (!candidate)
        scan.seek(recordStartPosition - 4);
      int checkLength = scan.readInt();
      if (checkLength != recordLength && checkLength < recordLength)
      {


        //lengh written in the end of the log record should be always
        //less then the length written in the beginning if the log
        //record was half written before the crash.
        if(checkLength < recordLength)
        {
          fuzzyLogEnd = true ;
          return null;
        }else
        {
       
          //If checklength > recordLength then it can be not be a partial write
          //probablly it is corrupted for some reason , this should never
          //happen throw error in debug mode. In non debug case , let's
          //hope it's only is wrong and system can proceed.
           
          if (SanityManager.DEBUG)
          { 
            throw logFactory.markCorrupt
            (StandardException.newException(
              SQLState.LOG_RECORD_CORRUPTED,
                            new Long(checkLength),
                            new Long(recordLength),
                            new Long(currentInstant),
                            new Long(currentLogFileNumber)));

          }
         
          //In non debug case, do nothing , let's hope it's only
          //length part that is incorrect and system can proceed.
        }

      }

      // next record start position is right after this record
      recordStartPosition += recordLength + LogToFile.LOG_RECORD_OVERHEAD;
      knownGoodLogEnd = LogCounter.makeLogInstantAsLong
                (currentLogFileNumber, recordStartPosition);


      if (SanityManager.DEBUG)
      {
        if (recordStartPosition != scan.getFilePointer())
          SanityManager.THROWASSERT(
                   "calculated end " + recordStartPosition +
                   " != real end " + scan.getFilePointer());
      }
      else
      {
        // seek to the start of the next log record
        scan.seek(recordStartPosition);
      }

      // the scan is now positioned just past this log record and right
      // at the beginning of the next log record


      /** if the current log record is a checksum log record then
       * using the information available in this record validate
       * that data in the log file by matching the checksum in
       * checksum log record and by recalculating the checksum for the
       * specified length of the data in the log file. cheksum values
       * should match unless the right was incomplete before the crash.
       */
      if(lr.isChecksum())
      {
        // checksum log record should not be returned to the logger recovery redo
        // routines, it is just used to identify the incomplete log writes.

        candidate = false;
        Loggable op = lr.getLoggable();
        if (SanityManager.DEBUG)
                {
                    if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY) ||
                        SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))

View Full Code Here

    // Keep in mind the dynamic nature of the logOutputBuffer which means
    // it could switch buffer from underneath the logOutputBuffer on every
    // write.
    logIn = new ArrayInputStream();
    logRecord = new LogRecord();

  }
View Full Code Here

        SanityManager.ASSERT(
                    scanLog != null, "cannot open log for prepare");

      rawInput    = new ArrayInputStream(new byte[4096]);

      LogRecord record;

      while ((record =
                    scanLog.getNextRecord(rawInput, prepareId, 0))
                       != null)
      {
        if (SanityManager.DEBUG)
        {
          SanityManager.ASSERT(
                        record.getTransactionId().equals(prepareId),
              "getNextRecord return unqualified log rec for prepare");
        }

        logrecordseen++;

        if (record.isCLR())
        {
          clrskipped++;

                    // the loggable is still in the input stream, get rid of it
          record.skipLoggable();

          // read the prepareInstant
          long prepareInstant = rawInput.readLong();

          if (SanityManager.DEBUG)
                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                        {
                            SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                    "Skipping over CLRs, reset scan to " +
                                    LogCounter.toDebugString(prepareInstant));
                        }
          }

          scanLog.resetPosition(new LogCounter(prepareInstant));
          // scanLog now positioned at the beginning of the log
          // record that was rolled back by this CLR.
          // The scan is a backward one so getNextRecord will skip
          // over the record that was rolled back and go to the one
          // previous to it

          continue;
        }

                if (record.requiresPrepareLocks())
                {
                    lop = record.getRePreparable();
                }
                else
                {
                    continue;
                }
View Full Code Here

        SanityManager.ASSERT(
                    scanLog != null, "cannot open log for undo");

      rawInput   = new ArrayInputStream(new byte[4096]);

      LogRecord record;

      while ((record =
                    scanLog.getNextRecord(rawInput, undoId, 0))
                        != null)
      {
        if (SanityManager.DEBUG)
        {
          SanityManager.ASSERT(
                        record.getTransactionId().equals(undoId),
                        "getNextRecord return unqualified log record for undo");
        }

        logrecordseen++;

        if (record.isCLR())
        {
          clrskipped++;

                    // the loggable is still in the input stream, get rid of it
          record.skipLoggable();

          // read the undoInstant
          long undoInstant = rawInput.readLong();

          if (SanityManager.DEBUG)
                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
                        {
                            SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                "Skipping over CLRs, reset scan to " +
                                LogCounter.toDebugString(undoInstant));
                        }
                    }


          scanLog.resetPosition(new LogCounter(undoInstant));

          // scanLog now positioned at the beginning of the log
          // record that was rolled back by this CLR.
          // The scan is a backward one so getNextRecord will skip
          // over the record that was rolled back and go to the one
          // previous to it

          continue;
        }

        lop = record.getUndoable();

        if (lop != null)
        {
          int optionalDataLength = rawInput.readInt();
          int savePosition = rawInput.getPosition();
View Full Code Here

    try
        {

      // scan the log forward in redo pass and go to the end
      LogRecord record;
      while((record =
                    redoScan.getNextRecord(logIn, null, 0))
                        != null)
      {
        scanCount++;
        long undoInstant = 0;

        // last known good instant
        instant = redoScan.getInstant();

        // last known good log end
        logEnd = redoScan.getLogRecordEnd();


        // NOTE NOTE -- be very careful about the undoInstant, it is
        // read off the input stream in this debug section.
        // if we change the log format we will need to change the way
        // the undo instant is gotten.  Also, once it is read off, it
        // should not be read from the stream any more
        // NOTE NOTE
        if (SanityManager.DEBUG)
                {
                    if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY) ||
                        SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))

                    {
                        if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY))
                            SanityManager.DEBUG_SET(LogToFile.DBG_FLAG);

                        op = record.getLoggable();
                        tranId = record.getTransactionId();
                        if (record.isCLR()) 
                        {
                            // !!!!!!! this moves the file pointer
                            undoInstant = logIn.readLong();

                            SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                "scanned " + tranId + " : " + op +
                                " instant = " +
                                    LogCounter.toDebugString(instant) +
                                " undoInstant : " +
                                    LogCounter.toDebugString(undoInstant));
                        }
                        else
                        {
                            SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                "scanned " + tranId + " : " + op +
                                " instant = " +
                                    LogCounter.toDebugString(instant)
                                + " logEnd = " +
                                    LogCounter.toDebugString(logEnd)
                                + " logIn at " + logIn.getPosition()
                                + " available " + logIn.available());
                        }

                        // we only want to dump the log, don't touch it
                        if (SanityManager.DEBUG_ON(LogToFile.DUMP_LOG_ONLY))
                            continue;
                    }
                }

        // if the redo scan is between the undoLWM and redoLWM, we only
        // need to redo begin and end tran.  Everything else has
        // already been flushed by checkpoint
        if (redoLWM !=
                        LogCounter.INVALID_LOG_INSTANT && instant < redoLWM)
        {
          if (!(record.isFirst()      ||
                          record.isComplete()   ||
                          record.isPrepare()))
                    {
            continue;
                    }
        }

        // get the transaction
        tranId = record.getTransactionId();

        // if this transaction is known to the transaction factory, make
                // the recoveryTransaction assume its identitiy and properties
                // otherwise, make it known to the transaction factory
        if (!transFactory.findTransaction(tranId, recoveryTransaction))
        {
          // transaction not found

          if (redoLWM != LogCounter.INVALID_LOG_INSTANT &&
            instant < redoLWM &&
                        (record.isPrepare() || record.isComplete()))
          {
            // What is happening here is that a transaction that
            // started before the undoLWM has commited by the time
            // the checkpoint undoLWM was taken.  Hence, we only
            // see the tail end of its log record and its endXact
                        // record.
            //
            // NOTE:
            // Since we didn't see its beginXact, we cannot do the
            // endXact's doMe either.  Also if the endXact, is
                        // actually just a prepare, we don't need to do
                        // anything as the transaction will commit or abort
                        // prior to point we are recovering to.
            // If it is deemed necessary to do the endXact's doMe,
                        // then we should start the transaction right here.
                        // For now, just completely ignore this transaction
            //
            etranCount++;

            continue;
          }

          if ((ttabInstant == LogCounter.INVALID_LOG_INSTANT) &&
                        !record.isFirst())
                    {
            throw StandardException.newException(
                            SQLState.LOG_UNEXPECTED_RECOVERY_PROBLEM,
                            MessageService.getTextMessage(MessageId.LOG_RECORD_NOT_FIRST,tranId));

                    }

          if (SanityManager.DEBUG)
          {
            // if we dumped the transaction table but see a non
                        // BeginXact record after the transaction table dump
                        // instant, error.
            if (ttabInstant != LogCounter.INVALID_LOG_INSTANT)
            {
              if (instant > ttabInstant && !record.isFirst())
                            {
                SanityManager.THROWASSERT(
                "log record is Not first but transaction " +
                                "is not in transaction table (2) : " + tranId);
                            }

              // If we dump the transaction table and the table
              // does not have the transaction, and we see this
              // beginXact before the ttab instant, we could have
              // igored it because we "know" that we should see
              // the endXact before the ttab instant also.
              // Leave it in just in case.
            }
          }
          btranCount++;

          // the long transaction ID is embedded in the beginXact log
          // record.  The short ID is stored in the log record.
          recoveryTransaction.setTransactionId(
                        record.getLoggable(), tranId);

        }
        else       
        {
                    // recoveryTransaction found
                   
          if ((ttabInstant == LogCounter.INVALID_LOG_INSTANT) &&
                         record.isFirst())
                    {
            throw StandardException.newException(
                            SQLState.LOG_UNEXPECTED_RECOVERY_PROBLEM,
                            MessageService.getTextMessage(MessageId.LOG_RECORD_FIRST,
                                tranId));

                    }

          if (SanityManager.DEBUG)
          {
            if (ttabInstant != LogCounter.INVALID_LOG_INSTANT &&
              instant > ttabInstant &&
              record.isFirst())
                        {
              SanityManager.THROWASSERT(
                "log record is first but transaction is " +
                                "already in transaction table (3): " + tranId);
                        }

                        if (record.isPrepare())
                            prepareCount++;
          }

          // if we have a transaction table dumped with the
          // checkpoint log record, then during the redo scan we may
          // see the beginXact of a transaction which is already in
                    // the transaction table, just ignore it if it is after the
          // redoLWM but before the transaction table instant.  We
          // still need to redo any database changes but since the
          // transaction is already recorded in the transaction
          // table, ignore it.
          //
          if (record.isFirst())
          {
            btranCount++;
            continue;
          }
        }
       
        op = record.getLoggable();

        if (SanityManager.DEBUG)
                {
                    if (!record.isCLR())
                    {
                        if (logIn.available() < 4)
                        {
                            SanityManager.THROWASSERT(
                              "not enough bytes read in : " +
                                  logIn.available() +
                              " for " + op + " instant " +
                                  LogCounter.toDebugString(instant));
                        }
                    }
                }

        if (SanityManager.DEBUG)
                {
          SanityManager.ASSERT(
                        !recoveryTransaction.handlesPostTerminationWork(),
             "recovery transaction handles post termination work");
                }

        if (op.needsRedo(recoveryTransaction))
        {
          redoCount++;

          if (record.isCLR()) 
          {
            clrCount++;

            // the log operation is not complete, the operation to
            // undo is stashed away at the undoInstant.
            // Reconstitute that first.

            if (SanityManager.DEBUG)
              SanityManager.ASSERT(op instanceof Compensation);


                        // this value may be set by sanity xxxx
            if (undoInstant == 0)
              undoInstant = logIn.readLong();

            if (undoScan == null)
            {
              undoScan = (StreamLogScan)
                logFactory.openForwardsScan(
                                    undoInstant,(LogInstant)null);
            }
            else
            {
              undoScan.resetPosition(new LogCounter(undoInstant));
            }

            // undoScan now positioned at the beginning of the log
            // record was rolled back by this CLR. 
            // The scan is a forward one so getNextRecord will get
                        // the log record that needs to be rolled back.

            // reuse the buffer in logIn and logIn since CLR
                        // has no optional data and has no use for them anymore
            logIn.clearLimit();
            LogRecord undoRecord =
              undoScan.getNextRecord(logIn, null, 0);

            Undoable undoOp = undoRecord.getUndoable();

            if (SanityManager.DEBUG)
            {
              SanityManager.DEBUG(
                                LogToFile.DBG_FLAG,
                                "Redoing CLR: undoInstant = " +
                                    LogCounter.toDebugString(undoInstant) +
                                " clrinstant = " +
                                    LogCounter.toDebugString(instant));

              SanityManager.ASSERT(
                                undoRecord.getTransactionId().equals(tranId));

              SanityManager.ASSERT(undoOp != null);
            }

            ((Compensation)op).setUndoOp(undoOp);
View Full Code Here

  {
    Loggable lop = null;

    ArrayInputStream logInputBuffer = new ArrayInputStream(new byte[size]);

    LogRecord record = scan.getNextRecord(logInputBuffer, null, 0);
    if (record != null)
      lop = record.getLoggable();
    return lop;
  }
View Full Code Here

      return null;

    if (SanityManager.DEBUG)
      SanityManager.ASSERT(scanDirection != 0, "scan has been secretly closed!");

    LogRecord lr = null;
    try
    {
      if (scanDirection == BACKWARD)
        lr = getNextRecordBackward(input, tranId, groupmask);
      else if (scanDirection == FORWARD)
View Full Code Here

TOP

Related Classes of org.apache.derby.impl.store.raw.log.LogRecord

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.