001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2006 Oracle. All rights reserved.
005: *
006: * $Id: VerifyUtils.java,v 1.8.2.2 2007/11/20 13:32:27 cwl Exp $
007: */
008:
009: package com.sleepycat.je.cleaner;
010:
011: import java.io.PrintStream;
012: import java.util.ArrayList;
013: import java.util.HashSet;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Set;
017:
018: import com.sleepycat.je.Database;
019: import com.sleepycat.je.DatabaseException;
020: import com.sleepycat.je.DbInternal;
021: import com.sleepycat.je.dbi.DatabaseImpl;
022: import com.sleepycat.je.dbi.SortedLSNTreeWalker;
023: import com.sleepycat.je.dbi.SortedLSNTreeWalker.TreeNodeProcessor;
024: import com.sleepycat.je.log.LogEntryType;
025: import com.sleepycat.je.tree.Node;
026: import com.sleepycat.je.tree.LN;
027: import com.sleepycat.je.utilint.DbLsn;
028:
029: /**
030: * Verify cleaner data structures
031: */
032: public class VerifyUtils {
033:
034: private static final boolean DEBUG = false;
035:
036: /**
037: * Compare the LSNs referenced by a given Database to the lsns held
038: * in the utilization profile. Assumes that the database and
039: * environment is quiescent, and that there is no current cleaner
040: * activity.
041: */
042: public static void checkLsns(Database db) throws DatabaseException {
043: checkLsns(DbInternal.dbGetDatabaseImpl(db), System.out);
044: }
045:
046: /**
047: * Compare the lsns referenced by a given Database to the lsns held
048: * in the utilization profile. Assumes that the database and
049: * environment is quiescent, and that there is no current cleaner
050: * activity.
051: */
052: public static void checkLsns(DatabaseImpl dbImpl, PrintStream out)
053: throws DatabaseException {
054:
055: /* Get all the LSNs in the database. */
056: GatherLSNs gatherLsns = new GatherLSNs();
057: long rootLsn = dbImpl.getTree().getRootLsn();
058: List savedExceptions = new ArrayList();
059:
060: SortedLSNTreeWalker walker = new SortedLSNTreeWalker(dbImpl,
061: false, // don't remove from INList
062: false, // don't set db state
063: rootLsn, gatherLsns, savedExceptions, null);
064: walker.walk();
065:
066: /* Print out any exceptions seen during the walk. */
067: if (savedExceptions.size() > 0) {
068: out.println(savedExceptions.size()
069: + " problems seen during tree walk for checkLsns");
070: Iterator iter = savedExceptions.iterator();
071: while (iter.hasNext()) {
072: Exception e = (Exception) iter.next();
073: out.println(" " + e);
074: }
075: }
076:
077: Set lsnsInTree = gatherLsns.getLsns();
078: lsnsInTree.add(new Long(rootLsn));
079:
080: /* Get all the files used by this database. */
081: Iterator iter = lsnsInTree.iterator();
082: Set fileNums = new HashSet();
083:
084: while (iter.hasNext()) {
085: long lsn = ((Long) iter.next()).longValue();
086: fileNums.add(new Long(DbLsn.getFileNumber(lsn)));
087: }
088:
089: /* Gather up the obsolete lsns in these file summary lns */
090: iter = fileNums.iterator();
091: Set obsoleteLsns = new HashSet();
092: UtilizationProfile profile = dbImpl.getDbEnvironment()
093: .getUtilizationProfile();
094:
095: while (iter.hasNext()) {
096: Long fileNum = (Long) iter.next();
097:
098: PackedOffsets obsoleteOffsets = new PackedOffsets();
099: TrackedFileSummary tfs = profile.getObsoleteDetail(fileNum,
100: obsoleteOffsets, false /* logUpdate */);
101: PackedOffsets.Iterator obsoleteIter = obsoleteOffsets
102: .iterator();
103: while (obsoleteIter.hasNext()) {
104: long offset = obsoleteIter.next();
105: Long oneLsn = new Long(DbLsn.makeLsn(fileNum
106: .longValue(), offset));
107: obsoleteLsns.add(oneLsn);
108: if (DEBUG) {
109: out.println("Adding 0x"
110: + Long.toHexString(oneLsn.longValue()));
111: }
112: }
113: }
114:
115: /* Check than none the lsns in the tree is in the UP. */
116: boolean error = false;
117: iter = lsnsInTree.iterator();
118: while (iter.hasNext()) {
119: Long lsn = (Long) iter.next();
120: if (obsoleteLsns.contains(lsn)) {
121: out.println("Obsolete LSN set contains valid LSN "
122: + DbLsn.getNoFormatString(lsn.longValue()));
123: error = true;
124: }
125: }
126:
127: /*
128: * Check that none of the lsns in the file summary ln is in the
129: * tree.
130: */
131: iter = obsoleteLsns.iterator();
132: while (iter.hasNext()) {
133: Long lsn = (Long) iter.next();
134: if (lsnsInTree.contains(lsn)) {
135: out.println("Tree contains obsolete LSN "
136: + DbLsn.getNoFormatString(lsn.longValue()));
137: error = true;
138: }
139: }
140:
141: if (error) {
142: throw new DatabaseException("Lsn mismatch");
143: }
144:
145: if (savedExceptions.size() > 0) {
146: throw new DatabaseException("Sorted LSN Walk problem");
147: }
148: }
149:
150: private static class GatherLSNs implements TreeNodeProcessor {
151: private Set lsns = new HashSet();
152:
153: public void processLSN(long childLSN, LogEntryType childType,
154: Node ignore, byte[] ignore2) throws DatabaseException {
155:
156: lsns.add(new Long(childLSN));
157: }
158:
159: /* ignore */
160: public void processDirtyDeletedLN(long childLsn, LN ln,
161: byte[] lnKey) throws DatabaseException {
162: }
163:
164: /* ignore */
165: public void processDupCount(long ignore) {
166: }
167:
168: public Set getLsns() {
169: return lsns;
170: }
171: }
172: }
|