001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Core License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: WizardObjectContainer.java,v 1.2 2002/06/08 00:49:39 mediumnet Exp $
008:
009: package org.ozoneDB.core.wizardStore;
010:
011: import java.io.*;
012: import org.ozoneDB.DxLib.*;
013: import org.ozoneDB.*;
014: import org.ozoneDB.core.*;
015: import org.ozoneDB.util.*;
016:
017: /**
018: * The "Wizard" implementation of the ObjectContainer interface. Much of the
019: * lock functionality is implemented in the Cluster class.
020: *
021: * Note: only the join/commit/abort methods are synchronized. All other methods
022: * are guaranteed to run exclusively through the explicite locks
023: *
024: *
025: * @author <a href="http://www.softwarebuero.de/">SMB</a>
026: * @author <A HREF="http://www.medium.net/">Medium.net</A>
027: * @version $Revision: 1.2 $Date: 2002/06/08 00:49:39 $
028: */
029: public final class WizardObjectContainer extends
030: AbstractObjectContainer implements Externalizable {
031:
032: protected final static long serialVersionUID = 1L;
033: protected final static byte subSerialVersionUID = 2;
034:
035: protected Cluster cluster;
036:
037: /**
038: * The currently commited target object of the container.
039: */
040: protected OzoneCompatible target;
041:
042: protected ObjectID objID;
043:
044: protected String name;
045:
046: protected transient int invokeCount;
047:
048: protected long modTime;
049:
050: /**
051: The garbage collection level of this ObjectContainer. This number is compared to the
052: currentGarbageCollectionLevel of the database.
053: Is this number smaller, then this object may be reachable.
054: Is it equal, then this object is reachable, but it's descendants are not yet considered.
055: Is it greater, then this object is reachable and this object is processed, it's descendants have been considered.
056: At the end of the mark-process, every object which still is not reachable must be unreachable, so at this and,
057: a smaller garbageCollectionLevel than currentGarbageCollectionLevel means that this object may be deleted.
058: */
059: protected int garbageCollectionLevel;
060:
061: /**
062: * Constructor for object serialization via Externalizable.
063: */
064: public WizardObjectContainer() {
065: }
066:
067: public WizardObjectContainer(ObjectID _objID) {
068: state = STATE_CREATED;
069: objID = _objID;
070: }
071:
072: protected void setCluster(Cluster cluster) {
073: Cluster oldCluster = this .cluster;
074:
075: this .cluster = cluster;
076: if (true) {
077: if (cluster == null) {
078:
079: if (false) {
080: System.out.println(this + ": setCluster(" + cluster
081: + ").");
082: }
083:
084: if (false && getCluster().env.logWriter
085: .hasTarget(LogWriter.DEBUG3)) {
086: getCluster().env.logWriter.newEntry(this ,
087: "setCluster(null).", LogWriter.DEBUG2);
088: }
089: }
090: }
091: }
092:
093: public/*protected*/Cluster getCluster() {
094: return cluster;
095: }
096:
097: public long modTime() {
098: return getCluster().modTime();
099: }
100:
101: protected boolean isDeleted() {
102: return (state() & ObjectContainer.STATE_DELETED) > 0;
103: }
104:
105: protected boolean isCreated() {
106: return (state() & ObjectContainer.STATE_CREATED) > 0;
107: }
108:
109: /**
110: * Returns the Class for the target object. This method is used by
111: * AbstractObjectContainer.
112: */
113: public Class targetClass() {
114: try {
115: return target.getClass();
116: } catch (NullPointerException e) {
117: if (target != null) {
118: throw e;
119: } else {
120: throw new NullPointerException(this + ": getCluster()="
121: + getCluster() + ": target=" + target + ".");
122: }
123: }
124: }
125:
126: public synchronized void setTarget(OzoneCompatible _target) {
127: if (target != null) {
128: target.setContainer(null);
129: }
130: target = _target;
131: target.setContainer(this );
132: }
133:
134: public OzoneCompatible target() {
135: return target;
136: }
137:
138: public void touch() {
139: getCluster().touch();
140: }
141:
142: public Lock lock() {
143: return getCluster().lock;
144: }
145:
146: public void updateLockLevel(Transaction ta) throws Exception {
147: if (getCluster().env.logWriter.hasTarget(LogWriter.DEBUG3)) {
148: getCluster().env.logWriter.newEntry(this ,
149: "upgradeLockLevel(): ", LogWriter.DEBUG3);
150: }
151: getCluster().updateLockLevel(ta);
152: }
153:
154: public synchronized void notifyAllTAs(Transaction ta) {
155: getCluster().lock.notifyAll();
156: }
157:
158: public Permissions permissions() {
159: return getCluster().permissions;
160: }
161:
162: public int lockLevel(Transaction ta) {
163: return getCluster().lock.level(ta);
164: }
165:
166: public boolean isInvoked() {
167: // for performance reasons we assume that the specified transaction
168: // is the locking transaction
169: return invokeCount > 0;
170: }
171:
172: public Object invokeTarget(Env env, String methodName, String sig,
173: Object[] args) throws Exception {
174: if (getCluster().env.logWriter.hasTarget(LogWriter.DEBUG3)) {
175: getCluster().env.logWriter.newEntry(this ,
176: "invokeTarget(): ", LogWriter.DEBUG3);
177: }
178: invokeCount++;
179: Object result = super .invokeTarget(env, methodName, sig, args);
180: invokeCount--;
181: return result;
182: }
183:
184: public void deleteTarget() {
185: if (false && getCluster().env.logWriter
186: .hasTarget(LogWriter.DEBUG3)) {
187: getCluster().env.logWriter.newEntry(this ,
188: "deleteTarget(): ", LogWriter.DEBUG3);
189: }
190: raiseState(STATE_DELETED);
191: }
192:
193: public synchronized void nameTarget(String _name) {
194: if (false && getCluster().env.logWriter
195: .hasTarget(LogWriter.DEBUG3)) {
196: getCluster().env.logWriter.newEntry(this , "nameTarget(): ",
197: LogWriter.DEBUG3);
198: }
199: name = _name;
200: }
201:
202: public DxCollection allLockers() {
203: return getCluster().allLockers();
204: }
205:
206: public boolean equals(Object obj) {
207: if (obj != null && obj instanceof WizardObjectContainer) {
208: WizardObjectContainer rhs = (WizardObjectContainer) obj;
209: return objID.equals(rhs.objID);
210: }
211: return false;
212: }
213:
214: public ObjectID id() {
215: return objID;
216: }
217:
218: public String name() {
219: return name;
220: }
221:
222: public void setName(String _name) {
223: name = _name;
224: }
225:
226: public final void writeExternal(ObjectOutput out)
227: throws IOException {
228: // System.out.println ("container.writeExternal()...");
229: out.writeByte(subSerialVersionUID);
230: out.writeObject(target);
231: // out.writeObject (objID);
232: out.writeLong(objID.value());
233: if (name == null) {
234: out.writeByte(0);
235: } else {
236: out.writeByte(1);
237: out.writeUTF(name);
238: }
239: out.writeByte((byte) state);
240: out.writeInt(garbageCollectionLevel);
241: }
242:
243: public final void readExternal(ObjectInput in) throws IOException,
244: ClassNotFoundException {
245: // System.out.println ("container.readExternal()...");
246: byte streamVersion = in.readByte();
247: target = (OzoneCompatible) in.readObject();
248: if (target != null) {
249: target.setContainer(this );
250: }
251: // objID = (ObjectID)in.readObject();
252: objID = new ObjectID(in.readLong());
253: name = null;
254: if (in.readByte() != 0) {
255: name = in.readUTF();
256: }
257: state = (int) in.readByte();
258: if (streamVersion >= 2) {
259: garbageCollectionLevel = in.readInt();
260: } else {
261: garbageCollectionLevel = 0;
262: }
263: }
264:
265: /**
266: Ensures that the garbageCollectionLevel is at least the given currentGarbageCollectionLevel.
267: The return value is meaningful if the supplied newGarbageCollectionLevel is the currentGarbageCollectionLevel
268:
269: @return
270: <=0 if this object still has to be processed.
271: This is the case if it belongs to the surelyReachable set but not to the processedReachable set
272: > otherwise
273:
274: <0 if this object has been updated
275: =0 if this object has not been updated, it is surelyReachable
276: >0 if this object has not been updated, it is processedReachable
277: */
278: public int ensureGarbageCollectionLevel(
279: int newGarbageCollectionLevel) {
280: int difference = this .garbageCollectionLevel
281: - newGarbageCollectionLevel;
282:
283: if (difference < 0) { // This object's garbageCollectionLevel must be updated
284: this .garbageCollectionLevel = newGarbageCollectionLevel;
285: touch();
286: }
287:
288: return difference;
289: }
290:
291: /**
292: Returns the garbageCollectionLevel this ObjectContainer has reached due to (not) calling {@link #ensureGarbageCollectionLevel}.
293: */
294: public int getGarbageCollectionLevel() {
295: return garbageCollectionLevel;
296: }
297:
298: /**
299: Pins this ObjectContainer.
300: Every caller of this method must pair this call with a call to {@link #unpin}.
301: An ObjectContainer remains in main memory at least as long as it is pinned.
302: */
303: public void pin() {
304: getCluster().pin();
305: }
306:
307: /**
308: Unpins this ObjectContainer.
309: This method must be called exactly once for every call to {@link #pin}.
310: */
311: public void unpin() {
312: getCluster().unpin();
313: }
314:
315: /**
316: Returns wether this ObjectContainer is pinned.
317: */
318: public boolean isPinned() {
319: return getCluster().isPinned();
320: }
321:
322: public boolean hasSameClusterAs(WizardObjectContainer container) {
323: return container.getCluster() == getCluster();
324: }
325:
326: public String toString() {
327: return "WizardObjectContainer[target=" + target + "]";
328: }
329: }
|