KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > Transaction


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

21 package com.db4o;
22
23 import com.db4o.foundation.*;
24 import com.db4o.inside.ix.IndexTransaction;
25 import com.db4o.inside.marshall.ObjectHeader;
26 import com.db4o.reflect.Reflector;
27
28 /**
29  * @exclude
30  */

31 public abstract class Transaction {
32
33     protected int i_address; // only used to pass address to Thread
34

35     protected final byte[] _pointerBuffer = new byte[YapConst.POINTER_LENGTH];
36
37     // contains DeleteInfo nodes
38
public Tree i_delete; // public for .NET conversion
39

40     private List4 i_dirtyFieldIndexes;
41     
42     public final YapFile i_file;
43
44     final Transaction i_parentTransaction;
45
46     protected final YapWriter i_pointerIo;
47
48     private final YapStream i_stream;
49     
50     private List4 i_transactionListeners;
51     
52     protected Tree i_writtenUpdateDeletedMembers;
53     
54     // TODO: join _dirtyBTree and _enlistedIndices
55
private final Collection4 _participants = new Collection4();
56
57     public Transaction(YapStream a_stream, Transaction a_parent) {
58         i_stream = a_stream;
59         i_file = (a_stream instanceof YapFile) ? (YapFile) a_stream : null;
60         i_parentTransaction = a_parent;
61         i_pointerIo = new YapWriter(this, YapConst.POINTER_LENGTH);
62     }
63
64     public void addDirtyFieldIndex(IndexTransaction a_xft) {
65         i_dirtyFieldIndexes = new List4(i_dirtyFieldIndexes, a_xft);
66     }
67
68     public final void checkSynchronization() {
69         if(Debug.checkSychronization){
70             stream().i_lock.notify();
71         }
72     }
73
74     public void addTransactionListener(TransactionListener a_listener) {
75         i_transactionListeners = new List4(i_transactionListeners, a_listener);
76     }
77     
78     protected void clearAll() {
79         i_dirtyFieldIndexes = null;
80         i_transactionListeners = null;
81         disposeParticipants();
82         _participants.clear();
83     }
84
85     private void disposeParticipants() {
86         Iterator4 iterator = _participants.iterator();
87         while (iterator.moveNext()) {
88             ((TransactionParticipant)iterator.current()).dispose(this);
89         }
90     }
91
92     public void close(boolean a_rollbackOnClose) {
93         try {
94             if (stream() != null) {
95                 checkSynchronization();
96                 stream().releaseSemaphores(this);
97             }
98         } catch (Exception JavaDoc e) {
99             if (Debug.atHome) {
100                 e.printStackTrace();
101             }
102         }
103         if (a_rollbackOnClose) {
104             try {
105                 rollback();
106             } catch (Exception JavaDoc e) {
107                 if (Debug.atHome) {
108                     e.printStackTrace();
109                 }
110             }
111         }
112     }
113
114     public void commit() {
115         synchronized (stream().i_lock) {
116             i_file.freeSpaceBeginCommit();
117             commitExceptForFreespace();
118             i_file.freeSpaceEndCommit();
119         }
120     }
121
122     private void commitExceptForFreespace(){
123         
124         if(DTrace.enabled){
125             boolean systemTrans = (i_parentTransaction == null);
126             DTrace.TRANS_COMMIT.logInfo( "server == " + stream().isServer() + ", systemtrans == " + systemTrans);
127         }
128         
129         commit2Listeners();
130         
131         commit3Stream();
132         
133         commit4FieldIndexes();
134         
135         commit5Participants();
136         
137         stream().writeDirty();
138         
139         commit6WriteChanges();
140         
141         freeOnCommit();
142         
143         commit7ClearAll();
144     }
145     
146     protected void freeOnCommit() {
147     }
148
149     protected void commit6WriteChanges() {
150     }
151     
152     private void commit7ClearAll(){
153         commit7ParentClearAll();
154         clearAll();
155     }
156
157     private void commit7ParentClearAll() {
158         if(i_parentTransaction != null){
159             i_parentTransaction.commit7ClearAll();
160         }
161     }
162
163     private void commit2Listeners(){
164         commit2ParentListeners();
165         commitTransactionListeners();
166     }
167
168     private void commit2ParentListeners() {
169         if (i_parentTransaction != null) {
170             i_parentTransaction.commit2Listeners();
171         }
172     }
173     
174     private void commit3Stream(){
175         stream().checkNeededUpdates();
176         stream().writeDirty();
177         stream().classCollection().write(stream().getSystemTransaction());
178     }
179     
180     private void commit4FieldIndexes(){
181         if(i_parentTransaction != null){
182             i_parentTransaction.commit4FieldIndexes();
183         }
184         if (i_dirtyFieldIndexes != null) {
185             Iterator4 i = new Iterator4Impl(i_dirtyFieldIndexes);
186             while (i.moveNext()) {
187                 ((IndexTransaction) i.current()).commit();
188             }
189         }
190     }
191     
192     private void commit5Participants() {
193         if (i_parentTransaction != null) {
194             i_parentTransaction.commit5Participants();
195         }
196         
197         Iterator4 iterator = _participants.iterator();
198         while (iterator.moveNext()) {
199             ((TransactionParticipant)iterator.current()).commit(this);
200         }
201     }
202     
203     protected void commitTransactionListeners() {
204         checkSynchronization();
205         if (i_transactionListeners != null) {
206             Iterator4 i = new Iterator4Impl(i_transactionListeners);
207             while (i.moveNext()) {
208                 ((TransactionListener) i.current()).preCommit();
209             }
210             i_transactionListeners = null;
211         }
212     }
213     
214     public abstract boolean isDeleted(int id);
215
216     public boolean delete(YapObject ref, int id, int cascade) {
217         checkSynchronization();
218         
219         if(ref != null){
220             if(! i_stream.flagForDelete(ref)){
221                 return false;
222             }
223         }
224         
225         if(isDeleted(id)){
226             return false;
227         }
228         
229         if(DTrace.enabled){
230             DTrace.TRANS_DELETE.log(id);
231         }
232         
233         DeleteInfo info = (DeleteInfo) TreeInt.find(i_delete, id);
234         if(info == null){
235             info = new DeleteInfo(id, ref, cascade);
236             i_delete = Tree.add(i_delete, info);
237             return true;
238         }
239         info._reference = ref;
240         if(cascade > info._cascade){
241             info._cascade = cascade;
242         }
243         return true;
244     }
245     
246     public void dontDelete(int a_id) {
247         if(DTrace.enabled){
248             DTrace.TRANS_DONT_DELETE.log(a_id);
249         }
250         if(i_delete == null){
251             return;
252         }
253         i_delete = TreeInt.removeLike((TreeInt)i_delete, a_id);
254     }
255     
256     void dontRemoveFromClassIndex(int a_yapClassID, int a_id) {
257         // If objects are deleted and rewritten during a cascade
258
// on delete, we dont want them to be gone.
259
checkSynchronization();
260         YapClass yapClass = stream().getYapClass(a_yapClassID);
261         yapClass.index().add(this, a_id);
262     }
263     
264     public Object JavaDoc[] objectAndYapObjectBySignature(final long a_uuid, final byte[] a_signature) {
265         checkSynchronization();
266         return stream().getFieldUUID().objectAndYapObjectBySignature(this, a_uuid, a_signature);
267     }
268     
269     public void processDeletes() {
270         if (i_delete == null) {
271             i_writtenUpdateDeletedMembers = null;
272             return;
273         }
274
275         while(i_delete != null) {
276             
277             Tree delete = i_delete;
278             i_delete = null;
279             
280             delete.traverse(new Visitor4() {
281                 public void visit(Object JavaDoc a_object) {
282                     DeleteInfo info = (DeleteInfo)a_object;
283                     Object JavaDoc obj = null;
284                     if(info._reference != null){
285                         obj = info._reference.getObject();
286                     }
287                     if(obj == null){
288                         
289                         // This means the object was gc'd.
290

291                         // Let's try to read it again, but this may fail in CS mode
292
// if another transaction has deleted it. We are taking care
293
// of possible nulls in #delete4().
294

295                         Object JavaDoc[] arr = stream().getObjectAndYapObjectByID(Transaction.this, info._key);
296                         obj = arr[0];
297                         info._reference = (YapObject)arr[1];
298                         info._reference.flagForDelete(stream().topLevelCallId());
299                     }
300                     stream().delete3(Transaction.this,info._reference ,info._cascade, false);
301                 }
302             });
303         }
304         i_writtenUpdateDeletedMembers = null;
305     }
306     
307     
308     public Reflector reflector(){
309         return stream().reflector();
310     }
311
312     public void rollback() {
313         synchronized (stream().i_lock) {
314             
315             rollbackParticipants();
316             
317             rollbackFieldIndexes();
318             
319             rollbackSlotChanges();
320             
321             rollBackTransactionListeners();
322             
323             clearAll();
324         }
325     }
326
327     protected void rollbackSlotChanges() {
328     }
329
330     private void rollbackFieldIndexes() {
331         if (i_dirtyFieldIndexes != null) {
332             Iterator4 i = new Iterator4Impl(i_dirtyFieldIndexes);
333             while (i.moveNext()) {
334                 ((IndexTransaction) i.current()).rollback();
335             }
336         }
337     }
338     
339     private void rollbackParticipants() {
340         Iterator4 iterator = _participants.iterator();
341         while (iterator.moveNext()) {
342             ((TransactionParticipant)iterator.current()).rollback(this);
343         }
344     }
345
346     protected void rollBackTransactionListeners() {
347         checkSynchronization();
348         if (i_transactionListeners != null) {
349             Iterator4 i = new Iterator4Impl(i_transactionListeners);
350             while (i.moveNext()) {
351                 ((TransactionListener) i.current()).postRollback();
352             }
353             i_transactionListeners = null;
354         }
355     }
356
357     void setAddress(int a_address) {
358         i_address = a_address;
359     }
360
361     public abstract void setPointer(int a_id, int a_address, int a_length);
362     
363     void slotDelete(int a_id, int a_address, int a_length) {
364     }
365
366     public void slotFreeOnCommit(int a_id, int a_address, int a_length) {
367     }
368
369     void slotFreeOnRollback(int a_id, int a_address, int a_length) {
370     }
371
372     void slotFreeOnRollbackCommitSetPointer(int a_id, int newAddress, int newLength) {
373     }
374
375     void slotFreeOnRollbackSetPointer(int a_id, int a_address, int a_length) {
376     }
377     
378     public void slotFreePointerOnCommit(int a_id) {
379     }
380     
381     void slotFreePointerOnCommit(int a_id, int a_address, int a_length) {
382     }
383
384     boolean supportsVirtualFields(){
385         return true;
386     }
387     
388     public Transaction systemTransaction(){
389         if(i_parentTransaction != null){
390             return i_parentTransaction;
391         }
392         return this;
393     }
394
395     public String JavaDoc toString() {
396         return stream().toString();
397     }
398     
399
400     public void writePointer(int a_id, int a_address, int a_length) {
401         if(DTrace.enabled){
402             DTrace.WRITE_POINTER.log(a_id);
403             DTrace.WRITE_POINTER.logLength(a_address, a_length);
404         }
405         checkSynchronization();
406         i_pointerIo.useSlot(a_id);
407         if (Deploy.debug) {
408             i_pointerIo.writeBegin(YapConst.YAPPOINTER);
409         }
410         i_pointerIo.writeInt(a_address);
411         i_pointerIo.writeInt(a_length);
412         if (Deploy.debug) {
413             i_pointerIo.writeEnd();
414         }
415         if (Debug.xbytes && Deploy.overwrite) {
416             i_pointerIo.setID(YapConst.IGNORE_ID);
417         }
418         i_pointerIo.write();
419     }
420     
421     
422     public void writeUpdateDeleteMembers(int a_id, YapClass a_yc, int a_type, int a_cascade) {
423         checkSynchronization();
424         if(Tree.find(i_writtenUpdateDeletedMembers, new TreeInt(a_id)) != null){
425             return;
426         }
427         if(DTrace.enabled){
428             DTrace.WRITE_UPDATE_DELETE_MEMBERS.log(a_id);
429         }
430         i_writtenUpdateDeletedMembers = Tree.add(i_writtenUpdateDeletedMembers, new TreeInt(a_id));
431         YapWriter objectBytes = stream().readWriterByID(this, a_id);
432         if(objectBytes == null){
433             if (a_yc.hasIndex()) {
434                  dontRemoveFromClassIndex(a_yc.getID(), a_id);
435             }
436             return;
437         }
438         
439         ObjectHeader oh = new ObjectHeader(stream(), a_yc, objectBytes);
440         
441         DeleteInfo info = (DeleteInfo)TreeInt.find(i_delete, a_id);
442         if(info != null){
443             if(info._cascade > a_cascade){
444                 a_cascade = info._cascade;
445             }
446         }
447         
448         objectBytes.setCascadeDeletes(a_cascade);
449         a_yc.deleteMembers(oh._marshallerFamily, oh._headerAttributes, objectBytes, a_type, true);
450         slotFreeOnCommit(a_id, objectBytes.getAddress(), objectBytes.getLength());
451     }
452
453     public final YapStream stream() {
454         return i_stream;
455     }
456
457     public void enlist(TransactionParticipant participant) {
458         if (null == participant) {
459             throw new ArgumentNullException("participant");
460         }
461         checkSynchronization();
462         if (!_participants.containsByIdentity(participant)) {
463             _participants.add(participant);
464         }
465     }
466     
467     public static Transaction readInterruptedTransaction(YapFile file, YapReader reader) {
468         int transactionID1 = reader.readInt();
469         int transactionID2 = reader.readInt();
470         if( (transactionID1 > 0) && (transactionID1 == transactionID2)){
471             Transaction transaction = file.newTransaction(null);
472             transaction.setAddress(transactionID1);
473             return transaction;
474         }
475         return null;
476     }
477
478     public Transaction parentTransaction() {
479         return i_parentTransaction;
480     }
481
482 }
Popular Tags