001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: TrackedFileSummary.java,v 1.9.2.4 2008/01/07 15:14:08 cwl Exp $
007: */
008:
009: package com.sleepycat.je.cleaner;
010:
011: import com.sleepycat.je.dbi.MemoryBudget;
012:
013: /**
014: * Delta file summary info for a tracked file. Tracked files are managed by
015: * the UtilizationTracker.
016: *
017: * <p>The methods in this class for reading obsolete offsets may be used by
018: * multiple threads without synchronization even while another thread is adding
019: * offsets. This is possible because elements are never deleted from the
020: * lists. The thread adding obsolete offsets does so under the log write
021: * latch to prevent multiple threads from adding concurrently.</p>
022: */
023: public class TrackedFileSummary extends FileSummary {
024:
025: private UtilizationTracker tracker;
026: private long fileNum;
027: private OffsetList obsoleteOffsets;
028: private int memSize;
029: private boolean trackDetail;
030: private boolean allowFlush = true;
031:
032: /**
033: * Creates an empty tracked summary.
034: */
035: TrackedFileSummary(UtilizationTracker tracker, long fileNum,
036: boolean trackDetail) {
037: this .tracker = tracker;
038: this .fileNum = fileNum;
039: this .trackDetail = trackDetail;
040: }
041:
042: /**
043: * Returns whether this summary is allowed or prohibited from being flushed
044: * or evicted during cleaning. By default, flushing is allowed.
045: */
046: public boolean getAllowFlush() {
047: return allowFlush;
048: }
049:
050: /**
051: * Allows or prohibits this summary from being flushed or evicted during
052: * cleaning. By default, flushing is allowed.
053: */
054: void setAllowFlush(boolean allowFlush) {
055: this .allowFlush = allowFlush;
056: }
057:
058: /**
059: * Returns the file number being tracked.
060: */
061: public long getFileNumber() {
062: return fileNum;
063: }
064:
065: /**
066: * Return the total memory size for this object. We only bother to budget
067: * obsolete detail, not the overhead for this object, for two reasons:
068: * 1) The number of these objects is very small, and 2) unit tests disable
069: * detail tracking as a way to prevent budget adjustments here.
070: */
071: int getMemorySize() {
072: return memSize;
073: }
074:
075: /**
076: * Overrides reset for a tracked file, and is called when a FileSummaryLN
077: * is written to the log.
078: *
079: * <p>Must be called under the log write latch.</p>
080: */
081: public void reset() {
082:
083: obsoleteOffsets = null;
084:
085: tracker.resetFile(this );
086:
087: if (memSize > 0) {
088: updateMemoryBudget(0 - memSize);
089: }
090:
091: super .reset();
092: }
093:
094: /**
095: * Tracks the given offset as obsolete or non-obsolete.
096: *
097: * <p>Must be called under the log write latch.</p>
098: */
099: void trackObsolete(long offset) {
100:
101: if (!trackDetail) {
102: return;
103: }
104: int adjustMem = 0;
105: if (obsoleteOffsets == null) {
106: obsoleteOffsets = new OffsetList();
107: adjustMem += MemoryBudget.TFS_LIST_INITIAL_OVERHEAD;
108: }
109: if (obsoleteOffsets.add(offset, tracker.getEnvironment()
110: .isOpen())) {
111: adjustMem += MemoryBudget.TFS_LIST_SEGMENT_OVERHEAD;
112: }
113: if (adjustMem != 0) {
114: updateMemoryBudget(adjustMem);
115: }
116: }
117:
118: /**
119: * Adds the obsolete offsets as well as the totals of the given object.
120: */
121: void addTrackedSummary(TrackedFileSummary other) {
122:
123: /* Add the totals. */
124: add(other);
125:
126: /*
127: * Add the offsets and the memory used [#15505] by the other tracker.
128: * The memory budget has already been updated for the offsets to be
129: * added, so we only need to account for a possible difference of one
130: * segment when we merge them.
131: */
132: memSize += other.memSize;
133: if (other.obsoleteOffsets != null) {
134: if (obsoleteOffsets != null) {
135: /* Merge the other offsets into our list. */
136: if (obsoleteOffsets.merge(other.obsoleteOffsets)) {
137: /* There is one segment less as a result of the merge. */
138: updateMemoryBudget(-MemoryBudget.TFS_LIST_SEGMENT_OVERHEAD);
139: }
140: } else {
141: /* Adopt the other's offsets as our own. */
142: obsoleteOffsets = other.obsoleteOffsets;
143: }
144: }
145: }
146:
147: /**
148: * Returns obsolete offsets as an array of longs, or null if none.
149: */
150: public long[] getObsoleteOffsets() {
151:
152: if (obsoleteOffsets != null) {
153: return obsoleteOffsets.toArray();
154: } else {
155: return null;
156: }
157: }
158:
159: /**
160: * Returns whether the given offset is present in the tracked offsets.
161: * This does not indicate whether the offset is obsolete in general, but
162: * only if it is known to be obsolete in this version of the tracked
163: * information.
164: */
165: boolean containsObsoleteOffset(long offset) {
166:
167: if (obsoleteOffsets != null) {
168: return obsoleteOffsets.contains(offset);
169: } else {
170: return false;
171: }
172: }
173:
174: private void updateMemoryBudget(int delta) {
175: memSize += delta;
176: tracker.getEnvironment().getMemoryBudget()
177: .updateMiscMemoryUsage(delta);
178: }
179: }
|