KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > YapFileTransaction


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.slots.*;
25
26 /**
27  * @exclude
28  */

29 public class YapFileTransaction extends Transaction {
30     
31     private Tree _slotChanges;
32
33     public YapFileTransaction(YapStream a_stream, Transaction a_parent) {
34         super(a_stream, a_parent);
35     }
36     
37     protected void clearAll() {
38         _slotChanges = null;
39         super.clearAll();
40     }
41     
42     protected void rollbackSlotChanges() {
43         if(_slotChanges != null){
44             _slotChanges.traverse(new Visitor4() {
45                 public void visit(Object JavaDoc a_object) {
46                     ((SlotChange)a_object).rollback(i_file);
47                 }
48             });
49         }
50     }
51     
52     public boolean isDeleted(int id) {
53         return slotChangeIsFlaggedDeleted(id);
54     }
55
56     
57     protected void commit6WriteChanges() {
58         checkSynchronization();
59             
60         final int slotSetPointerCount = countSlotChanges();
61         
62         if (slotSetPointerCount > 0) {
63             int length = (((slotSetPointerCount * 3) + 2) * YapConst.INT_LENGTH);
64             int address = i_file.getSlot(length);
65             final YapWriter bytes = new YapWriter(this, address, length);
66             bytes.writeInt(length);
67             bytes.writeInt(slotSetPointerCount);
68             
69             appendSlotChanges(bytes);
70             
71             bytes.write();
72             flushFile();
73             
74             stream().writeTransactionPointer(address);
75             flushFile();
76             
77             if(writeSlots()){
78                 flushFile();
79             }
80             
81             stream().writeTransactionPointer(0);
82             flushFile();
83             
84             i_file.free(address, length);
85         }
86     }
87     
88     private boolean writeSlots() {
89         
90         checkSynchronization();
91         
92         boolean ret = false;
93         
94         if(i_parentTransaction != null){
95             if(parentFileTransaction().writeSlots()){
96                 ret = true;
97             }
98         }
99         
100         if(_slotChanges != null){
101             _slotChanges.traverse(new Visitor4() {
102                 public void visit(Object JavaDoc a_object) {
103                     ((SlotChange)a_object).writePointer(YapFileTransaction.this);
104                 }
105             });
106             ret = true;
107         }
108         
109         return ret;
110     }
111     
112     protected void flushFile(){
113         if(DTrace.enabled){
114             DTrace.TRANS_FLUSH.log();
115         }
116         if(i_file.configImpl().flushFileBuffers()){
117             i_file.syncFiles();
118         }
119     }
120     
121     private SlotChange produceSlotChange(int id){
122         if(DTrace.enabled){
123             DTrace.PRODUCE_SLOT_CHANGE.log(id);
124         }
125         SlotChange slot = new SlotChange(id);
126         _slotChanges = Tree.add(_slotChanges, slot);
127         return (SlotChange)slot.duplicateOrThis();
128     }
129     
130     
131     private final SlotChange findSlotChange(int a_id) {
132         checkSynchronization();
133         return (SlotChange)TreeInt.find(_slotChanges, a_id);
134     }
135
136     public Slot getCurrentSlotOfID(int id) {
137         checkSynchronization();
138         if (id == 0) {
139             return null;
140         }
141         SlotChange change = findSlotChange(id);
142         if (change != null) {
143             if(change.isSetPointer()){
144                 return change.newSlot();
145             }
146         }
147         
148         if (i_parentTransaction != null) {
149             Slot parentSlot = parentFileTransaction().getCurrentSlotOfID(id);
150             if (parentSlot != null) {
151                 return parentSlot;
152             }
153         }
154         return readCommittedSlotOfID(id);
155     }
156     
157     public Slot getCommittedSlotOfID(int id){
158         if (id == 0) {
159             return null;
160         }
161         SlotChange change = findSlotChange(id);
162         if (change != null) {
163             Slot slot = change.oldSlot();
164             if(slot != null){
165                 return slot;
166             }
167         }
168         
169         if (i_parentTransaction != null) {
170             Slot parentSlot = parentFileTransaction().getCommittedSlotOfID(id);
171             if (parentSlot != null) {
172                 return parentSlot;
173             }
174         }
175         return readCommittedSlotOfID(id);
176     }
177
178     private Slot readCommittedSlotOfID(int id) {
179         if (Deploy.debug) {
180             i_pointerIo.useSlot(id);
181             i_pointerIo.read();
182             i_pointerIo.readBegin(YapConst.YAPPOINTER);
183             int debugAddress = i_pointerIo.readInt();
184             int debugLength = i_pointerIo.readInt();
185             i_pointerIo.readEnd();
186             return new Slot(debugAddress, debugLength);
187         }
188         // FIXME: This shouldn't be silently swallowed. Currently this situation can occur for
189
// a class collection in a new yap file that already has its ID assigned but hasn't been
190
// written yet. Should be fixed in the YapClassCollection logic.
191
try {
192             i_file.readBytes(_pointerBuffer, id, YapConst.POINTER_LENGTH);
193         }
194         catch(RuntimeException JavaDoc exc) {
195             return null;
196         }
197         int address = (_pointerBuffer[3] & 255)
198             | (_pointerBuffer[2] & 255) << 8 | (_pointerBuffer[1] & 255) << 16
199             | _pointerBuffer[0] << 24;
200         int length = (_pointerBuffer[7] & 255)
201             | (_pointerBuffer[6] & 255) << 8 | (_pointerBuffer[5] & 255) << 16
202             | _pointerBuffer[4] << 24;
203         return new Slot(address, length);
204     }
205     
206     public void setPointer(int a_id, int a_address, int a_length) {
207         if(DTrace.enabled){
208             DTrace.SLOT_SET_POINTER.log(a_id);
209             DTrace.SLOT_SET_POINTER.logLength(a_address, a_length);
210         }
211         checkSynchronization();
212         produceSlotChange(a_id).setPointer(a_address, a_length);
213     }
214     
215     private boolean slotChangeIsFlaggedDeleted(int id){
216         SlotChange slot = findSlotChange(id);
217         if (slot != null) {
218             return slot.isDeleted();
219         }
220         if (i_parentTransaction != null) {
221             return parentFileTransaction().slotChangeIsFlaggedDeleted(id);
222         }
223         return false;
224     }
225
226     
227      private int countSlotChanges(){
228             
229             int count = 0;
230             
231             if(i_parentTransaction != null){
232                 count += parentFileTransaction().countSlotChanges();
233             }
234             
235             final int slotSetPointerCount[] = {count};
236             
237             if(_slotChanges != null){
238                 _slotChanges.traverse(new Visitor4() {
239                     public void visit(Object JavaDoc obj) {
240                         SlotChange slot = (SlotChange)obj;
241                         if(slot.isSetPointer()){
242                             slotSetPointerCount[0] ++;
243                         }
244                     }
245                 });
246             }
247             
248             return slotSetPointerCount[0];
249         }
250     
251     void writeOld() {
252         synchronized (stream().i_lock) {
253             i_pointerIo.useSlot(i_address);
254             i_pointerIo.read();
255             int length = i_pointerIo.readInt();
256             if (length > 0) {
257                 YapWriter bytes = new YapWriter(this, i_address, length);
258                 bytes.read();
259                 bytes.incrementOffset(YapConst.INT_LENGTH);
260                 _slotChanges = new TreeReader(bytes, new SlotChange(0)).read();
261                 if(writeSlots()){
262                     flushFile();
263                 }
264                 stream().writeTransactionPointer(0);
265                 flushFile();
266                 freeOnCommit();
267             } else {
268                 stream().writeTransactionPointer(0);
269                 flushFile();
270             }
271         }
272     }
273     
274     protected final void freeOnCommit() {
275         checkSynchronization();
276         if(i_parentTransaction != null){
277             parentFileTransaction().freeOnCommit();
278         }
279         if(_slotChanges != null){
280             _slotChanges.traverse(new Visitor4() {
281                 public void visit(Object JavaDoc obj) {
282                     ((SlotChange)obj).freeDuringCommit(i_file);
283                 }
284             });
285         }
286     }
287     
288     private void appendSlotChanges(final YapReader writer){
289         
290         if(i_parentTransaction != null){
291             parentFileTransaction().appendSlotChanges(writer);
292         }
293         
294         Tree.traverse(_slotChanges, new Visitor4() {
295             public void visit(Object JavaDoc obj) {
296                 ((TreeInt)obj).write(writer);
297             }
298         });
299         
300     }
301     
302     void slotDelete(int a_id, int a_address, int a_length) {
303         checkSynchronization();
304         if(DTrace.enabled){
305             DTrace.SLOT_DELETE.log(a_id);
306             DTrace.SLOT_DELETE.logLength(a_address, a_length);
307         }
308         if (a_id == 0) {
309             return;
310         }
311         SlotChange slot = produceSlotChange(a_id);
312         slot.freeOnCommit(i_file, new Slot(a_address, a_length));
313         slot.setPointer(0, 0);
314     }
315
316     public void slotFreeOnCommit(int a_id, int a_address, int a_length) {
317         checkSynchronization();
318         if(DTrace.enabled){
319             DTrace.SLOT_FREE_ON_COMMIT.log(a_id);
320             DTrace.SLOT_FREE_ON_COMMIT.logLength(a_address, a_length);
321         }
322         if (a_id == 0) {
323             return;
324         }
325         produceSlotChange(a_id).freeOnCommit(i_file, new Slot(a_address, a_length));
326     }
327
328     void slotFreeOnRollback(int a_id, int a_address, int a_length) {
329         checkSynchronization();
330         if(DTrace.enabled){
331             DTrace.SLOT_FREE_ON_ROLLBACK_ID.log(a_id);
332             DTrace.SLOT_FREE_ON_ROLLBACK_ADDRESS.logLength(a_address, a_length);
333         }
334         produceSlotChange(a_id).freeOnRollback(a_address, a_length);
335     }
336
337     void slotFreeOnRollbackCommitSetPointer(int a_id, int newAddress, int newLength) {
338         
339         Slot slot = getCurrentSlotOfID(a_id);
340         if(slot==null) {
341             return;
342         }
343         
344         checkSynchronization();
345         
346         if(DTrace.enabled){
347             DTrace.FREE_ON_ROLLBACK.log(a_id);
348             DTrace.FREE_ON_ROLLBACK.logLength(newAddress, newLength);
349             DTrace.FREE_ON_COMMIT.log(a_id);
350             DTrace.FREE_ON_COMMIT.logLength(slot._address, slot._length);
351         }
352         
353         SlotChange change = produceSlotChange(a_id);
354         change.freeOnRollbackSetPointer(newAddress, newLength);
355         change.freeOnCommit(i_file, slot);
356     }
357
358     void slotFreeOnRollbackSetPointer(int a_id, int a_address, int a_length) {
359         checkSynchronization();
360         if(DTrace.enabled){
361             DTrace.FREE_ON_ROLLBACK.log(a_id);
362             DTrace.FREE_ON_ROLLBACK.logLength(a_address, a_length);
363         }
364         produceSlotChange(a_id).freeOnRollbackSetPointer(a_address, a_length);
365     }
366     
367     public void slotFreePointerOnCommit(int a_id) {
368         checkSynchronization();
369         Slot slot = getCurrentSlotOfID(a_id);
370         if(slot == null){
371             return;
372         }
373         
374         // FIXME: From looking at this it should call slotFreePointerOnCommit
375
// Write a test case and check.
376

377         slotFreeOnCommit(a_id, slot._address, slot._length);
378     }
379     
380     void slotFreePointerOnCommit(int a_id, int a_address, int a_length) {
381         checkSynchronization();
382         slotFreeOnCommit(a_address, a_address, a_length);
383         slotFreeOnCommit(a_id, a_id, YapConst.POINTER_LENGTH);
384     }
385     
386     private YapFileTransaction parentFileTransaction() {
387         return (YapFileTransaction)i_parentTransaction;
388     }
389
390 }
391
Popular Tags