001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal;
022:
023: import com.db4o.*;
024: import com.db4o.foundation.*;
025: import com.db4o.internal.ix.IndexTransaction;
026: import com.db4o.internal.slots.*;
027: import com.db4o.marshall.*;
028: import com.db4o.reflect.Reflector;
029:
030: /**
031: * @exclude
032: */
033: public abstract class Transaction {
034:
035: // contains DeleteInfo nodes
036: protected Tree _delete;
037:
038: private List4 _dirtyFieldIndexes;
039:
040: protected final Transaction _systemTransaction;
041:
042: /**
043: * This is the inside representation to operate against, the actual
044: * file-based ObjectContainerBase or the client. For all calls
045: * against this ObjectContainerBase the method signatures that take
046: * a transaction have to be used.
047: */
048: private final ObjectContainerBase _container;
049:
050: /**
051: * This is the outside representation to the user. This ObjectContainer
052: * should use this transaction as it's main user transation, so it also
053: * allows using the method signatures on ObjectContainer without a
054: * transaction.
055: */
056: private ObjectContainer _objectContainer;
057:
058: private List4 _transactionListeners;
059:
060: private final TransactionalReferenceSystem _referenceSystem;
061:
062: public Transaction(ObjectContainerBase container,
063: Transaction systemTransaction,
064: TransactionalReferenceSystem referenceSystem) {
065: _container = container;
066: _systemTransaction = systemTransaction;
067: _referenceSystem = referenceSystem;
068: }
069:
070: public void addDirtyFieldIndex(IndexTransaction indexTransaction) {
071: _dirtyFieldIndexes = new List4(_dirtyFieldIndexes,
072: indexTransaction);
073: }
074:
075: public final void checkSynchronization() {
076: if (Debug.checkSychronization) {
077: container()._lock.notify();
078: }
079: }
080:
081: public void addTransactionListener(TransactionListener listener) {
082: _transactionListeners = new List4(_transactionListeners,
083: listener);
084: }
085:
086: protected final void clearAll() {
087: clear();
088: _dirtyFieldIndexes = null;
089: _transactionListeners = null;
090: }
091:
092: protected abstract void clear();
093:
094: public void close(boolean rollbackOnClose) {
095: if (container() != null) {
096: checkSynchronization();
097: container().releaseSemaphores(this );
098: if (_referenceSystem != null) {
099: container().referenceSystemRegistry()
100: .removeReferenceSystem(_referenceSystem);
101: }
102: }
103: if (rollbackOnClose) {
104: rollback();
105: }
106: }
107:
108: public abstract void commit();
109:
110: protected void commit4FieldIndexes() {
111: if (_systemTransaction != null) {
112: _systemTransaction.commit4FieldIndexes();
113: }
114: if (_dirtyFieldIndexes != null) {
115: Iterator4 i = new Iterator4Impl(_dirtyFieldIndexes);
116: while (i.moveNext()) {
117: ((IndexTransaction) i.current()).commit();
118: }
119: }
120: }
121:
122: protected void commitTransactionListeners() {
123: checkSynchronization();
124: if (_transactionListeners != null) {
125: Iterator4 i = new Iterator4Impl(_transactionListeners);
126: while (i.moveNext()) {
127: ((TransactionListener) i.current()).preCommit();
128: }
129: _transactionListeners = null;
130: }
131: }
132:
133: public abstract boolean isDeleted(int id);
134:
135: protected boolean isSystemTransaction() {
136: return _systemTransaction == null;
137: }
138:
139: public boolean delete(ObjectReference ref, int id, int cascade) {
140: checkSynchronization();
141:
142: if (ref != null) {
143: if (!_container.flagForDelete(ref)) {
144: return false;
145: }
146: }
147:
148: if (DTrace.enabled) {
149: DTrace.TRANS_DELETE.log(id);
150: }
151:
152: DeleteInfo info = (DeleteInfo) TreeInt.find(_delete, id);
153: if (info == null) {
154: info = new DeleteInfo(id, ref, cascade);
155: _delete = Tree.add(_delete, info);
156: return true;
157: }
158: info._reference = ref;
159: if (cascade > info._cascade) {
160: info._cascade = cascade;
161: }
162: return true;
163: }
164:
165: public void dontDelete(int a_id) {
166: if (DTrace.enabled) {
167: DTrace.TRANS_DONT_DELETE.log(a_id);
168: }
169: if (_delete == null) {
170: return;
171: }
172: _delete = TreeInt.removeLike((TreeInt) _delete, a_id);
173: }
174:
175: void dontRemoveFromClassIndex(int a_yapClassID, int a_id) {
176: // If objects are deleted and rewritten during a cascade
177: // on delete, we dont want them to be gone.
178: checkSynchronization();
179: ClassMetadata yapClass = container().classMetadataForId(
180: a_yapClassID);
181: yapClass.index().add(this , a_id);
182: }
183:
184: public HardObjectReference getHardReferenceBySignature(
185: final long a_uuid, final byte[] a_signature) {
186: checkSynchronization();
187: return container().uUIDIndex()
188: .getHardObjectReferenceBySignature(this , a_uuid,
189: a_signature);
190: }
191:
192: public abstract void processDeletes();
193:
194: public ReferenceSystem referenceSystem() {
195: if (_referenceSystem != null) {
196: return _referenceSystem;
197: }
198: return parentTransaction().referenceSystem();
199: }
200:
201: public Reflector reflector() {
202: return container().reflector();
203: }
204:
205: public abstract void rollback();
206:
207: protected void rollbackFieldIndexes() {
208: if (_dirtyFieldIndexes != null) {
209: Iterator4 i = new Iterator4Impl(_dirtyFieldIndexes);
210: while (i.moveNext()) {
211: ((IndexTransaction) i.current()).rollback();
212: }
213: }
214: }
215:
216: protected void rollBackTransactionListeners() {
217: checkSynchronization();
218: if (_transactionListeners != null) {
219: Iterator4 i = new Iterator4Impl(_transactionListeners);
220: while (i.moveNext()) {
221: ((TransactionListener) i.current()).postRollback();
222: }
223: _transactionListeners = null;
224: }
225: }
226:
227: public final void setPointer(Pointer4 pointer) {
228: setPointer(pointer._id, pointer._slot);
229: }
230:
231: /**
232: * @param id
233: * @param slot
234: */
235: public void setPointer(int id, Slot slot) {
236: }
237:
238: /**
239: * @param id
240: * @param slot
241: */
242: public void slotDelete(int id, Slot slot) {
243: }
244:
245: /**
246: * @param id
247: * @param slot
248: */
249: public void slotFreeOnCommit(int id, Slot slot) {
250: }
251:
252: /**
253: * @param id
254: * @param slot
255: */
256: public void slotFreeOnRollback(int id, Slot slot) {
257: }
258:
259: /**
260: * @param id
261: * @param slot
262: * @param forFreespace
263: */
264: void slotFreeOnRollbackCommitSetPointer(int id, Slot slot,
265: boolean forFreespace) {
266: }
267:
268: /**
269: * @param id
270: * @param slot
271: */
272: void produceUpdateSlotChange(int id, Slot slot) {
273: }
274:
275: /** @param id */
276: public void slotFreePointerOnCommit(int id) {
277: }
278:
279: /**
280: * @param id
281: * @param slot
282: */
283: void slotFreePointerOnCommit(int id, Slot slot) {
284: }
285:
286: /** @param id */
287: public void slotFreePointerOnRollback(int id) {
288: }
289:
290: boolean supportsVirtualFields() {
291: return true;
292: }
293:
294: public Transaction systemTransaction() {
295: if (_systemTransaction != null) {
296: return _systemTransaction;
297: }
298: return this ;
299: }
300:
301: public String toString() {
302: return container().toString();
303: }
304:
305: public abstract void writeUpdateDeleteMembers(int id,
306: ClassMetadata clazz, int typeInfo, int cascade);
307:
308: public final ObjectContainerBase container() {
309: return _container;
310: }
311:
312: public Transaction parentTransaction() {
313: return _systemTransaction;
314: }
315:
316: public void rollbackReferenceSystem() {
317: referenceSystem().rollback();
318: }
319:
320: public void commitReferenceSystem() {
321: referenceSystem().commit();
322: }
323:
324: public void addNewReference(ObjectReference ref) {
325: referenceSystem().addNewReference(ref);
326: }
327:
328: public final Object objectForIdFromCache(int id) {
329: ObjectReference ref = referenceForId(id);
330: if (ref == null) {
331: return null;
332: }
333: Object candidate = ref.getObject();
334: if (candidate == null) {
335: removeReference(ref);
336: }
337: return candidate;
338: }
339:
340: public final ObjectReference referenceForId(int id) {
341: ObjectReference ref = referenceSystem().referenceForId(id);
342: if (ref != null) {
343: return ref;
344: }
345: if (parentTransaction() != null) {
346: return parentTransaction().referenceForId(id);
347: }
348: return null;
349: }
350:
351: public final ObjectReference referenceForObject(Object obj) {
352: ObjectReference ref = referenceSystem().referenceForObject(obj);
353: if (ref != null) {
354: return ref;
355: }
356: if (parentTransaction() != null) {
357: return parentTransaction().referenceForObject(obj);
358: }
359: return null;
360: }
361:
362: public final void removeReference(ObjectReference ref) {
363:
364: referenceSystem().removeReference(ref);
365:
366: // setting the ID to minus 1 ensures that the
367: // gc mechanism does not kill the new YapObject
368: ref.setID(-1);
369: Platform4.killYapRef(ref.getObjectReference());
370: }
371:
372: public final void removeObjectFromReferenceSystem(Object obj) {
373: ObjectReference ref = referenceForObject(obj);
374: if (ref != null) {
375: removeReference(ref);
376: }
377: }
378:
379: public void setOutSideRepresentation(ObjectContainer objectContainer) {
380: _objectContainer = objectContainer;
381: }
382:
383: public ObjectContainer objectContainer() {
384: if (_objectContainer != null) {
385: return _objectContainer;
386: }
387: return (ObjectContainer) _container;
388: }
389:
390: public Context context() {
391: return new Context() {
392: public ObjectContainer objectContainer() {
393: return Transaction.this .objectContainer();
394: }
395:
396: public Transaction transaction() {
397: return Transaction.this;
398: }
399: };
400: }
401:
402: }
|