1 21 package com.db4o; 22 23 import java.io.*; 24 25 import com.db4o.config.*; 26 import com.db4o.ext.*; 27 import com.db4o.foundation.*; 28 import com.db4o.header.*; 29 import com.db4o.inside.*; 30 import com.db4o.inside.btree.*; 31 import com.db4o.inside.convert.*; 32 import com.db4o.inside.freespace.*; 33 import com.db4o.inside.query.*; 34 import com.db4o.inside.slots.*; 35 36 39 public abstract class YapFile extends YapStream { 40 41 protected FileHeader _fileHeader; 42 43 private Collection4 i_dirty; 44 45 private FreespaceManager _freespaceManager; 46 47 private FreespaceManager _fmChecker; 49 50 private boolean i_isServer = false; 51 52 private Tree i_prefetchedIDs; 53 54 private Hashtable4 i_semaphores; 55 56 private int _blockEndAddress; 57 58 private Tree _freeOnCommit; 59 60 private SystemData _systemData; 61 62 YapFile(Configuration config,YapStream a_parent) { 63 super(config,a_parent); 64 } 65 66 public Transaction newTransaction(Transaction parentTransaction) { 67 return new YapFileTransaction(this, parentTransaction); 68 } 69 70 public FreespaceManager freespaceManager() { 71 return _freespaceManager; 72 } 73 74 public abstract void blockSize(int size); 75 76 public void blockSizeReadFromFile(int size){ 77 blockSize(size); 78 setRegularEndAddress(fileLength()); 79 } 80 81 public void setRegularEndAddress(long address){ 82 _blockEndAddress = blocksFor(address); 83 } 84 85 protected boolean close2() { 86 boolean ret = super.close2(); 87 i_dirty = null; 88 return ret; 89 } 90 91 public void commit1() { 92 try { 93 write(false); 94 } catch (Throwable t) { 95 fatalException(t); 96 } 97 } 98 99 void configureNewFile() throws IOException{ 100 101 newSystemData(configImpl().freespaceSystem()); 102 systemData().converterVersion(Converter.VERSION); 103 createStringIO(_systemData.stringEncoding()); 104 105 generateNewIdentity(); 106 107 _freespaceManager = FreespaceManager.createNew(this); 108 109 if(Debug.freespaceChecker){ 110 _fmChecker = new FreespaceManagerRam(this); 111 } 112 113 blockSize(configImpl().blockSize()); 114 115 _fileHeader = new FileHeader1(); 116 117 setRegularEndAddress(_fileHeader.length()); 118 119 initNewClassCollection(); 120 initializeEssentialClasses(); 121 122 _fileHeader.initNew(this); 123 124 _freespaceManager.onNew(this); 125 _freespaceManager.start(_systemData.freespaceAddress()); 126 127 if(Debug.freespace && Debug.freespaceChecker){ 128 _fmChecker.start(0); 129 } 130 } 131 132 private void newSystemData(byte freespaceSystem){ 133 _systemData = new SystemData(); 134 _systemData.stringEncoding(configImpl().encoding()); 135 _systemData.freespaceSystem(freespaceSystem); 136 } 137 138 public int converterVersion() { 139 return _systemData.converterVersion(); 140 } 141 142 public abstract void copy(int oldAddress, int oldAddressOffset, int newAddress, int newAddressOffset, int length); 143 144 public long currentVersion() { 145 return _timeStampIdGenerator.lastTimeStampId(); 146 } 147 148 void initNewClassCollection() { 149 classCollection().initTables(1); 151 } 152 153 public final BTree createBTreeClassIndex(int id){ 154 return new BTree(i_trans, id, new IDHandler(this)); 155 } 156 157 public final AbstractQueryResult newQueryResult(Transaction trans) { 158 return newQueryResult(trans, config().queryEvaluationMode()); 159 } 160 161 public final AbstractQueryResult newQueryResult(Transaction trans, QueryEvaluationMode mode) { 162 if(mode == QueryEvaluationMode.IMMEDIATE){ 163 return new IdListQueryResult(trans); 164 } 165 return new HybridQueryResult(trans, mode); 166 } 167 168 public final boolean delete4(Transaction ta, YapObject yo, int a_cascade, boolean userCall) { 169 int id = yo.getID(); 170 YapWriter reader = readWriterByID(ta, id); 171 if (reader != null) { 172 Object obj = yo.getObject(); 173 if (obj != null) { 174 if ((!showInternalClasses()) 175 && YapConst.CLASS_INTERNAL.isAssignableFrom(obj.getClass())) { 176 return false; 177 } 178 } 179 reader.setCascadeDeletes(a_cascade); 180 reader.slotDelete(); 181 YapClass yc = yo.getYapClass(); 182 yc.delete(reader, obj); 183 184 188 192 return true; 193 } 194 return false; 195 } 196 197 public abstract long fileLength(); 198 199 abstract String fileName(); 200 201 public void free(Slot slot) { 202 if(slot == null){ 203 return; 204 } 205 if(slot._address == 0){ 206 return; 207 } 208 free(slot._address, slot._length); 209 } 210 211 public void free(int a_address, int a_length) { 212 if(DTrace.enabled){ 213 DTrace.FILE_FREE.logLength(a_address, a_length); 214 } 215 if(_freespaceManager == null){ 216 return; 219 } 220 _freespaceManager.free(a_address, a_length); 221 if(Debug.freespace && Debug.freespaceChecker){ 222 _fmChecker.free(a_address, a_length); 223 } 224 } 225 226 final void freePrefetchedPointers() { 227 if (i_prefetchedIDs != null) { 228 i_prefetchedIDs.traverse(new Visitor4() { 229 230 public void visit(Object a_object) { 231 free(((TreeInt) a_object)._key, YapConst.POINTER_LENGTH); 232 } 233 }); 234 } 235 i_prefetchedIDs = null; 236 } 237 238 final void freeSpaceBeginCommit(){ 239 if(_freespaceManager == null){ 240 return; 241 } 242 _freespaceManager.beginCommit(); 243 } 244 245 final void freeSpaceEndCommit(){ 246 if(_freespaceManager == null){ 247 return; 248 } 249 _freespaceManager.endCommit(); 250 } 251 252 public void generateNewIdentity(){ 253 synchronized(i_lock){ 254 setIdentity(Db4oDatabase.generate()); 255 } 256 } 257 258 public AbstractQueryResult getAll(Transaction trans) { 259 return getAll(trans, config().queryEvaluationMode()); 260 } 261 262 public AbstractQueryResult getAll(Transaction trans, QueryEvaluationMode mode) { 263 final AbstractQueryResult queryResult = newQueryResult(trans, mode); 264 queryResult.loadFromClassIndexes(classCollection().iterator()); 265 return queryResult; 266 } 267 268 final int getPointerSlot() { 269 int id = getSlot(YapConst.POINTER_LENGTH); 270 271 i_systemTrans.writePointer(id, 0, 0); 274 275 276 if(i_handlers.isSystemHandler(id)){ 279 return getPointerSlot(); 280 } 281 282 return id; 283 } 284 285 public int getSlot(int a_length){ 286 287 if(! DTrace.enabled){ 288 return getSlot1(a_length); 289 } 290 291 int address = getSlot1(a_length); 292 DTrace.GET_SLOT.logLength(address, a_length); 293 return address; 294 } 295 296 private final int getSlot1(int bytes) { 297 298 if(Deploy.debug){ 299 if(bytes <= 0){ 300 throw new RuntimeException ("Who wants invalid zero or smaller slots ?"); 301 } 302 } 303 304 if(_freespaceManager != null){ 305 306 int freeAddress = _freespaceManager.getSlot(bytes); 307 308 if(Debug.freespace && Debug.freespaceChecker){ 309 if(freeAddress > 0){ 310 Collection4 wrongOnes = new Collection4(); 311 int freeCheck = _fmChecker.getSlot(bytes); 312 313 while(freeCheck != freeAddress && freeCheck > 0){ 314 wrongOnes.add(new int[]{freeCheck,bytes}); 316 freeCheck = _fmChecker.getSlot(bytes); 317 } 318 Iterator4 i = wrongOnes.iterator(); 319 while(i.moveNext()){ 320 int[] adrLength = (int[])i.current(); 321 _fmChecker.free(adrLength[0], adrLength[1]); 322 } 323 if(freeCheck == 0){ 324 _freespaceManager.debug(); 325 _fmChecker.debug(); 326 } 327 } 328 } 329 330 if(freeAddress > 0){ 331 return freeAddress; 332 } 333 } 334 335 int blocksNeeded = blocksFor(bytes); 336 if (Debug.xbytes && Deploy.overwrite) { 337 debugWriteXBytes(_blockEndAddress, blocksNeeded * blockSize()); 338 } 339 return appendBlocks(blocksNeeded); 340 } 341 342 protected int appendBlocks(int blockCount){ 343 int blockedAddress = _blockEndAddress; 344 _blockEndAddress += blockCount; 345 return blockedAddress; 346 } 347 348 void ensureLastSlotWritten(){ 349 if (!Debug.xbytes){ 350 if(Deploy.overwrite){ 351 if(_blockEndAddress > blocksFor(fileLength())){ 352 YapWriter writer = getWriter(i_systemTrans, _blockEndAddress - 1, blockSize()); 353 writer.write(); 354 } 355 } 356 } 357 } 358 359 public Db4oDatabase identity() { 360 return _systemData.identity(); 361 } 362 363 public void setIdentity(Db4oDatabase identity){ 364 _systemData.identity(identity); 365 366 _timeStampIdGenerator.next(); 370 } 371 372 void initialize2() { 373 i_dirty = new Collection4(); 374 super.initialize2(); 375 } 376 377 boolean isServer() { 378 return i_isServer; 379 } 380 381 public final Pointer4 newSlot(Transaction a_trans, int a_length) { 382 int id = getPointerSlot(); 383 int address = getSlot(a_length); 384 a_trans.setPointer(id, address, a_length); 385 return new Pointer4(id, address); 386 } 387 388 public final int newUserObject() { 389 return getPointerSlot(); 390 } 391 392 public void prefetchedIDConsumed(int a_id) { 393 i_prefetchedIDs = i_prefetchedIDs.removeLike(new TreeIntObject(a_id)); 394 } 395 396 public int prefetchID() { 397 int id = getPointerSlot(); 398 i_prefetchedIDs = Tree.add(i_prefetchedIDs, new TreeInt(id)); 399 return id; 400 } 401 402 public ReferencedSlot produceFreeOnCommitEntry(int id){ 403 Tree node = TreeInt.find(_freeOnCommit, id); 404 if (node != null) { 405 return (ReferencedSlot) node; 406 } 407 ReferencedSlot slot = new ReferencedSlot(id); 408 _freeOnCommit = Tree.add(_freeOnCommit, slot); 409 return slot; 410 } 411 412 public void reduceFreeOnCommitReferences(ReferencedSlot slot){ 413 if(slot.removeReferenceIsLast()){ 414 _freeOnCommit = _freeOnCommit.removeNode(slot); 415 } 416 } 417 418 public void freeDuringCommit(ReferencedSlot referencedSlot, Slot slot){ 419 _freeOnCommit = referencedSlot.free(this, _freeOnCommit, slot); 420 } 421 422 public void raiseVersion(long a_minimumVersion) { 423 synchronized (lock()) { 424 _timeStampIdGenerator.setMinimumNext(a_minimumVersion); 425 } 426 } 427 428 public YapWriter readWriterByID(Transaction a_ta, int a_id) { 429 return (YapWriter)readReaderOrWriterByID(a_ta, a_id, false); 430 } 431 432 public YapReader readReaderByID(Transaction a_ta, int a_id) { 433 return readReaderOrWriterByID(a_ta, a_id, true); 434 } 435 436 private final YapReader readReaderOrWriterByID(Transaction a_ta, int a_id, boolean useReader) { 437 if (a_id == 0) { 438 return null; 439 } 440 441 if(DTrace.enabled){ 442 DTrace.READ_ID.log(a_id); 443 } 444 445 try { 446 Slot slot = ((YapFileTransaction)a_ta).getCurrentSlotOfID(a_id); 447 if (slot == null) { 448 return null; 449 } 450 451 if (slot._address == 0) { 452 return null; 453 } 454 455 if(DTrace.enabled){ 456 DTrace.READ_SLOT.logLength(slot._address, slot._length); 457 } 458 459 YapReader reader = null; 460 if(useReader){ 461 reader = new YapReader(slot._length); 462 }else{ 463 reader = getWriter(a_ta, slot._address, slot._length); 464 ((YapWriter)reader).setID(a_id); 465 } 466 467 reader.readEncrypt(this, slot._address); 468 return reader; 469 470 } catch (Exception e) { 471 472 476 479 if (Debug.atHome) { 480 System.out.println("YapFile.readReaderOrWriterByID failed for ID: " + a_id); 481 e.printStackTrace(); 482 } 483 } 484 return null; 485 486 } 487 488 489 490 void readThis() throws IOException { 491 492 newSystemData(FreespaceManager.FM_LEGACY_RAM); 493 blockSizeReadFromFile(1); 494 495 _fileHeader = FileHeader.readFixedPart(this); 496 497 createStringIO(_systemData.stringEncoding()); 498 499 classCollection().setID(_systemData.classCollectionID()); 500 classCollection().read(i_systemTrans); 501 502 Converter.convert(new ConversionStage.ClassCollectionAvailableStage(this)); 503 504 readHeaderVariablePart(); 505 506 _freespaceManager = FreespaceManager.createNew(this, _systemData.freespaceSystem()); 507 _freespaceManager.read(_systemData.freespaceID()); 508 509 if(Debug.freespace){ 510 _fmChecker = new FreespaceManagerRam(this); 511 _fmChecker.read(_systemData.freespaceID()); 512 } 513 514 _freespaceManager.start(_systemData.freespaceAddress()); 515 516 if(Debug.freespace){ 517 _fmChecker.start(0); 518 } 519 520 if(_freespaceManager.requiresMigration(configImpl().freespaceSystem(), _systemData.freespaceSystem())){ 521 FreespaceManager oldFreespaceManager = _freespaceManager; 522 _freespaceManager = FreespaceManager.createNew(this, _systemData.freespaceSystem()); 523 _freespaceManager.start(newFreespaceSlot(_systemData.freespaceSystem())); 524 FreespaceManager.migrate(oldFreespaceManager, _freespaceManager); 525 _fileHeader.writeVariablePart(this, 1); 526 } 527 528 writeHeader(false); 529 530 YapFileTransaction trans = (YapFileTransaction) _fileHeader.interruptedTransaction(); 531 532 if (trans != null) { 533 if (!configImpl().commitRecoveryDisabled()) { 534 trans.writeOld(); 535 } 536 } 537 538 if(Converter.convert(new ConversionStage.SystemUpStage(this))){ 539 _systemData.converterVersion(Converter.VERSION); 540 _fileHeader.writeVariablePart(this, 1); 541 getTransaction().commit(); 542 } 543 544 } 545 546 private void readHeaderVariablePart() { 547 _fileHeader.readVariablePart(this); 548 setNextTimeStampId(systemData().lastTimeStampID()); 549 } 550 551 public int newFreespaceSlot(byte freespaceSystem){ 552 _systemData.freespaceAddress(FreespaceManager.initSlot(this)); 553 _systemData.freespaceSystem(freespaceSystem); 554 return _systemData.freespaceAddress(); 555 } 556 557 public void ensureFreespaceSlot(){ 558 if(systemData().freespaceAddress() == 0){ 559 newFreespaceSlot(systemData().freespaceSystem()); 560 } 561 } 562 563 public void releaseSemaphore(String name) { 564 releaseSemaphore(checkTransaction(null), name); 565 } 566 567 public void releaseSemaphore(Transaction ta, String name) { 568 if (i_semaphores != null) { 569 synchronized (i_semaphores) { 570 if (i_semaphores != null && ta == i_semaphores.get(name)) { 571 i_semaphores.remove(name); 572 i_semaphores.notifyAll(); 573 } 574 } 575 } 576 } 577 578 public void releaseSemaphores(Transaction ta) { 579 if (i_semaphores != null) { 580 final Hashtable4 semaphores = i_semaphores; 581 synchronized (semaphores) { 582 semaphores.forEachKeyForIdentity(new Visitor4() { 583 public void visit(Object a_object) { 584 semaphores.remove(a_object); 585 } 586 }, ta); 587 semaphores.notifyAll(); 588 } 589 } 590 } 591 592 public final void rollback1() { 593 getTransaction().rollback(); 594 } 595 596 public final void setDirtyInSystemTransaction(YapMeta a_object) { 597 a_object.setStateDirty(); 598 a_object.cacheDirty(i_dirty); 599 } 600 601 public boolean setSemaphore(String name, int timeout) { 602 return setSemaphore(checkTransaction(null), name, timeout); 603 } 604 605 public boolean setSemaphore(Transaction ta, String name, int timeout) { 606 if (name == null) { 607 throw new NullPointerException (); 608 } 609 if (i_semaphores == null) { 610 synchronized (i_lock) { 611 if (i_semaphores == null) { 612 i_semaphores = new Hashtable4(10); 613 } 614 } 615 } 616 synchronized (i_semaphores) { 617 Object obj = i_semaphores.get(name); 618 if (obj == null) { 619 i_semaphores.put(name, ta); 620 return true; 621 } 622 if (ta == obj) { 623 return true; 624 } 625 long endtime = System.currentTimeMillis() + timeout; 626 long waitTime = timeout; 627 while (waitTime > 0) { 628 try { 629 i_semaphores.wait(waitTime); 630 } catch (Exception e) { 631 if (Debug.atHome) { 632 e.printStackTrace(); 633 } 634 } 635 if (classCollection() == null) { 636 return false; 637 } 638 639 obj = i_semaphores.get(name); 640 641 if (obj == null) { 642 i_semaphores.put(name, ta); 643 return true; 644 } 645 646 waitTime = endtime - System.currentTimeMillis(); 647 } 648 return false; 649 } 650 } 651 652 public void setServer(boolean flag) { 653 i_isServer = flag; 654 } 655 656 public abstract void syncFiles(); 657 658 public String toString() { 659 if (Debug4.prettyToStrings) { 660 return super.toString(); 661 } 662 return fileName(); 663 } 664 665 public void write(boolean shuttingDown) { 666 667 i_trans.commit(); 670 671 if (shuttingDown) { 672 writeHeader(shuttingDown); 673 } 674 } 675 676 public abstract boolean writeAccessTime(int address, int offset, long time) throws IOException; 677 678 public abstract void writeBytes(YapReader a_Bytes, int address, int addressOffset); 679 680 public final void writeDirty() { 681 writeCachedDirty(); 682 writeVariableHeader(); 683 } 684 685 private void writeCachedDirty() { 686 Iterator4 i = i_dirty.iterator(); 687 while (i.moveNext()) { 688 YapMeta dirty = (YapMeta) i.current(); 689 dirty.write(i_systemTrans); 690 dirty.notCachedDirty(); 691 } 692 i_dirty.clear(); 693 } 694 695 protected void writeVariableHeader(){ 696 if(! _timeStampIdGenerator.isDirty()){ 697 return; 698 } 699 _systemData.lastTimeStampID(_timeStampIdGenerator.lastTimeStampId()); 700 _fileHeader.writeVariablePart(this, 2); 701 _timeStampIdGenerator.setClean(); 702 } 703 704 public final void writeEmbedded(YapWriter a_parent, YapWriter a_child) { 705 int length = a_child.getLength(); 706 int address = getSlot(length); 707 a_child.getTransaction().slotFreeOnRollback(address, address, length); 708 a_child.address(address); 709 a_child.writeEncrypt(); 710 int offsetBackup = a_parent._offset; 711 a_parent._offset = a_child.getID(); 712 a_parent.writeInt(address); 713 a_parent._offset = offsetBackup; 714 } 715 716 void writeHeader(boolean shuttingDown) { 717 718 int freespaceID = _freespaceManager.write(shuttingDown); 719 720 if(shuttingDown){ 721 _freespaceManager = null; 722 } 723 724 if(Debug.freespace && Debug.freespaceChecker){ 725 freespaceID = _fmChecker.write(shuttingDown); 726 } 727 728 YapWriter writer = getWriter(i_systemTrans, 0, _fileHeader.length()); 730 731 _fileHeader.writeFixedPart(this, shuttingDown, writer, blockSize(), freespaceID); 732 733 if(shuttingDown){ 734 ensureLastSlotWritten(); 735 } 736 syncFiles(); 737 } 738 739 public final void writeNew(YapClass a_yapClass, YapWriter aWriter) { 740 aWriter.writeEncrypt(this, aWriter.getAddress(), 0); 741 if(a_yapClass == null){ 742 return; 743 } 744 if (maintainsIndices()) { 745 a_yapClass.addToIndex(this, aWriter.getTransaction(), aWriter 746 .getID()); 747 } 748 } 749 750 753 public abstract void debugWriteXBytes(int a_address, int a_length); 754 755 YapReader xBytes(int a_address, int a_length) { 756 YapReader bytes = getWriter(i_systemTrans, a_address, a_length); 757 for (int i = 0; i < a_length; i++) { 758 bytes.append(YapConst.XBYTE); 759 } 760 return bytes; 761 } 762 763 public final void writeTransactionPointer(int address) { 764 _fileHeader.writeTransactionPointer(getSystemTransaction(), address); 765 } 766 767 public final void getSlotForUpdate(YapWriter forWriter){ 768 Transaction trans = forWriter.getTransaction(); 769 int id = forWriter.getID(); 770 int length = forWriter.getLength(); 771 int address = getSlot(length); 772 forWriter.address(address); 773 trans.slotFreeOnRollbackSetPointer(id, address, length); 774 } 775 776 public final void writeUpdate(YapClass a_yapClass, YapWriter a_bytes) { 777 if(a_bytes.getAddress() == 0){ 778 getSlotForUpdate(a_bytes); 779 } 780 a_bytes.writeEncrypt(); 781 } 782 783 public void setNextTimeStampId(long val) { 784 _timeStampIdGenerator.setMinimumNext(val); 785 _timeStampIdGenerator.setClean(); 786 } 787 788 public SystemInfo systemInfo() { 789 return new SystemInfoFileImpl(this); 790 } 791 792 public FileHeader getFileHeader() { 793 return _fileHeader; 794 } 795 796 public void installDebugFreespaceManager(FreespaceManager manager) { 797 _freespaceManager = manager; 798 } 799 800 public SystemData systemData() { 801 return _systemData; 802 } 803 804 public long[] getIDsForClass(Transaction trans, YapClass clazz){ 805 final IntArrayList ids = new IntArrayList(); 806 clazz.index().traverseAll(trans, new Visitor4() { 807 public void visit(Object obj) { 808 ids.add(((Integer )obj).intValue()); 809 } 810 }); 811 return ids.asLong(); 812 } 813 814 public QueryResult classOnlyQuery(Transaction trans, YapClass clazz){ 815 if (!clazz.hasIndex()) { 816 817 return null; 822 } 823 824 final AbstractQueryResult queryResult = newQueryResult(trans); 825 queryResult.loadFromClassIndex(clazz); 826 return queryResult; 827 } 828 829 public QueryResult executeQuery(QQuery query){ 830 AbstractQueryResult queryResult = newQueryResult(query.getTransaction()); 831 queryResult.loadFromQuery(query); 832 return queryResult; 833 } 834 835 } | Popular Tags |