1 21 package com.db4o; 22 23 import com.db4o.foundation.*; 24 import com.db4o.inside.slots.*; 25 26 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 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 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 try { 192 i_file.readBytes(_pointerBuffer, id, YapConst.POINTER_LENGTH); 193 } 194 catch(RuntimeException 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 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 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 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 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 |