KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > inside > ix > Index4


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.inside.ix;
22
23 import com.db4o.*;
24 import com.db4o.foundation.*;
25
26 /**
27  *
28  * @exclude
29  */

30 public class Index4 {
31
32     public final Indexable4 _handler;
33
34     static private int _version;
35
36     public final MetaIndex _metaIndex;
37
38     private IndexTransaction _globalIndexTransaction;
39
40     private Collection4 _indexTransactions;
41
42     private IxFileRangeReader _fileRangeReader;
43     
44     final boolean _nullHandling;
45
46     public Index4(Transaction systemTrans, Indexable4 handler, MetaIndex metaIndex, boolean nullHandling) {
47         _metaIndex = metaIndex;
48         _handler = handler;
49         _globalIndexTransaction = new IndexTransaction(systemTrans, this);
50         _nullHandling = nullHandling;
51         createGlobalFileRange();
52     }
53
54     public IndexTransaction dirtyIndexTransaction(Transaction a_trans) {
55         IndexTransaction ift = new IndexTransaction(a_trans, this);
56         if (_indexTransactions == null) {
57             _indexTransactions = new Collection4();
58         } else {
59             IndexTransaction iftExisting = (IndexTransaction) _indexTransactions.get(ift);
60             if (iftExisting != null) {
61                 return iftExisting;
62             }
63         }
64         a_trans.addDirtyFieldIndex(ift);
65         ift.setRoot(Tree.deepClone(_globalIndexTransaction.getRoot(), ift));
66         ift.i_version = ++_version;
67         _indexTransactions.add(ift);
68         return ift;
69     }
70     
71     public IndexTransaction globalIndexTransaction(){
72         return _globalIndexTransaction;
73     }
74
75     public IndexTransaction indexTransactionFor(Transaction a_trans) {
76         if (_indexTransactions != null) {
77             IndexTransaction ift = new IndexTransaction(a_trans, this);
78             ift = (IndexTransaction) _indexTransactions.get(ift);
79             if (ift != null) {
80                 return ift;
81             }
82         }
83         return _globalIndexTransaction;
84     }
85     
86     private int[] freeForMetaIndex(){
87         return new int[] {
88             _metaIndex.indexAddress,
89             _metaIndex.indexLength,
90 // _metaIndex.patchAddress,
91
// _metaIndex.patchLength
92
};
93     }
94     
95     private void doFree(int[] addressLength){
96         YapFile yf = file();
97         for(int i = 0; i < addressLength.length; i += 2){
98             yf.free(addressLength[i], addressLength[i + 1]);
99         }
100     }
101                 
102     
103     /**
104      * solving a hen-egg problem: commit itself works with freespace
105      * so we have to do this all sequentially in the right way, working
106      * with with both indexes at the same time.
107      */

108     public void commitFreeSpace(Index4 other){
109         
110         int entries = countEntries();
111         
112         // For the two freespace indexes themselves, we call
113
// the freespace system and we store two meta indexes. Potential effects:
114
// 2 x getSlot -2 to 0
115
// 4 x free -4 to + 4
116
//
117

118         // Therefore we have to raise the value by 4, to make
119
// sure that there are enough.
120

121         
122         int length = (entries + 4) * lengthPerEntry();
123         
124         int mySlot = getSlot(length);
125         int otherSlot = getSlot(length);
126         doFree(freeForMetaIndex());
127         doFree(other.freeForMetaIndex());
128         
129         entries = writeToNewSlot(mySlot);
130         metaIndexSetMembers(entries, length, mySlot);
131         createGlobalFileRange();
132         
133         int otherEntries = other.writeToNewSlot(otherSlot);
134         
135         if(Deploy.debug){
136             if(entries != otherEntries){
137                 throw new RuntimeException JavaDoc("Should never happen");
138             }
139         }
140         
141         other.metaIndexSetMembers(entries, length, otherSlot);
142         other.createGlobalFileRange();
143     }
144     
145     private int lengthPerEntry(){
146         return _handler.linkLength() + YapConst.INT_LENGTH;
147     }
148     
149     private void metaIndexStore(int entries, int length, int address){
150         Transaction transact = trans();
151         metaIndexSetMembers(entries, length, address);
152         transact.stream().setInternal(transact, _metaIndex, 1, false);
153     }
154     
155     private void metaIndexSetMembers(int entries, int length, int address){
156         _metaIndex.indexEntries = entries;
157         _metaIndex.indexLength = length;
158         _metaIndex.indexAddress = address;
159     }
160     
161     private int writeToNewSlot(int slot){
162         Tree root = getRoot();
163         final YapWriter writer = new YapWriter(trans(),slot, lengthPerEntry());
164         final int[] entries = new int[] {0};
165         if (root != null) {
166             root.traverse(new Visitor4() {
167                 public void visit(Object JavaDoc a_object) {
168                     entries[0] += ((IxTree) a_object).write(_handler, writer);
169                 }
170             });
171         }
172         return entries[0];
173     }
174     
175
176     void commit(IndexTransaction ixTrans) {
177         
178         _indexTransactions.remove(ixTrans);
179         _globalIndexTransaction.merge(ixTrans);
180
181
182         // TODO: Use more intelligent heuristic here to
183
// calculate when to flush the global index
184

185         // int leaves = _globalIndexTransaction.countLeaves();
186
// boolean createNewFileRange = leaves > MAX_LEAVES;
187

188         
189         boolean createNewFileRange = true;
190
191         if (createNewFileRange) {
192             
193             int entries = countEntries();
194             int length = countEntries() * lengthPerEntry();
195             int slot = getSlot(length);
196             
197             int[] free = freeForMetaIndex();
198             
199             metaIndexStore(entries, length, slot);
200             
201             writeToNewSlot(slot);
202             
203             IxFileRange newFileRange = createGlobalFileRange();
204
205             if(_indexTransactions != null){
206                 Iterator4 i = _indexTransactions.iterator();
207                 while (i.moveNext()) {
208                     final IndexTransaction ft = (IndexTransaction) i.current();
209                     Tree clonedTree = newFileRange;
210                     if (clonedTree != null) {
211                         clonedTree = (Tree)clonedTree.deepClone(ft);
212                     }
213                     final Tree.ByRef tree = new Tree.ByRef(clonedTree);
214                     ft.getRoot().traverseFromLeaves((new Visitor4() {
215                         
216                         public void visit(Object JavaDoc a_object) {
217                             IxTree ixTree = (IxTree) a_object;
218                             if (ixTree._version == ft.i_version) {
219                                 if (!(ixTree instanceof IxFileRange)) {
220                                     ixTree.beginMerge();
221                                     tree.value = Tree.add(tree.value, ixTree);
222                                 }
223                             }
224                         }
225                     }));
226                     ft.setRoot(tree.value);
227                 }
228             }
229             
230             doFree(free);
231
232         } else {
233             Iterator4 i = _indexTransactions.iterator();
234             while (i.moveNext()) {
235                 ((IndexTransaction) i.current()).merge(ixTrans);
236             }
237         }
238     }
239
240     private IxFileRange createGlobalFileRange() {
241         IxFileRange fr = null;
242         if (_metaIndex.indexEntries > 0) {
243             fr = new IxFileRange(_globalIndexTransaction,
244                     _metaIndex.indexAddress, 0, _metaIndex.indexEntries);
245         }
246         _globalIndexTransaction.setRoot(fr);
247         return fr;
248     }
249
250     void rollback(IndexTransaction a_ft) {
251         _indexTransactions.remove(a_ft);
252     }
253
254     IxFileRangeReader fileRangeReader() {
255         if (_fileRangeReader == null) {
256             _fileRangeReader = new IxFileRangeReader(_handler);
257         }
258         return _fileRangeReader;
259     }
260
261     public String JavaDoc toString() {
262         if(! Debug4.prettyToStrings){
263             return super.toString();
264         }
265         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
266         sb.append("IxField " + System.identityHashCode(this));
267         if (_globalIndexTransaction != null) {
268             sb.append("\n Global \n ");
269             sb.append(_globalIndexTransaction.toString());
270         } else {
271             sb.append("\n no global index \n ");
272         }
273         if (_indexTransactions != null) {
274             Iterator4 i = _indexTransactions.iterator();
275             while (i.moveNext()) {
276                 sb.append("\n");
277                 sb.append(i.current().toString());
278             }
279         }
280         return sb.toString();
281     }
282     
283     private Transaction trans(){
284         return _globalIndexTransaction.i_trans;
285     }
286     
287     private YapFile file(){
288         return trans().i_file;
289     }
290     
291     private int getSlot(int length){
292         return file().getSlot(length);
293     }
294     
295     private Tree getRoot(){
296         return _globalIndexTransaction.getRoot();
297     }
298     
299     private int countEntries(){
300         Tree root = getRoot();
301         return root == null ? 0 : root.size();
302     }
303     
304
305 }
306
Popular Tags