/** This reader collects stats about the log entry. */ @Override protected boolean processEntry(ByteBuffer entryBuffer) { byte currentType = currentEntryHeader.getType(); int itemSize = currentEntryHeader.getItemSize(); int headerSize = currentEntryHeader.getSize(); /* * Record various stats based on the entry header, then move the buffer * forward to skip ahead. */ LogEntryType lastEntryType = LogEntryType.findType(currentType); int nextEntryPosition = entryBuffer.position() + itemSize; /* * Get the info object for it, if this is the first time it's seen, * create an info object and insert it. */ EntryInfo info = entryInfoMap.get(lastEntryType); if (info == null) { info = new EntryInfo(); entryInfoMap.put(lastEntryType, info); } /* Update counts. */ info.count++; totalCount++; if (currentEntryHeader.getProvisional() == Provisional.YES) { info.provisionalCount++; } int size = itemSize + headerSize; info.totalBytes += size; info.headerBytes += headerSize; totalLogBytes += size; if ((info.minBytes == 0) || (info.minBytes > size)) { info.minBytes = size; } if (info.maxBytes < size) { info.maxBytes = size; } if (verbose) { if (firstLsnRead == DbLsn.NULL_LSN) { firstLsnRead = getLastLsn(); } if (currentType == LogEntryType.LOG_CKPT_END.getTypeNum()) { /* Start counting a new interval. */ ckptCounter.endCkptLsn = getLastLsn(); ckptCounter = new CheckpointCounter(); ckptList.add(ckptCounter); } else { ckptCounter.increment(this, currentType); } } if (lastEntryType.isUserLNType()) { /* Read the entry into the ByteBuffer. */ LNLogEntry<?> entry = (LNLogEntry<?>) lastEntryType.getSharedLogEntry(); entry.readEntry(envImpl, currentEntryHeader, entryBuffer); /* * The getUnconvertedXxx methods are used because we don't have a * DatabaseImpl for calling LNLogEntry.postFetchInit, and we can * tolerate statistics that use the old duplicates format. */ int keyLen = entry.getUnconvertedKeyLength(); realTotalKeyBytes += keyLen; if (!entry.isDeleted()) { int dataLen = entry.getUnconvertedDataLength(); realTotalDataBytes += dataLen; } } entryBuffer.position(nextEntryPosition); return true; }
/** * 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; }