001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: FileSummary.java,v 1.18.2.2 2008/01/07 15:14:08 cwl Exp $
007: */
008:
009: package com.sleepycat.je.cleaner;
010:
011: import java.nio.ByteBuffer;
012:
013: import com.sleepycat.je.DatabaseException;
014: import com.sleepycat.je.log.Loggable;
015: import com.sleepycat.je.log.LogUtils;
016:
017: public class FileSummary implements Loggable {
018:
019: /* Persistent fields. */
020: public int totalCount; // Total # of log entries
021: public int totalSize; // Total bytes in log file
022: public int totalINCount; // Number of IN log entries
023: public int totalINSize; // Byte size of IN log entries
024: public int totalLNCount; // Number of LN log entries
025: public int totalLNSize; // Byte size of LN log entries
026: public int obsoleteINCount; // Number of obsolete IN log entries
027: public int obsoleteLNCount; // Number of obsolete LN log entries
028: public int obsoleteLNSize; // Byte size of obsolete LN log entries
029: public int obsoleteLNSizeCounted; // Number obsolete LNs with size counted
030:
031: /**
032: * Creates an empty summary.
033: */
034: public FileSummary() {
035: }
036:
037: /**
038: * Returns whether this summary contains any non-zero totals.
039: */
040: public boolean isEmpty() {
041:
042: return totalCount == 0 && totalSize == 0
043: && obsoleteINCount == 0 && obsoleteLNCount == 0;
044: }
045:
046: /**
047: * Returns the approximate byte size of all obsolete LN entries. In
048: * FileSummaryLN version 3 and greater the exact tracked size is used.
049: */
050: public int getObsoleteLNSize() {
051:
052: if (totalLNCount == 0) {
053: return 0;
054: }
055:
056: /*
057: * Use the tracked obsolete size for all entries for which the size was
058: * counted, plus the average size for all obsolete entries whose size
059: * was not counted.
060: */
061: int obsolete = obsoleteLNSize;
062: int notCounted = obsoleteLNCount - obsoleteLNSizeCounted;
063: if (notCounted > 0) {
064: /* Use long arithmetic. */
065: long total = totalLNSize;
066: /* Scale by 255 to reduce integer truncation error. */
067: total <<= 8;
068: long avgSizePerLN = total / totalLNCount;
069: obsolete += (int) ((notCounted * avgSizePerLN) >> 8);
070: }
071: return obsolete;
072: }
073:
074: /**
075: * Returns the approximate byte size of all obsolete IN entries.
076: */
077: public int getObsoleteINSize() {
078:
079: if (totalINCount == 0) {
080: return 0;
081: }
082: /* Use long arithmetic. */
083: long size = totalINSize;
084: /* Scale by 255 to reduce integer truncation error. */
085: size <<= 8;
086: long avgSizePerIN = size / totalINCount;
087: return (int) ((obsoleteINCount * avgSizePerIN) >> 8);
088: }
089:
090: /**
091: * Returns an estimate of the total bytes that are obsolete.
092: */
093: public int getObsoleteSize() throws DatabaseException {
094:
095: if (totalSize > 0) {
096: /* Leftover (non-IN non-LN) space is considered obsolete. */
097: int leftoverSize = totalSize - (totalINSize + totalLNSize);
098: int obsoleteSize = getObsoleteLNSize()
099: + getObsoleteINSize() + leftoverSize;
100:
101: /*
102: * Don't report more obsolete bytes than the total. We may
103: * calculate more than the total because of (intentional)
104: * double-counting during recovery.
105: */
106: if (obsoleteSize > totalSize) {
107: obsoleteSize = totalSize;
108: }
109: return obsoleteSize;
110: } else {
111: return 0;
112: }
113: }
114:
115: /**
116: * Returns the total number of entries counted. This value is guaranted
117: * to increase whenever the tracking information about a file changes. It
118: * is used a key discriminator for FileSummaryLN records.
119: */
120: public int getEntriesCounted() {
121: return totalCount + obsoleteLNCount + obsoleteINCount;
122: }
123:
124: /**
125: * Returns the number of non-obsolete LN and IN entries.
126: */
127: public int getNonObsoleteCount() {
128: return totalLNCount + totalINCount - obsoleteLNCount
129: - obsoleteINCount;
130: }
131:
132: /**
133: * Reset all totals to zero.
134: */
135: public void reset() {
136:
137: totalCount = 0;
138: totalSize = 0;
139: totalINCount = 0;
140: totalINSize = 0;
141: totalLNCount = 0;
142: totalLNSize = 0;
143: obsoleteINCount = 0;
144: obsoleteLNCount = 0;
145: obsoleteLNSize = 0;
146: obsoleteLNSizeCounted = 0;
147: }
148:
149: /**
150: * Add the totals of the given summary object to the totals of this object.
151: */
152: public void add(FileSummary o) {
153:
154: totalCount += o.totalCount;
155: totalSize += o.totalSize;
156: totalINCount += o.totalINCount;
157: totalINSize += o.totalINSize;
158: totalLNCount += o.totalLNCount;
159: totalLNSize += o.totalLNSize;
160: obsoleteINCount += o.obsoleteINCount;
161: obsoleteLNCount += o.obsoleteLNCount;
162: obsoleteLNSize += o.obsoleteLNSize;
163: obsoleteLNSizeCounted += o.obsoleteLNSizeCounted;
164: }
165:
166: /**
167: * @see Loggable#getLogSize
168: */
169: public int getLogSize() {
170:
171: return 10 * LogUtils.getIntLogSize();
172: }
173:
174: /**
175: * @see Loggable#writeToLog
176: */
177: public void writeToLog(ByteBuffer buf) {
178:
179: LogUtils.writeInt(buf, totalCount);
180: LogUtils.writeInt(buf, totalSize);
181: LogUtils.writeInt(buf, totalINCount);
182: LogUtils.writeInt(buf, totalINSize);
183: LogUtils.writeInt(buf, totalLNCount);
184: LogUtils.writeInt(buf, totalLNSize);
185: LogUtils.writeInt(buf, obsoleteINCount);
186: LogUtils.writeInt(buf, obsoleteLNCount);
187: LogUtils.writeInt(buf, obsoleteLNSize);
188: LogUtils.writeInt(buf, obsoleteLNSizeCounted);
189: }
190:
191: /**
192: * @see Loggable#readFromLog
193: */
194: public void readFromLog(ByteBuffer buf, byte entryTypeVersion) {
195:
196: totalCount = LogUtils.readInt(buf);
197: totalSize = LogUtils.readInt(buf);
198: totalINCount = LogUtils.readInt(buf);
199: totalINSize = LogUtils.readInt(buf);
200: totalLNCount = LogUtils.readInt(buf);
201: totalLNSize = LogUtils.readInt(buf);
202: obsoleteINCount = LogUtils.readInt(buf);
203: if (obsoleteINCount == -1) {
204:
205: /*
206: * If INs were not counted in an older log file written by 1.5.3 or
207: * earlier, consider all INs to be obsolete. This causes the file
208: * to be cleaned, and then IN counting will be accurate.
209: */
210: obsoleteINCount = totalINCount;
211: }
212: obsoleteLNCount = LogUtils.readInt(buf);
213:
214: /*
215: * obsoleteLNSize and obsoleteLNSizeCounted were added in FileSummaryLN
216: * version 3.
217: */
218: if (entryTypeVersion >= 3) {
219: obsoleteLNSize = LogUtils.readInt(buf);
220: obsoleteLNSizeCounted = LogUtils.readInt(buf);
221: } else {
222: obsoleteLNSize = 0;
223: obsoleteLNSizeCounted = 0;
224: }
225: }
226:
227: /**
228: * @see Loggable#dumpLog
229: */
230: public void dumpLog(StringBuffer buf, boolean verbose) {
231:
232: buf.append("<summary totalCount=\"");
233: buf.append(totalCount);
234: buf.append("\" totalSize=\"");
235: buf.append(totalSize);
236: buf.append("\" totalINCount=\"");
237: buf.append(totalINCount);
238: buf.append("\" totalINSize=\"");
239: buf.append(totalINSize);
240: buf.append("\" totalLNCount=\"");
241: buf.append(totalLNCount);
242: buf.append("\" totalLNSize=\"");
243: buf.append(totalLNSize);
244: buf.append("\" obsoleteINCount=\"");
245: buf.append(obsoleteINCount);
246: buf.append("\" obsoleteLNCount=\"");
247: buf.append(obsoleteLNCount);
248: buf.append("\" obsoleteLNSize=\"");
249: buf.append(obsoleteLNSize);
250: buf.append("\" obsoleteLNSizeCounted=\"");
251: buf.append(obsoleteLNSizeCounted);
252: buf.append("\"/>");
253: }
254:
255: /**
256: * Never called.
257: * @see Loggable#getTransactionId
258: */
259: public long getTransactionId() {
260: return -1;
261: }
262:
263: public String toString() {
264: StringBuffer buf = new StringBuffer();
265: dumpLog(buf, true);
266: return buf.toString();
267: }
268: }
|