1 8 9 package com.sleepycat.je.dbi; 10 11 import java.io.PrintStream ; 12 import java.io.UnsupportedEncodingException ; 13 import java.nio.ByteBuffer ; 14 import java.util.ArrayList ; 15 import java.util.List ; 16 import java.util.Map ; 17 18 import com.sleepycat.je.Database; 19 import com.sleepycat.je.DatabaseConfig; 20 import com.sleepycat.je.DatabaseEntry; 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.DatabaseNotFoundException; 23 import com.sleepycat.je.DeadlockException; 24 import com.sleepycat.je.OperationStatus; 25 import com.sleepycat.je.TransactionConfig; 26 import com.sleepycat.je.VerifyConfig; 27 import com.sleepycat.je.dbi.CursorImpl.SearchMode; 28 import com.sleepycat.je.log.LogEntryType; 29 import com.sleepycat.je.log.LogException; 30 import com.sleepycat.je.log.LogReadable; 31 import com.sleepycat.je.log.LogUtils; 32 import com.sleepycat.je.log.LoggableObject; 33 import com.sleepycat.je.tree.ChildReference; 34 import com.sleepycat.je.tree.IN; 35 import com.sleepycat.je.tree.LN; 36 import com.sleepycat.je.tree.MapLN; 37 import com.sleepycat.je.tree.NameLN; 38 import com.sleepycat.je.tree.Tree; 39 import com.sleepycat.je.tree.TreeUtils; 40 import com.sleepycat.je.tree.WithRootLatched; 41 import com.sleepycat.je.txn.AutoTxn; 42 import com.sleepycat.je.txn.BasicLocker; 43 import com.sleepycat.je.txn.LockType; 44 import com.sleepycat.je.txn.Locker; 45 46 49 public class DbTree implements LoggableObject, LogReadable { 50 51 52 public static final DatabaseId ID_DB_ID = new DatabaseId(0); 53 54 public static final DatabaseId NAME_DB_ID = new DatabaseId(1); 55 56 57 private static final String ID_DB_NAME = "_jeIdMap"; 58 private static final String NAME_DB_NAME = "_jeNameMap"; 59 public static final String UTILIZATION_DB_NAME = "_jeUtilization"; 60 public static final String REP_OPERATIONS_NAME = "_jeRepOp"; 61 62 63 private static final String [] RESERVED_DB_NAMES = { 64 ID_DB_NAME, 65 NAME_DB_NAME, 66 UTILIZATION_DB_NAME, 67 REP_OPERATIONS_NAME 68 }; 69 70 71 private int lastAllocatedDbId; 72 73 private DatabaseImpl idDatabase; private DatabaseImpl nameDatabase; private EnvironmentImpl envImpl; 76 77 80 public DbTree() 81 throws DatabaseException { 82 83 this.envImpl = null; 84 idDatabase = new DatabaseImpl(); 85 idDatabase.setDebugDatabaseName(ID_DB_NAME); 86 nameDatabase = new DatabaseImpl(); 87 nameDatabase.setDebugDatabaseName(NAME_DB_NAME); 88 } 89 90 93 public DbTree(EnvironmentImpl env) 94 throws DatabaseException { 95 96 this.envImpl = env; 97 idDatabase = new DatabaseImpl(ID_DB_NAME, 98 new DatabaseId(0), 99 env, 100 new DatabaseConfig()); 101 102 nameDatabase = new DatabaseImpl(NAME_DB_NAME, 103 new DatabaseId(1), 104 env, 105 new DatabaseConfig()); 106 107 lastAllocatedDbId = 1; 108 } 109 110 113 public synchronized int getLastDbId() { 114 return lastAllocatedDbId; 115 } 116 117 120 private synchronized int getNextDbId() { 121 return ++lastAllocatedDbId; 122 } 123 124 127 public synchronized void setLastDbId(int maxDbId) { 128 lastAllocatedDbId = maxDbId; 129 } 130 131 private Locker createMapDbLocker(EnvironmentImpl envImpl) 132 throws DatabaseException { 133 134 if (envImpl.isNoLocking()) { 135 return new BasicLocker(envImpl); 136 } else { 137 return new AutoTxn(envImpl, new TransactionConfig()); 138 } 139 } 140 141 145 void setEnvironmentImpl(EnvironmentImpl envImpl) 146 throws DatabaseException { 147 148 this.envImpl = envImpl; 149 idDatabase.setEnvironmentImpl(envImpl); 150 nameDatabase.setEnvironmentImpl(envImpl); 151 } 152 153 163 public synchronized DatabaseImpl createDb(Locker locker, 164 String databaseName, 165 DatabaseConfig dbConfig, 166 Database databaseHandle) 167 throws DatabaseException { 168 169 170 DatabaseId newId = new DatabaseId(getNextDbId()); 171 DatabaseImpl newDb = new DatabaseImpl(databaseName, 172 newId, 173 envImpl, 174 dbConfig); 175 CursorImpl idCursor = null; 176 CursorImpl nameCursor = null; 177 boolean operationOk = false; 178 Locker idDbLocker = null; 179 try { 180 181 nameCursor = new CursorImpl(nameDatabase, locker); 182 LN nameLN = new NameLN(newId); 183 nameCursor.putLN(databaseName.getBytes("UTF-8"), 184 nameLN, false); 185 186 189 if (databaseHandle != null) { 190 locker.addToHandleMaps(new Long (nameLN.getNodeId()), 191 databaseHandle); 192 } 193 194 195 idDbLocker = new BasicLocker(envImpl); 196 idCursor = new CursorImpl(idDatabase, idDbLocker); 197 idCursor.putLN(newId.getBytes(), new MapLN(newDb), false); 198 operationOk = true; 199 } catch (UnsupportedEncodingException UEE) { 200 throw new DatabaseException(UEE); 201 } finally { 202 if (idCursor != null) { 203 idCursor.close(); 204 } 205 206 if (nameCursor != null) { 207 nameCursor.close(); 208 } 209 210 if (idDbLocker != null) { 211 idDbLocker.operationEnd(operationOk); 212 } 213 } 214 215 return newDb; 216 } 217 224 public void optionalModifyDbRoot(DatabaseImpl db) 225 throws DatabaseException { 226 227 if (db.isDeferredWrite()) { 228 return; 229 } 230 231 modifyDbRoot(db); 232 } 233 234 245 public void modifyDbRoot(DatabaseImpl db) 246 throws DatabaseException { 247 248 if (db.getId().equals(ID_DB_ID) || 249 db.getId().equals(NAME_DB_ID)) { 250 envImpl.logMapTreeRoot(); 251 } else { 252 Locker idDbLocker = new BasicLocker(envImpl); 253 CursorImpl cursor = new CursorImpl(idDatabase, idDbLocker); 254 boolean operationOk = false; 255 try { 256 DatabaseEntry keyDbt = 257 new DatabaseEntry(db.getId().getBytes()); 258 MapLN mapLN = null; 259 260 265 while (true) { 266 try { 267 boolean searchOk = (cursor.searchAndPosition 268 (keyDbt, new DatabaseEntry(), 269 SearchMode.SET, LockType.WRITE) & 270 CursorImpl.FOUND) != 0; 271 if (!searchOk) { 272 throw new DatabaseException( 273 "can't find database " + db.getId()); 274 } 275 mapLN = (MapLN) 276 cursor.getCurrentLNAlreadyLatched(LockType.WRITE); 277 assert mapLN != null; 278 } catch (DeadlockException DE) { 279 cursor.close(); 280 idDbLocker.operationEnd(false); 281 idDbLocker = new BasicLocker(envImpl); 282 cursor = new CursorImpl(idDatabase, idDbLocker); 283 continue; 284 } finally { 285 cursor.releaseBINs(); 286 } 287 break; 288 } 289 290 RewriteMapLN writeMapLN = new RewriteMapLN(cursor); 291 mapLN.getDatabase().getTree(). 292 withRootLatchedExclusive(writeMapLN); 293 294 operationOk = true; 295 } finally { 296 if (cursor != null) { 297 cursor.close(); 298 } 299 300 idDbLocker.operationEnd(operationOk); 301 } 302 } 303 } 304 305 private static class RewriteMapLN implements WithRootLatched { 306 private CursorImpl cursor; 307 308 RewriteMapLN(CursorImpl cursor) { 309 this.cursor = cursor; 310 } 311 312 public IN doWork(ChildReference root) 313 throws DatabaseException { 314 315 DatabaseEntry dataDbt = new DatabaseEntry(new byte[0]); 316 cursor.putCurrent(dataDbt, null, null); 317 return null; 318 } 319 } 320 321 328 private NameLockResult lockNameLN(Locker locker, 329 String databaseName, 330 String action) 331 throws DatabaseException { 332 333 337 NameLockResult result = new NameLockResult(); 338 339 340 result.dbImpl = getDb(locker, databaseName, null); 341 if (result.dbImpl == null) { 342 throw new DatabaseNotFoundException 343 ("Attempted to " + action + " non-existent database " + 344 databaseName); 345 } 346 result.nameCursor = new CursorImpl(nameDatabase, locker); 347 348 try { 349 350 DatabaseEntry key = 351 new DatabaseEntry(databaseName.getBytes("UTF-8")); 352 boolean found = 353 (result.nameCursor.searchAndPosition(key, null, SearchMode.SET, 354 LockType.WRITE) & 355 CursorImpl.FOUND) != 0; 356 if (!found) { 357 result.nameCursor.releaseBIN(); 358 result.nameCursor.close(); 359 result.nameCursor = null; 360 return result; 361 } 362 363 364 result.nameLN = (NameLN) 365 result.nameCursor.getCurrentLNAlreadyLatched(LockType.WRITE); 366 assert result.nameLN != null; 367 368 373 int handleCount = result.dbImpl.getReferringHandleCount(); 374 if (handleCount > 0) { 375 throw new DatabaseException("Can't " + action + " database " + 376 databaseName + "," + handleCount + 377 " open Dbs exist"); 378 } 379 } catch (UnsupportedEncodingException UEE) { 380 result.nameCursor.releaseBIN(); 381 result.nameCursor.close(); 382 throw new DatabaseException(UEE); 383 } catch (DatabaseException e) { 384 result.nameCursor.releaseBIN(); 385 result.nameCursor.close(); 386 throw e; 387 } 388 389 return result; 390 } 391 392 private static class NameLockResult { 393 CursorImpl nameCursor; 394 DatabaseImpl dbImpl; 395 NameLN nameLN; 396 } 397 398 401 boolean dbRename(Locker locker, String databaseName, String newName) 402 throws DatabaseException { 403 404 CursorImpl nameCursor = null; 405 try { 406 NameLockResult result = lockNameLN(locker, databaseName, "rename"); 407 nameCursor = result.nameCursor; 408 if (nameCursor == null) { 409 return false; 410 } else { 411 412 417 nameCursor.latchBIN(); 418 nameCursor.delete(); 419 nameCursor.putLN(newName.getBytes("UTF-8"), 420 new NameLN(result.dbImpl.getId()), false); 421 result.dbImpl.setDebugDatabaseName(newName); 422 return true; 423 } 424 } catch (UnsupportedEncodingException UEE) { 425 throw new DatabaseException(UEE); 426 } finally { 427 if (nameCursor != null) { 428 nameCursor.releaseBIN(); 429 nameCursor.close(); 430 } 431 } 432 } 433 434 437 void dbRemove(Locker locker, String databaseName) 438 throws DatabaseException { 439 440 CursorImpl nameCursor = null; 441 try { 442 NameLockResult result = lockNameLN(locker, databaseName, "remove"); 443 nameCursor = result.nameCursor; 444 if (nameCursor == null) { 445 return; 446 } else { 447 448 454 nameCursor.latchBIN(); 455 nameCursor.delete(); 456 457 462 locker.markDeleteAtTxnEnd(result.dbImpl, true); 463 } 464 } finally { 465 if (nameCursor != null) { 466 nameCursor.releaseBIN(); 467 nameCursor.close(); 468 } 469 } 470 } 471 472 482 long truncate(Locker locker, 483 String databaseName, 484 boolean returnCount) 485 throws DatabaseException { 486 487 CursorImpl nameCursor = null; 488 Locker idDbLocker = null; 489 try { 490 NameLockResult result = lockNameLN(locker, databaseName, 491 "truncate"); 492 nameCursor = result.nameCursor; 493 if (nameCursor == null) { 494 return 0; 495 } else { 496 497 501 DatabaseId newId = new DatabaseId(getNextDbId()); 502 DatabaseImpl newDb = (DatabaseImpl) result.dbImpl.clone(); 503 newDb.setId(newId); 504 newDb.setTree(new Tree(newDb)); 505 506 511 CursorImpl idCursor = null; 512 boolean operationOk = false; 513 try { 514 idDbLocker = new BasicLocker(envImpl); 515 idCursor = new CursorImpl(idDatabase, idDbLocker); 516 idCursor.putLN(newId.getBytes(), 517 new MapLN(newDb), false); 518 operationOk = true; 519 } finally { 520 if (idCursor != null) { 521 idCursor.close(); 522 } 523 524 if (idDbLocker != null) { 525 idDbLocker.operationEnd(operationOk); 526 } 527 } 528 result.nameLN.setId(newDb.getId()); 529 530 531 long recordCount = 0; 532 if (returnCount) { 533 recordCount = result.dbImpl.count(); 534 } 535 536 537 DatabaseEntry dataDbt = new DatabaseEntry(new byte[0]); 538 nameCursor.putCurrent(dataDbt, null, null); 539 540 544 545 546 locker.markDeleteAtTxnEnd(result.dbImpl, true); 547 548 549 locker.markDeleteAtTxnEnd(newDb, false); 550 551 return recordCount; 552 } 553 554 } catch (CloneNotSupportedException CNSE) { 555 throw new DatabaseException(CNSE); 556 } finally { 557 if (nameCursor != null) { 558 nameCursor.releaseBIN(); 559 nameCursor.close(); 560 } 561 } 562 } 563 564 570 void deleteMapLN(DatabaseId id) 571 throws DatabaseException { 572 573 Locker idDbLocker = null; 574 boolean operationOk = false; 575 CursorImpl idCursor = null; 576 577 try { 578 idDbLocker = new BasicLocker(envImpl); 579 idCursor = new CursorImpl(idDatabase, idDbLocker); 580 boolean found = 581 (idCursor.searchAndPosition(new DatabaseEntry(id.getBytes()), 582 null, 583 SearchMode.SET, 584 LockType.WRITE) & 585 CursorImpl.FOUND) != 0; 586 if (found) { 587 idCursor.delete(); 588 } 589 590 operationOk = true; 591 } finally { 592 if (idCursor != null) { 593 idCursor.close(); 594 } 595 596 if (idDbLocker != null) { 597 idDbLocker.operationEnd(operationOk); 598 } 599 } 600 } 601 602 612 TruncateResult truncate(Locker locker, 613 DatabaseImpl oldDatabase, 614 boolean returnCount) 615 throws DatabaseException { 616 617 CursorImpl nameCursor = new CursorImpl(nameDatabase, locker); 618 619 try { 620 String databaseName = getDbName(oldDatabase.getId()); 621 DatabaseEntry keyDbt = 622 new DatabaseEntry(databaseName.getBytes("UTF-8")); 623 boolean found = 624 (nameCursor.searchAndPosition(keyDbt, null, 625 SearchMode.SET, LockType.WRITE) & 626 CursorImpl.FOUND) != 0; 627 if (!found) { 628 629 633 throw new DatabaseException 634 ("Database " + databaseName + " not found in map tree"); 635 } 636 637 638 NameLN nameLN = (NameLN) 639 nameCursor.getCurrentLNAlreadyLatched(LockType.WRITE); 640 assert nameLN != null; 641 642 647 int handleCount = oldDatabase.getReferringHandleCount(); 648 if (handleCount > 1) { 649 throw new DatabaseException("Can't truncate database " + 650 databaseName + "," + handleCount + 651 " open databases exist"); 652 } 653 654 658 DatabaseImpl newDb; 659 DatabaseId newId = new DatabaseId(getNextDbId()); 660 newDb = (DatabaseImpl) oldDatabase.clone(); 661 newDb.setId(newId); 662 newDb.setTree(new Tree(newDb)); 663 664 665 CursorImpl idCursor = null; 666 boolean operationOk = false; 667 Locker idDbLocker = null; 668 try { 669 idDbLocker = new BasicLocker(envImpl); 670 idCursor = new CursorImpl(idDatabase, idDbLocker); 671 idCursor.putLN(newId.getBytes(), 672 new MapLN(newDb), false); 673 operationOk = true; 674 } finally { 675 if (idCursor != null) { 676 idCursor.close(); 677 } 678 679 if (idDbLocker != null) { 680 idDbLocker.operationEnd(operationOk); 681 } 682 } 683 nameLN.setId(newDb.getId()); 684 685 686 long count = 0; 687 if (returnCount) { 688 count = oldDatabase.count(); 689 } 690 691 692 locker.markDeleteAtTxnEnd(oldDatabase, true); 693 694 695 DatabaseEntry dataDbt = new DatabaseEntry(new byte[0]); 696 nameCursor.putCurrent(dataDbt, null, null); 697 698 return new TruncateResult(newDb, (int) count); 699 } catch (CloneNotSupportedException CNSE) { 700 throw new DatabaseException(CNSE); 701 } catch (UnsupportedEncodingException UEE) { 702 throw new DatabaseException(UEE); 703 } finally { 704 nameCursor.releaseBIN(); 705 nameCursor.close(); 706 } 707 } 708 709 720 public DatabaseImpl getDb(Locker nameLocker, 721 String databaseName, 722 Database databaseHandle) 723 throws DatabaseException { 724 725 try { 726 if (databaseName.equals(ID_DB_NAME)) { 727 return idDatabase; 728 } else if (databaseName.equals(NAME_DB_NAME)) { 729 return nameDatabase; 730 } 731 732 736 CursorImpl nameCursor = null; 737 DatabaseId id = null; 738 try { 739 740 nameCursor = new CursorImpl(nameDatabase, nameLocker); 741 DatabaseEntry keyDbt = 742 new DatabaseEntry(databaseName.getBytes("UTF-8")); 743 boolean found = 744 (nameCursor.searchAndPosition(keyDbt, null, 745 SearchMode.SET, 746 LockType.READ) & 747 CursorImpl.FOUND) != 0; 748 749 if (found) { 750 NameLN nameLN = (NameLN) 751 nameCursor.getCurrentLNAlreadyLatched(LockType.READ); 752 assert nameLN != null; 753 id = nameLN.getId(); 754 755 759 if (databaseHandle != null) { 760 nameLocker.addToHandleMaps(new Long (nameLN.getNodeId()), 761 databaseHandle); 762 } 763 } 764 } finally { 765 if (nameCursor != null) { 766 nameCursor.releaseBIN(); 767 nameCursor.close(); 768 } 769 } 770 771 774 if (id == null) { 775 return null; 776 } else { 777 return getDb(id, -1, databaseName); 778 } 779 } catch (UnsupportedEncodingException UEE) { 780 throw new DatabaseException(UEE); 781 } 782 } 783 784 789 public DatabaseImpl getDb(DatabaseId dbId) 790 throws DatabaseException { 791 792 return getDb(dbId, -1); 793 } 794 795 801 public DatabaseImpl getDb(DatabaseId dbId, long lockTimeout) 802 throws DatabaseException { 803 804 return getDb(dbId, lockTimeout, (String ) null); 805 } 806 807 811 public DatabaseImpl getDb(DatabaseId dbId, long lockTimeout, Map dbCache) 812 throws DatabaseException { 813 814 if (dbCache.containsKey(dbId)) { 815 return (DatabaseImpl) dbCache.get(dbId); 816 } else { 817 DatabaseImpl db = getDb(dbId, lockTimeout, (String ) null); 818 dbCache.put(dbId, db); 819 return db; 820 } 821 } 822 823 832 public DatabaseImpl getDb(DatabaseId dbId, 833 long lockTimeout, 834 String dbNameIfAvailable) 835 throws DatabaseException { 836 837 if (dbId.equals(idDatabase.getId())) { 838 839 return idDatabase; 840 } else if (dbId.equals(nameDatabase.getId())) { 841 842 return nameDatabase; 843 } else { 844 Locker locker = new BasicLocker(envImpl); 845 if (lockTimeout != -1) { 846 locker.setLockTimeout(lockTimeout); 847 } 848 849 850 CursorImpl idCursor = null; 851 DatabaseImpl foundDbImpl = null; 852 853 857 while (true) { 858 idCursor = new CursorImpl(idDatabase, locker); 859 try { 860 DatabaseEntry keyDbt = new DatabaseEntry(dbId.getBytes()); 861 boolean found = 862 (idCursor.searchAndPosition 863 (keyDbt, new DatabaseEntry(), SearchMode.SET, 864 LockType.READ) & 865 CursorImpl.FOUND) != 0; 866 if (found) { 867 MapLN mapLN = (MapLN) 868 idCursor.getCurrentLNAlreadyLatched(LockType.READ); 869 assert mapLN != null; 870 foundDbImpl = mapLN.getDatabase(); 871 } 872 break; 873 } catch (DeadlockException DE) { 874 idCursor.close(); 875 locker.operationEnd(false); 876 locker = new BasicLocker(envImpl); 877 if (lockTimeout != -1) { 878 locker.setLockTimeout(lockTimeout); 879 } 880 idCursor = new CursorImpl(idDatabase, locker); 881 continue; 882 } finally { 883 idCursor.releaseBIN(); 884 idCursor.close(); 885 locker.operationEnd(true); 886 } 887 } 888 889 893 if (envImpl.isOpen()) { 894 setDebugNameForDatabaseImpl(foundDbImpl, dbNameIfAvailable); 895 } 896 897 return foundDbImpl; 898 } 899 } 900 901 908 private void setDebugNameForDatabaseImpl(DatabaseImpl dbImpl, 909 String dbName) 910 throws DatabaseException { 911 912 if (dbImpl != null) { 913 if (dbName != null) { 914 915 dbImpl.setDebugDatabaseName(dbName); 916 } else if (dbImpl.getDebugName() == null) { 917 921 dbImpl.setDebugDatabaseName(getDbName(dbImpl.getId())); 922 } 923 } 924 } 925 926 929 public void rebuildINListMapDb() 930 throws DatabaseException { 931 932 idDatabase.getTree().rebuildINList(); 933 } 934 935 938 public boolean verify(VerifyConfig config, PrintStream out) 939 throws DatabaseException { 940 941 boolean ret = true; 942 try { 943 944 boolean ok = idDatabase.verify(config, 945 idDatabase.getEmptyStats()); 946 if (!ok) { 947 ret = false; 948 } 949 950 ok = nameDatabase.verify(config, 951 nameDatabase.getEmptyStats()); 952 if (!ok) { 953 ret = false; 954 } 955 } catch (DatabaseException DE) { 956 ret = false; 957 } 958 959 synchronized (envImpl.getINCompressor()) { 960 961 970 Locker locker = null; 971 CursorImpl cursor = null; 972 LockType lockType = LockType.NONE; 973 try { 974 locker = new BasicLocker(envImpl); 975 cursor = new CursorImpl(idDatabase, locker); 976 977 cursor.setAllowEviction(true); 978 if (cursor.positionFirstOrLast(true, null)) { 979 MapLN mapLN = (MapLN) cursor. 980 getCurrentLNAlreadyLatched(lockType); 981 982 DatabaseEntry keyDbt = new DatabaseEntry(); 983 DatabaseEntry dataDbt = new DatabaseEntry(); 984 while (true) { 985 if (mapLN != null && !mapLN.isDeleted()) { 986 DatabaseImpl dbImpl = mapLN.getDatabase(); 987 boolean ok = dbImpl.verify(config, 988 dbImpl.getEmptyStats()); 989 if (!ok) { 990 ret = false; 991 } 992 } 993 994 OperationStatus status = 995 cursor.getNext(keyDbt, dataDbt, lockType, 996 true, false); if (status != OperationStatus.SUCCESS) { 999 break; 1000 } 1001 mapLN = (MapLN) cursor.getCurrentLN(lockType); 1002 } 1003 } 1004 } catch (DatabaseException e) { 1005 e.printStackTrace(out); 1006 ret = false; 1007 } finally { 1008 if (cursor != null) { 1009 cursor.releaseBINs(); 1010 cursor.close(); 1011 } 1012 if (locker != null) { 1013 locker.operationEnd(); 1014 } 1015 } 1016 } 1017 1018 return ret; 1019 } 1020 1021 1028 public String getDbName(DatabaseId id) 1029 throws DatabaseException { 1030 1031 if (id.equals(ID_DB_ID)) { 1032 return ID_DB_NAME; 1033 } else if (id.equals(NAME_DB_ID)) { 1034 return NAME_DB_NAME; 1035 } 1036 1037 Locker locker = null; 1038 CursorImpl cursor = null; 1039 try { 1040 locker = new BasicLocker(envImpl); 1041 cursor = new CursorImpl(nameDatabase, locker); 1042 1043 DatabaseEntry keyDbt = new DatabaseEntry(); 1044 DatabaseEntry dataDbt = new DatabaseEntry(); 1045 String name = null; 1046 if (cursor.positionFirstOrLast(true, null)) { 1047 1048 OperationStatus status = cursor.getCurrentAlreadyLatched 1049 (keyDbt, dataDbt, LockType.NONE, true); 1050 do { 1051 if (status == OperationStatus.SUCCESS) { 1052 NameLN nameLN = (NameLN) cursor.getCurrentLN 1053 (LockType.NONE); 1054 if (nameLN != null && nameLN.getId().equals(id)) { 1055 name = new String (keyDbt.getData(), "UTF-8"); 1056 break; 1057 } 1058 } 1059 1060 1061 status = cursor.getNext(keyDbt, dataDbt, LockType.NONE, 1062 true, false); } while (status == OperationStatus.SUCCESS); 1065 } 1066 return name; 1067 } catch (UnsupportedEncodingException UEE) { 1068 throw new DatabaseException(UEE); 1069 } finally { 1070 if (cursor != null) { 1071 cursor.releaseBINs(); 1072 cursor.close(); 1073 } 1074 if (locker != null) { 1075 locker.operationEnd(); 1076 } 1077 } 1078 } 1079 1080 1083 public List getDbNames() 1084 throws DatabaseException { 1085 1086 List nameList = new ArrayList (); 1087 Locker locker = null; 1088 CursorImpl cursor = null; 1089 try { 1090 locker = new BasicLocker(envImpl); 1091 cursor = new CursorImpl(nameDatabase, locker); 1092 1093 cursor.setAllowEviction(true); 1094 DatabaseEntry keyDbt = new DatabaseEntry(); 1095 DatabaseEntry dataDbt = new DatabaseEntry(); 1096 if (cursor.positionFirstOrLast(true, null)) { 1097 OperationStatus status = cursor.getCurrentAlreadyLatched 1098 (keyDbt, dataDbt, LockType.READ, true); 1099 do { 1100 if (status == OperationStatus.SUCCESS) { 1101 String name = new String (keyDbt.getData(), "UTF-8"); 1102 if (!isReservedDbName(name)) { 1103 nameList.add(name); 1104 } 1105 } 1106 1107 1108 status = cursor.getNext(keyDbt, dataDbt, LockType.READ, 1109 true, false); } while (status == OperationStatus.SUCCESS); 1112 } 1113 return nameList; 1114 } catch (UnsupportedEncodingException UEE) { 1115 throw new DatabaseException(UEE); 1116 } finally { 1117 if (cursor != null) { 1118 cursor.close(); 1119 } 1120 1121 if (locker != null) { 1122 locker.operationEnd(); 1123 } 1124 } 1125 } 1126 1127 1131 public List getInternalNoLookupDbNames() { 1132 List names = new ArrayList (); 1133 names.add(ID_DB_NAME); 1134 names.add(NAME_DB_NAME); 1135 return names; 1136 } 1137 1138 1141 public List getInternalDbNames() { 1142 List names = new ArrayList (); 1143 names.add(UTILIZATION_DB_NAME); 1144 return names; 1145 } 1146 1147 1150 public boolean isReservedDbName(String name) { 1151 for (int i = 0; i < RESERVED_DB_NAMES.length; i += 1) { 1152 if (RESERVED_DB_NAMES[i].equals(name)) { 1153 return true; 1154 } 1155 } 1156 return false; 1157 } 1158 1159 1162 public int getHighestLevel() 1163 throws DatabaseException { 1164 1165 1166 int idHighLevel = getHighestLevel(idDatabase); 1167 1168 1169 int nameHighLevel = getHighestLevel(nameDatabase); 1170 1171 return (nameHighLevel > idHighLevel) ? nameHighLevel : idHighLevel; 1172 } 1173 1174 1177 public int getHighestLevel(DatabaseImpl dbImpl) 1178 throws DatabaseException { 1179 1180 1181 RootLevel getLevel = new RootLevel(dbImpl); 1182 dbImpl.getTree().withRootLatchedShared(getLevel); 1183 return getLevel.getRootLevel(); 1184 } 1185 1186 1189 private static class RootLevel implements WithRootLatched { 1190 private DatabaseImpl db; 1191 private int rootLevel; 1192 1193 RootLevel(DatabaseImpl db) { 1194 this.db = db; 1195 rootLevel = 0; 1196 } 1197 1198 public IN doWork(ChildReference root) 1199 throws DatabaseException { 1200 1201 IN rootIN = (IN) root.fetchTarget(db, null); 1202 rootLevel = rootIN.getLevel(); 1203 return null; 1204 } 1205 1206 int getRootLevel() { 1207 return rootLevel; 1208 } 1209 } 1210 1211 1214 1215 1218 public LogEntryType getLogType() { 1219 return LogEntryType.LOG_ROOT; 1220 } 1221 1222 1226 public boolean marshallOutsideWriteLatch() { 1227 return true; 1228 } 1229 1230 1233 public boolean countAsObsoleteWhenLogged() { 1234 return false; 1235 } 1236 1237 1240 public int getLogSize() { 1241 return 1242 LogUtils.getIntLogSize() + idDatabase.getLogSize() + nameDatabase.getLogSize(); } 1246 1247 1250 public void writeToLog(ByteBuffer logBuffer) { 1251 LogUtils.writeInt(logBuffer,lastAllocatedDbId); idDatabase.writeToLog(logBuffer); nameDatabase.writeToLog(logBuffer); } 1255 1256 1259 public void postLogWork(long justLoggedLsn) 1260 throws DatabaseException { 1261 } 1262 1263 1266 1267 1270 public void readFromLog(ByteBuffer itemBuffer, byte entryTypeVersion) 1271 throws LogException { 1272 1273 lastAllocatedDbId = LogUtils.readInt(itemBuffer); idDatabase.readFromLog(itemBuffer, entryTypeVersion); nameDatabase.readFromLog(itemBuffer, entryTypeVersion); } 1277 1278 1281 public void dumpLog(StringBuffer sb, boolean verbose) { 1282 sb.append("<dbtree lastId = \""); 1283 sb.append(lastAllocatedDbId); 1284 sb.append("\">"); 1285 sb.append("<idDb>"); 1286 idDatabase.dumpLog(sb, verbose); 1287 sb.append("</idDb><nameDb>"); 1288 nameDatabase.dumpLog(sb, verbose); 1289 sb.append("</nameDb>"); 1290 sb.append("</dbtree>"); 1291 } 1292 1293 1296 public boolean logEntryIsTransactional() { 1297 return false; 1298 } 1299 1300 1303 public long getTransactionId() { 1304 return 0; 1305 } 1306 1307 1310 1311 String dumpString(int nSpaces) { 1312 StringBuffer self = new StringBuffer (); 1313 self.append(TreeUtils.indent(nSpaces)); 1314 self.append("<dbTree lastDbId =\""); 1315 self.append(lastAllocatedDbId); 1316 self.append("\">"); 1317 self.append('\n'); 1318 self.append(idDatabase.dumpString(nSpaces + 1)); 1319 self.append('\n'); 1320 self.append(nameDatabase.dumpString(nSpaces + 1)); 1321 self.append('\n'); 1322 self.append("</dbtree>"); 1323 return self.toString(); 1324 } 1325 1326 public String toString() { 1327 return dumpString(0); 1328 } 1329 1330 1333 public void dump() 1334 throws DatabaseException { 1335 1336 idDatabase.getTree().dump(); 1337 nameDatabase.getTree().dump(); 1338 } 1339} 1340 | Popular Tags |