Пример #1
0
  /**
   * This reader looks at all nodes for the max node id and database id. It only returns
   * non-provisional INs and IN delete entries.
   */
  protected boolean processEntry(ByteBuffer entryBuffer) throws DatabaseException {

    boolean useEntry = false;
    boolean entryLoaded = false;

    /* If this is a targetted entry, read the entire log entry. */
    if (targetLogEntry != null) {
      targetLogEntry.readEntry(entryBuffer, currentEntrySize, currentEntryTypeVersion, true);
      DatabaseId dbId = getDatabaseId();
      boolean isMapDb = dbId.equals(DbTree.ID_DB_ID);
      useEntry = (!mapDbOnly || isMapDb);
      entryLoaded = true;
    }

    /* Do a partial load during tracking if necessary. */
    if (trackIds) {

      /*
       * Do partial load of db and txn id tracking entries if necessary.
       * Note that these entries do not overlap with targetLogEntry.
       *
       * XXX We're doing a full load for now, since LNLogEntry does not
       * read the db and txn id in a partial load, only the node id.
       */
      LNLogEntry lnEntry = null;
      if (dbIdTrackingEntry != null) {
        /* This entry has a db id */
        lnEntry = dbIdTrackingEntry;
        lnEntry.readEntry(
            entryBuffer, currentEntrySize, currentEntryTypeVersion, true /* full load */);
        entryLoaded = true;
        MapLN mapLN = (MapLN) lnEntry.getMainItem();
        int dbId = mapLN.getDatabase().getId().getId();
        if (dbId > maxDbId) {
          maxDbId = dbId;
        }
      }
      if (txnIdTrackingEntry != null) {
        /* This entry has a txn id */
        if (lnEntry == null) {
          lnEntry = txnIdTrackingEntry;
          lnEntry.readEntry(
              entryBuffer, currentEntrySize, currentEntryTypeVersion, true /* full load */);
          entryLoaded = true;
        }
        long txnId = lnEntry.getTxnId().longValue();
        if (txnId > maxTxnId) {
          maxTxnId = txnId;
        }
      }

      /*
       * Perform utilization counting under trackIds to prevent
       * double-counting.
       */
      if (fsTrackingEntry != null) {

        /* Must do full load to get key from file summary LN. */
        if (!entryLoaded) {
          nodeTrackingEntry.readEntry(
              entryBuffer, currentEntrySize, currentEntryTypeVersion, true /* full load */);
          entryLoaded = true;
        }

        /*
         * When a FileSummaryLN is encountered, reset the tracked
         * summary for that file to replay what happens when a
         * FileSummaryLN log entry is written.
         */
        byte[] keyBytes = fsTrackingEntry.getKey();
        FileSummaryLN fsln = (FileSummaryLN) fsTrackingEntry.getMainItem();
        long fileNum = fsln.getFileNumber(keyBytes);
        TrackedFileSummary trackedLN = tracker.getTrackedFile(fileNum);
        if (trackedLN != null) {
          trackedLN.reset();
        }

        /* Save the LSN of the FileSummaryLN for use by undo/redo. */
        fileSummaryLsns.put(new Long(fileNum), new Long(getLastLsn()));

        /*
         * SR 10395: Do not cache the file summary in the
         * UtilizationProfile here, since it may be for a deleted log
         * file.
         */
      }

      /*
       * Do partial load of nodeTrackingEntry (and inTrackingEntry) if not
       * already loaded. We only need the node id.
       */
      if (nodeTrackingEntry != null) {
        if (!entryLoaded) {
          nodeTrackingEntry.readEntry(
              entryBuffer, currentEntrySize, currentEntryTypeVersion, false /* partial load */);
          entryLoaded = true;
        }
        /* Keep track of the largest node id seen. */
        long nodeId = nodeTrackingEntry.getNodeId();
        maxNodeId = (nodeId > maxNodeId) ? nodeId : maxNodeId;
      }

      if (inTrackingEntry != null) {
        assert entryLoaded : "All nodes should have been loaded";

        /*
         * Count the obsolete LSN of the previous version, if available
         * and if not already counted. Use inexact counting for two
         * reasons: 1) we don't always have the full LSN because earlier
         * log versions only had the file number, and 2) we can't
         * guarantee obsoleteness for provisional INs.
         */
        long oldLsn = inTrackingEntry.getObsoleteLsn();
        if (oldLsn != DbLsn.NULL_LSN) {
          long newLsn = getLastLsn();
          if (!isObsoleteLsnAlreadyCounted(oldLsn, newLsn)) {
            tracker.countObsoleteNodeInexact(oldLsn, fromLogType);
          }
        }

        /*
         * Count a provisional IN as obsolete if it follows
         * partialCkptStart. It cannot have been already counted,
         * because provisional INs are not normally counted as obsolete;
         * they are only considered obsolete when they are part of a
         * partial checkpoint.
         *
         * Depending on the exact point at which the checkpoint was
         * aborted, this technique is not always accurate; therefore
         * inexact counting must be used.
         */
        if (isProvisional && partialCkptStart != DbLsn.NULL_LSN) {
          oldLsn = getLastLsn();
          if (DbLsn.compareTo(partialCkptStart, oldLsn) < 0) {
            tracker.countObsoleteNodeInexact(oldLsn, fromLogType);
          }
        }
      }
    }

    /* Return true if this entry should be processed */
    return useEntry;
  }
Пример #2
0
  // changed to public
  public boolean isTargetEntry(byte entryTypeNum, byte entryTypeVersion) throws DatabaseException {

    lastEntryWasDelete = false;
    lastEntryWasDupDelete = false;
    targetLogEntry = null;
    dbIdTrackingEntry = null;
    txnIdTrackingEntry = null;
    nodeTrackingEntry = null;
    inTrackingEntry = null;
    fsTrackingEntry = null;
    isProvisional = LogEntryType.isProvisional(entryTypeVersion);

    /* Get the log entry type instance we need to read the entry. */
    fromLogType = LogEntryType.findType(entryTypeNum, entryTypeVersion);
    LogEntry possibleTarget = (LogEntry) targetEntryMap.get(fromLogType);

    /*
     * If the entry is provisional, we won't be reading it in its entirety;
     * otherwise, we try to establish targetLogEntry.
     */
    if (!isProvisional) {
      targetLogEntry = possibleTarget;
    }

    /* Was the log entry an IN deletion? */
    if (LogEntryType.LOG_IN_DELETE_INFO.equals(fromLogType)) {
      lastEntryWasDelete = true;
    }

    if (LogEntryType.LOG_IN_DUPDELETE_INFO.equals(fromLogType)) {
      lastEntryWasDupDelete = true;
    }

    if (trackIds) {

      /*
       * Check if it's a db or txn id tracking entry. Note that these
       * entries do not overlap with targetLogEntry.
       */
      if (!isProvisional) {
        dbIdTrackingEntry = (LNLogEntry) dbIdTrackingMap.get(fromLogType);
        txnIdTrackingEntry = (LNLogEntry) txnIdTrackingMap.get(fromLogType);
      }

      /*
       * Determine nodeTrackingEntry, inTrackingEntry, fsTrackingEntry.
       * Note that these entries do overlap with targetLogEntry.
       */
      if (fromLogType.isNodeType()) {
        if (possibleTarget != null) {
          nodeTrackingEntry = (NodeLogEntry) possibleTarget;
        } else if (dbIdTrackingEntry != null) {
          nodeTrackingEntry = dbIdTrackingEntry;
        } else if (txnIdTrackingEntry != null) {
          nodeTrackingEntry = txnIdTrackingEntry;
        } else {
          nodeTrackingEntry = (NodeLogEntry) otherNodeTrackingMap.get(fromLogType);
          if (nodeTrackingEntry == null) {
            nodeTrackingEntry = (NodeLogEntry) fromLogType.getNewLogEntry();
            otherNodeTrackingMap.put(fromLogType, nodeTrackingEntry);
          }
        }
        if (nodeTrackingEntry instanceof INLogEntry) {
          inTrackingEntry = (INLogEntry) nodeTrackingEntry;
        }
        if (LogEntryType.LOG_FILESUMMARYLN.equals(fromLogType)) {
          fsTrackingEntry = (LNLogEntry) nodeTrackingEntry;
        }
      }

      /* Count all entries as new. */
      tracker.countNewLogEntry(
          getLastLsn(), fromLogType, LogManager.HEADER_BYTES + currentEntrySize);

      /*
       * Return true if this entry should be passed on to processEntry. If
       * we're tracking ids, return if this is a targeted entry or if it's
       * any kind of tracked entry or node.
       */
      return (targetLogEntry != null)
          || (dbIdTrackingEntry != null)
          || (txnIdTrackingEntry != null)
          || (nodeTrackingEntry != null);
    } else {

      /*
       * Return true if this entry should be passed on to processEntry. If
       * we're not tracking ids, only return true if it's a targeted
       * entry.
       */
      return (targetLogEntry != null);
    }
  }