1 21 package com.db4o.inside.ix; 22 23 import com.db4o.*; 24 import com.db4o.foundation.*; 25 26 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 }; 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 108 public void commitFreeSpace(Index4 other){ 109 110 int entries = countEntries(); 111 112 118 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 ("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 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 185 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 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 toString() { 262 if(! Debug4.prettyToStrings){ 263 return super.toString(); 264 } 265 StringBuffer sb = new StringBuffer (); 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 |