예제 #1
0
  /** @see LN#writeToLog */
  public void writeToLog(ByteBuffer logBuffer) {

    /*
     * Add the tracked (live) summary to the base summary before writing it
     * to the log, and reset the tracked summary.  Do this even when
     * deleting the LN, so that the tracked summary is cleared.
     */
    if (trackedSummary != null) {

      baseSummary.add(trackedSummary);

      if (!isDeleted()) {
        getOffsets();
      }

      /* Reset the totals to zero and clear the tracked offsets. */
      trackedSummary.reset();
    }

    super.writeToLog(logBuffer);

    if (!isDeleted()) {
      baseSummary.writeToLog(logBuffer);
      obsoleteOffsets.writeToLog(logBuffer);
    }
  }
예제 #2
0
 /** If tracked offsets may be present, get them so they are ready to be written to the log. */
 private void getOffsets() {
   if (needOffsets) {
     long[] offsets = trackedSummary.getObsoleteOffsets();
     if (offsets != null) {
       int oldSize = obsoleteOffsets.getExtraMemorySize();
       obsoleteOffsets.pack(offsets);
       int newSize = obsoleteOffsets.getExtraMemorySize();
       memBudget.updateTreeMemoryUsage(newSize - oldSize);
     }
     needOffsets = false;
   }
 }
예제 #3
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;
  }