1 8 9 package com.sleepycat.je; 10 11 import java.util.ArrayList ; 12 import java.util.Comparator ; 13 import java.util.Iterator ; 14 import java.util.List ; 15 import java.util.logging.Level ; 16 import java.util.logging.Logger ; 17 18 import com.sleepycat.je.dbi.DatabaseImpl; 19 import com.sleepycat.je.dbi.EnvironmentImpl; 20 import com.sleepycat.je.dbi.GetMode; 21 import com.sleepycat.je.dbi.PutMode; 22 import com.sleepycat.je.dbi.TruncateResult; 23 import com.sleepycat.je.dbi.CursorImpl.SearchMode; 24 import com.sleepycat.je.txn.Locker; 25 import com.sleepycat.je.txn.LockerFactory; 26 import com.sleepycat.je.utilint.DatabaseUtil; 27 import com.sleepycat.je.utilint.TinyHashSet; 28 import com.sleepycat.je.utilint.Tracer; 29 30 public class Database { 31 32 35 static class DbState { 36 private String stateName; 37 38 DbState(String stateName) { 39 this.stateName = stateName; 40 } 41 42 public String toString() { 43 return "DbState." + stateName; 44 } 45 } 46 47 static DbState OPEN = new DbState("OPEN"); 48 static DbState CLOSED = new DbState("CLOSED"); 49 static DbState INVALID = new DbState("INVALID"); 50 51 52 private DbState state; 53 54 55 Environment envHandle; private DatabaseImpl databaseImpl; 57 58 DatabaseConfig configuration; 60 61 private boolean isWritable; 62 63 64 Locker handleLocker; 65 66 67 private TinyHashSet cursors = new TinyHashSet(); 68 69 75 private List triggerList; 76 77 private Logger logger; 78 79 83 protected Database(Environment env) { 84 this.envHandle = env; 85 handleLocker = null; 86 logger = envHandle.getEnvironmentImpl().getLogger(); 87 } 88 89 92 void initNew(Environment env, 93 Locker locker, 94 String databaseName, 95 DatabaseConfig dbConfig) 96 throws DatabaseException { 97 98 dbConfig.validateForNewDb(); 99 100 init(env, dbConfig); 101 102 103 EnvironmentImpl environmentImpl = 104 DbInternal.envGetEnvironmentImpl(envHandle); 105 databaseImpl = environmentImpl.createDb(locker, 106 databaseName, 107 dbConfig, 108 this); 109 databaseImpl.addReferringHandle(this); 110 } 111 112 115 void initExisting(Environment env, 116 Locker locker, 117 DatabaseImpl databaseImpl, 118 DatabaseConfig dbConfig) 119 throws DatabaseException { 120 121 125 validateConfigAgainstExistingDb(dbConfig, databaseImpl); 126 127 init(env, dbConfig); 128 this.databaseImpl = databaseImpl; 129 databaseImpl.addReferringHandle(this); 130 131 135 configuration.setSortedDuplicates(databaseImpl.getSortedDuplicates()); 136 configuration.setTransactional(databaseImpl.isTransactional()); 137 } 138 139 private void init(Environment env, 140 DatabaseConfig config) 141 throws DatabaseException { 142 143 handleLocker = null; 144 145 envHandle = env; 146 configuration = config.cloneConfig(); 147 isWritable = !configuration.getReadOnly(); 148 state = OPEN; 149 } 150 151 155 private void validateConfigAgainstExistingDb(DatabaseConfig config, 156 DatabaseImpl databaseImpl) 157 throws DatabaseException { 158 159 163 if (!config.getUseExistingConfig()) { 164 if (databaseImpl.getSortedDuplicates() != 165 config.getSortedDuplicates()) { 166 throw new DatabaseException 167 ("You can't open a Database with a duplicatesAllowed " + 168 "configuration of " + 169 config.getSortedDuplicates() + 170 " if the underlying database was created with a " + 171 "duplicatesAllowedSetting of " + 172 databaseImpl.getSortedDuplicates() + "."); 173 } 174 } 175 176 181 if (databaseImpl.hasOpenHandles()) { 182 if (!config.getUseExistingConfig()) { 183 if (config.getTransactional() != 184 databaseImpl.isTransactional()) { 185 throw new DatabaseException 186 ("You can't open a Database with a transactional " + 187 "configuration of " + config.getTransactional() + 188 " if the underlying database was created with a " + 189 "transactional configuration of " + 190 databaseImpl.isTransactional() + "."); 191 } 192 } 193 } else { 194 databaseImpl.setTransactional(config.getTransactional()); 195 } 196 197 202 if (databaseImpl.hasOpenHandles()) { 203 if (!config.getUseExistingConfig()) { 204 if (config.getDeferredWrite() != 205 databaseImpl.isDeferredWrite()) { 206 throw new DatabaseException 207 ("You can't open a Database with a deferredWrite " + 208 "configuration of " + config.getDeferredWrite() + 209 " if the underlying database was created with a " + 210 "deferredWrite configuration of " + 211 databaseImpl.isDeferredWrite() + "."); 212 } 213 } 214 } else { 215 databaseImpl.setDeferredWrite(config.getDeferredWrite()); 216 } 217 218 221 if (config.getOverrideBtreeComparator()) { 222 databaseImpl.setBtreeComparator 223 (config.getBtreeComparator(), 224 config.getBtreeComparatorByClassName()); 225 } 226 227 if (config.getOverrideDuplicateComparator()) { 228 databaseImpl.setDuplicateComparator 229 (config.getDuplicateComparator(), 230 config.getDuplicateComparatorByClassName()); 231 } 232 } 233 234 public synchronized void close() 235 throws DatabaseException { 236 237 try { 238 closeInternal(); 239 } catch (Error E) { 240 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 241 throw E; 242 } 243 } 244 245 private void closeInternal() 246 throws DatabaseException { 247 248 StringBuffer errors = null; 249 250 checkEnv(); 251 checkProhibitedDbState(CLOSED, "Can't close Database:"); 252 253 trace(Level.FINEST, "Database.close: ", null, null); 254 255 256 removeAllTriggers(); 257 258 envHandle.removeReferringHandle(this); 259 if (cursors.size() > 0) { 260 errors = new StringBuffer 261 ("There are open cursors against the database.\n"); 262 errors.append("They will be closed.\n"); 263 264 268 Iterator iter = cursors.copy().iterator(); 269 while (iter.hasNext()) { 270 Cursor dbc = (Cursor) iter.next(); 271 272 try { 273 dbc.close(); 274 } catch (DatabaseException DBE) { 275 errors.append("Exception while closing cursors:\n"); 276 errors.append(DBE.toString()); 277 } 278 } 279 } 280 281 if (databaseImpl != null) { 282 databaseImpl.removeReferringHandle(this); 283 databaseImpl = null; 284 285 290 handleLocker.setHandleLockOwner(true, this, true); 291 handleLocker.operationEnd(true); 292 state = CLOSED; 293 } 294 295 if (errors != null) { 296 throw new DatabaseException(errors.toString()); 297 } 298 } 299 300 304 public void sync() 305 throws DatabaseException { 306 307 checkEnv(); 308 checkRequiredDbState(OPEN, "Can't call Database.sync:"); 309 checkWritable("sync"); 310 trace(Level.FINEST, "Database.sync", null, null, null, null); 311 312 databaseImpl.sync(true); 313 } 314 315 319 public Sequence openSequence(Transaction txn, 320 DatabaseEntry key, 321 SequenceConfig config) 322 throws DatabaseException { 323 324 try { 325 checkEnv(); 326 DatabaseUtil.checkForNullDbt(key, "key", true); 327 checkRequiredDbState(OPEN, "Can't call Database.openSequence:"); 328 checkWritable("openSequence"); 329 trace(Level.FINEST, "Database.openSequence", txn, key, null, null); 330 331 return new Sequence(this, txn, key, config); 332 } catch (Error E) { 333 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 334 throw E; 335 } 336 } 337 338 342 public void removeSequence(Transaction txn, DatabaseEntry key) 343 throws DatabaseException { 344 345 try { 346 delete(txn, key); 347 } catch (Error E) { 348 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 349 throw E; 350 } 351 } 352 353 public synchronized Cursor openCursor(Transaction txn, 354 CursorConfig cursorConfig) 355 throws DatabaseException { 356 357 try { 358 checkEnv(); 359 checkRequiredDbState(OPEN, "Can't open a cursor"); 360 CursorConfig useConfig = 361 (cursorConfig == null) ? CursorConfig.DEFAULT : cursorConfig; 362 363 if (useConfig.getReadUncommitted() && 364 useConfig.getReadCommitted()) { 365 throw new IllegalArgumentException 366 ("Only one may be specified: " + 367 "ReadCommitted or ReadUncommitted"); 368 } 369 370 trace(Level.FINEST, "Database.openCursor", txn, cursorConfig); 371 Cursor ret = newDbcInstance(txn, useConfig); 372 373 return ret; 374 } catch (Error E) { 375 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 376 throw E; 377 } 378 } 379 380 383 Cursor newDbcInstance(Transaction txn, 384 CursorConfig cursorConfig) 385 throws DatabaseException { 386 387 return new Cursor(this, txn, cursorConfig); 388 } 389 390 public OperationStatus delete(Transaction txn, DatabaseEntry key) 391 throws DatabaseException { 392 393 try { 394 checkEnv(); 395 DatabaseUtil.checkForNullDbt(key, "key", true); 396 checkRequiredDbState(OPEN, "Can't call Database.delete:"); 397 checkWritable("delete"); 398 trace(Level.FINEST, "Database.delete", txn, key, null, null); 399 400 OperationStatus commitStatus = OperationStatus.NOTFOUND; 401 Locker locker = null; 402 try { 403 locker = LockerFactory.getWritableLocker 404 (envHandle, txn, isTransactional()); 405 commitStatus = deleteInternal(locker, key, null); 406 return commitStatus; 407 } finally { 408 if (locker != null) { 409 locker.operationEnd(commitStatus); 410 } 411 } 412 } catch (Error E) { 413 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 414 throw E; 415 } 416 } 417 418 452 453 457 OperationStatus deleteInternal(Locker locker, 458 DatabaseEntry key, 459 DatabaseEntry data) 460 throws DatabaseException { 461 462 Cursor cursor = null; 463 try { 464 cursor = new Cursor(this, locker, null); 465 cursor.setNonCloning(true); 466 OperationStatus commitStatus = OperationStatus.NOTFOUND; 467 468 469 DatabaseEntry oldData; 470 OperationStatus searchStatus; 471 if (data == null) { 472 oldData = new DatabaseEntry(); 473 searchStatus = 474 cursor.search(key, oldData, LockMode.RMW, SearchMode.SET); 475 } else { 476 oldData = data; 477 searchStatus = 478 cursor.search(key, oldData, LockMode.RMW, SearchMode.BOTH); 479 } 480 481 482 if (searchStatus == OperationStatus.SUCCESS) { 483 do { 484 485 490 if (hasTriggers()) { 491 notifyTriggers(locker, key, oldData, null); 492 } 493 494 commitStatus = cursor.deleteNoNotify(); 495 if (commitStatus != OperationStatus.SUCCESS) { 496 return commitStatus; 497 } 498 499 if (data != null) { 500 501 break; 502 } 503 504 505 if (databaseImpl.getSortedDuplicates()) { 506 searchStatus = 507 cursor.retrieveNext(key, oldData, 508 LockMode.RMW, 509 GetMode.NEXT_DUP); 510 } else { 511 searchStatus = OperationStatus.NOTFOUND; 512 } 513 } while (searchStatus == OperationStatus.SUCCESS); 514 commitStatus = OperationStatus.SUCCESS; 515 } 516 return commitStatus; 517 } finally { 518 if (cursor != null) { 519 cursor.close(); 520 } 521 } 522 } 523 524 public OperationStatus get(Transaction txn, 525 DatabaseEntry key, 526 DatabaseEntry data, 527 LockMode lockMode) 528 throws DatabaseException { 529 530 try { 531 checkEnv(); 532 DatabaseUtil.checkForNullDbt(key, "key", true); 533 DatabaseUtil.checkForNullDbt(data, "data", false); 534 checkRequiredDbState(OPEN, "Can't call Database.get:"); 535 trace(Level.FINEST, "Database.get", txn, key, null, lockMode); 536 537 CursorConfig cursorConfig = CursorConfig.DEFAULT; 538 if (lockMode == LockMode.READ_COMMITTED) { 539 cursorConfig = CursorConfig.READ_COMMITTED; 540 lockMode = null; 541 } 542 543 Cursor cursor = null; 544 try { 545 cursor = new Cursor(this, txn, cursorConfig); 546 cursor.setNonCloning(true); 547 return cursor.search(key, data, lockMode, SearchMode.SET); 548 } finally { 549 if (cursor != null) { 550 cursor.close(); 551 } 552 } 553 } catch (Error E) { 554 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 555 throw E; 556 } 557 } 558 559 public OperationStatus getSearchBoth(Transaction txn, 560 DatabaseEntry key, 561 DatabaseEntry data, 562 LockMode lockMode) 563 throws DatabaseException { 564 565 try { 566 checkEnv(); 567 DatabaseUtil.checkForNullDbt(key, "key", true); 568 DatabaseUtil.checkForNullDbt(data, "data", true); 569 checkRequiredDbState(OPEN, "Can't call Database.getSearchBoth:"); 570 trace(Level.FINEST, "Database.getSearchBoth", txn, key, data, 571 lockMode); 572 573 CursorConfig cursorConfig = CursorConfig.DEFAULT; 574 if (lockMode == LockMode.READ_COMMITTED) { 575 cursorConfig = CursorConfig.READ_COMMITTED; 576 lockMode = null; 577 } 578 579 Cursor cursor = null; 580 try { 581 cursor = new Cursor(this, txn, cursorConfig); 582 cursor.setNonCloning(true); 583 return cursor.search(key, data, lockMode, SearchMode.BOTH); 584 } finally { 585 if (cursor != null) { 586 cursor.close(); 587 } 588 } 589 } catch (Error E) { 590 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 591 throw E; 592 } 593 } 594 595 public OperationStatus put(Transaction txn, 596 DatabaseEntry key, 597 DatabaseEntry data) 598 throws DatabaseException { 599 600 checkEnv(); 601 DatabaseUtil.checkForNullDbt(key, "key", true); 602 DatabaseUtil.checkForNullDbt(data, "data", true); 603 DatabaseUtil.checkForPartialKey(key); 604 checkRequiredDbState(OPEN, "Can't call Database.put"); 605 checkWritable("put"); 606 trace(Level.FINEST, "Database.put", txn, key, data, null); 607 608 return putInternal(txn, key, data, PutMode.OVERWRITE); 609 } 610 611 public OperationStatus putNoOverwrite(Transaction txn, 612 DatabaseEntry key, 613 DatabaseEntry data) 614 throws DatabaseException { 615 616 checkEnv(); 617 DatabaseUtil.checkForNullDbt(key, "key", true); 618 DatabaseUtil.checkForNullDbt(data, "data", true); 619 DatabaseUtil.checkForPartialKey(key); 620 checkRequiredDbState(OPEN, "Can't call Database.putNoOverWrite"); 621 checkWritable("putNoOverwrite"); 622 trace(Level.FINEST, "Database.putNoOverwrite", txn, key, data, null); 623 624 return putInternal(txn, key, data, PutMode.NOOVERWRITE); 625 } 626 627 public OperationStatus putNoDupData(Transaction txn, 628 DatabaseEntry key, 629 DatabaseEntry data) 630 throws DatabaseException { 631 632 checkEnv(); 633 DatabaseUtil.checkForNullDbt(key, "key", true); 634 DatabaseUtil.checkForNullDbt(data, "data", true); 635 DatabaseUtil.checkForPartialKey(key); 636 checkRequiredDbState(OPEN, "Can't call Database.putNoDupData"); 637 checkWritable("putNoDupData"); 638 trace(Level.FINEST, "Database.putNoDupData", txn, key, data, null); 639 640 return putInternal(txn, key, data, PutMode.NODUP); 641 } 642 643 646 OperationStatus putInternal(Transaction txn, 647 DatabaseEntry key, 648 DatabaseEntry data, 649 PutMode putMode) 650 throws DatabaseException { 651 652 try { 653 Locker locker = null; 654 Cursor cursor = null; 655 OperationStatus commitStatus = OperationStatus.KEYEXIST; 656 try { 657 locker = LockerFactory.getWritableLocker 658 (envHandle, txn, isTransactional()); 659 660 cursor = new Cursor(this, locker, null); 661 cursor.setNonCloning(true); 662 commitStatus = cursor.putInternal(key, data, putMode); 663 return commitStatus; 664 } finally { 665 if (cursor != null) { 666 cursor.close(); 667 } 668 if (locker != null) { 669 locker.operationEnd(commitStatus); 670 } 671 } 672 } catch (Error E) { 673 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 674 throw E; 675 } 676 } 677 678 680 public JoinCursor join(Cursor[] cursors, JoinConfig config) 681 throws DatabaseException { 682 683 try { 684 checkEnv(); 685 checkRequiredDbState(OPEN, "Can't call Database.join"); 686 DatabaseUtil.checkForNullParam(cursors, "cursors"); 687 if (cursors.length == 0) { 688 throw new IllegalArgumentException 689 ("At least one cursor is required."); 690 } 691 692 697 Locker locker = cursors[0].getCursorImpl().getLocker(); 698 if (!locker.isTransactional()) { 699 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 700 for (int i = 1; i < cursors.length; i += 1) { 701 Locker locker2 = cursors[i].getCursorImpl().getLocker(); 702 if (locker2.isTransactional()) { 703 throw new IllegalArgumentException 704 ("All cursors must use the same transaction."); 705 } 706 EnvironmentImpl env2 = cursors[i].getDatabaseImpl() 707 .getDbEnvironment(); 708 if (env != env2) { 709 throw new IllegalArgumentException 710 ("All cursors must use the same environment."); 711 } 712 } 713 locker = null; 714 } else { 715 for (int i = 1; i < cursors.length; i += 1) { 716 Locker locker2 = cursors[i].getCursorImpl().getLocker(); 717 if (locker.getTxnLocker() != locker2.getTxnLocker()) { 718 throw new IllegalArgumentException 719 ("All cursors must use the same transaction."); 720 } 721 } 722 } 723 724 725 return new JoinCursor(locker, this, cursors, config); 726 } catch (Error E) { 727 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 728 throw E; 729 } 730 } 731 732 739 public int truncate(Transaction txn, boolean countRecords) 740 throws DatabaseException { 741 742 try { 743 checkEnv(); 744 checkRequiredDbState(OPEN, "Can't call Database.truncate"); 745 checkWritable("truncate"); 746 Tracer.trace(Level.FINEST, 747 envHandle.getEnvironmentImpl(), 748 "Database.truncate: txnId=" + 749 ((txn == null) ? 750 "null" : 751 Long.toString(txn.getId()))); 752 753 Locker locker = null; 754 boolean triggerLock = false; 755 boolean operationOk = false; 756 757 try { 758 locker = LockerFactory.getWritableLocker 759 (envHandle, txn, isTransactional(), true , 760 null); 761 762 766 acquireTriggerListReadLock(); 767 triggerLock = true; 768 769 770 int count = truncateInternal(locker, countRecords); 771 772 773 for (int i = 0; i < triggerList.size(); i += 1) { 774 Object obj = triggerList.get(i); 775 if (obj instanceof SecondaryTrigger) { 776 SecondaryDatabase secDb = 777 ((SecondaryTrigger) obj).getDb(); 778 secDb.truncateInternal(locker, false); 779 } 780 } 781 782 operationOk = true; 783 return count; 784 } finally { 785 if (locker != null) { 786 locker.operationEnd(operationOk); 787 } 788 if (triggerLock) { 789 releaseTriggerListReadLock(); 790 } 791 } 792 } catch (Error E) { 793 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 794 throw E; 795 } 796 } 797 798 802 int truncateInternal(Locker locker, boolean countRecords) 803 throws DatabaseException { 804 805 if (databaseImpl == null) { 806 throw new DatabaseException 807 ("couldn't find database - truncate"); 808 } 809 databaseImpl.checkIsDeleted("truncate"); 810 811 816 if (handleLocker.isHandleLockTransferrable()) { 817 handleLocker.transferHandleLock(this, locker, false); 818 } 819 820 boolean operationOk = false; 821 try { 822 823 828 TruncateResult result = 829 envHandle.getEnvironmentImpl().truncate(locker, databaseImpl); 830 databaseImpl = result.getDatabase(); 831 832 operationOk = true; 833 return countRecords ? result.getRecordCount() : -1; 834 } finally { 835 836 841 locker.setHandleLockOwner(operationOk, this, false); 842 } 843 } 844 845 849 public void preload(long maxBytes) 850 throws DatabaseException { 851 852 checkEnv(); 853 checkRequiredDbState(OPEN, "Can't call Database.preload"); 854 databaseImpl.checkIsDeleted("preload"); 855 856 PreloadConfig config = new PreloadConfig(); 857 config.setMaxBytes(maxBytes); 858 databaseImpl.preload(config); 859 } 860 861 865 public void preload(long maxBytes, long maxMillisecs) 866 throws DatabaseException { 867 868 checkEnv(); 869 checkRequiredDbState(OPEN, "Can't call Database.preload"); 870 databaseImpl.checkIsDeleted("preload"); 871 872 PreloadConfig config = new PreloadConfig(); 873 config.setMaxBytes(maxBytes); 874 config.setMaxMillisecs(maxMillisecs); 875 databaseImpl.preload(config); 876 } 877 878 public PreloadStats preload(PreloadConfig config) 879 throws DatabaseException { 880 881 checkEnv(); 882 checkRequiredDbState(OPEN, "Can't call Database.preload"); 883 databaseImpl.checkIsDeleted("preload"); 884 885 return databaseImpl.preload(config); 886 } 887 888 public long count() 889 throws DatabaseException { 890 891 checkEnv(); 892 checkRequiredDbState(OPEN, "Can't call Database.count"); 893 databaseImpl.checkIsDeleted("count"); 894 895 return databaseImpl.count(); 896 } 897 898 public DatabaseStats getStats(StatsConfig config) 899 throws DatabaseException { 900 901 checkEnv(); 902 checkRequiredDbState(OPEN, "Can't call Database.stat"); 903 StatsConfig useConfig = 904 (config == null) ? StatsConfig.DEFAULT : config; 905 906 if (databaseImpl != null) { 907 databaseImpl.checkIsDeleted("stat"); 908 return databaseImpl.stat(useConfig); 909 } 910 return null; 911 } 912 913 public DatabaseStats verify(VerifyConfig config) 914 throws DatabaseException { 915 916 try { 917 checkEnv(); 918 checkRequiredDbState(OPEN, "Can't call Database.verify"); 919 databaseImpl.checkIsDeleted("verify"); 920 VerifyConfig useConfig = 921 (config == null) ? VerifyConfig.DEFAULT : config; 922 923 DatabaseStats stats = databaseImpl.getEmptyStats(); 924 databaseImpl.verify(useConfig, stats); 925 return stats; 926 } catch (Error E) { 927 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 928 throw E; 929 } 930 } 931 932 public String getDatabaseName() 933 throws DatabaseException { 934 935 try { 936 checkEnv(); 937 if (databaseImpl != null) { 938 return databaseImpl.getName(); 939 } else { 940 return null; 941 } 942 } catch (Error E) { 943 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 944 throw E; 945 } 946 } 947 948 952 String getDebugName() { 953 if (databaseImpl != null) { 954 return databaseImpl.getDebugName(); 955 } else { 956 return null; 957 } 958 } 959 960 public DatabaseConfig getConfig() 961 throws DatabaseException { 962 963 try { 964 DatabaseConfig showConfig = configuration.cloneConfig(); 965 966 970 Comparator btComp = null; 971 Comparator dupComp = null; 972 boolean btCompByClass = false; 973 boolean dupCompByClass = false; 974 if (databaseImpl != null) { 975 btComp = databaseImpl.getBtreeComparator(); 976 dupComp = databaseImpl.getDuplicateComparator(); 977 btCompByClass = databaseImpl.getBtreeComparatorByClass(); 978 dupCompByClass = databaseImpl.getDuplicateComparatorByClass(); 979 } 980 showConfig.setBtreeComparatorInternal(btComp, btCompByClass); 981 showConfig.setDuplicateComparatorInternal(dupComp, dupCompByClass); 982 return showConfig; 983 } catch (Error E) { 984 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 985 throw E; 986 } 987 } 988 989 992 boolean isTransactional() 993 throws DatabaseException { 994 995 return databaseImpl.isTransactional(); 996 } 997 998 public Environment getEnvironment() 999 throws DatabaseException { 1000 1001 return envHandle; 1002 } 1003 1004 public List getSecondaryDatabases() 1005 throws DatabaseException { 1006 1007 try { 1008 List list = new ArrayList (); 1009 if (hasTriggers()) { 1010 acquireTriggerListReadLock(); 1011 try { 1012 for (int i = 0; i < triggerList.size(); i += 1) { 1013 Object obj = triggerList.get(i); 1014 if (obj instanceof SecondaryTrigger) { 1015 list.add(((SecondaryTrigger) obj).getDb()); 1016 } 1017 } 1018 } finally { 1019 releaseTriggerListReadLock(); 1020 } 1021 } 1022 return list; 1023 } catch (Error E) { 1024 DbInternal.envGetEnvironmentImpl(envHandle).invalidate(E); 1025 throw E; 1026 } 1027 } 1028 1029 1032 1033 1036 boolean isWritable() { 1037 return isWritable; 1038 } 1039 1040 1043 DatabaseImpl getDatabaseImpl() { 1044 return databaseImpl; 1045 } 1046 1047 1050 void setHandleLocker(Locker locker) { 1051 handleLocker = locker; 1052 } 1053 1054 synchronized void removeCursor(Cursor dbc) { 1055 cursors.remove(dbc); 1056 } 1057 1058 synchronized void addCursor(Cursor dbc) { 1059 cursors.add(dbc); 1060 } 1061 1062 1065 void checkRequiredDbState(DbState required, String msg) 1066 throws DatabaseException { 1067 1068 if (state != required) { 1069 throw new DatabaseException 1070 (msg + " Database state can't be " + state + 1071 " must be " + required); 1072 } 1073 } 1074 1075 1078 void checkProhibitedDbState(DbState prohibited, String msg) 1079 throws DatabaseException { 1080 1081 if (state == prohibited) { 1082 throw new DatabaseException 1083 (msg + " Database state must not be " + prohibited); 1084 } 1085 } 1086 1087 1091 void checkEnv() 1092 throws RunRecoveryException { 1093 1094 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 1095 if (env != null) { 1096 env.checkIfInvalid(); 1097 } 1098 } 1099 1100 1103 synchronized void invalidate() { 1104 state = INVALID; 1105 envHandle.removeReferringHandle(this); 1106 if (databaseImpl != null) { 1107 databaseImpl.removeReferringHandle(this); 1108 } 1109 } 1110 1111 1114 private void checkWritable(String operation) 1115 throws DatabaseException { 1116 1117 if (!isWritable) { 1118 throw new DatabaseException 1119 ("Database is Read Only: " + operation); 1120 } 1121 } 1122 1123 1128 void trace(Level level, 1129 String methodName, 1130 Transaction txn, 1131 DatabaseEntry key, 1132 DatabaseEntry data, 1133 LockMode lockMode) 1134 throws DatabaseException { 1135 1136 if (logger.isLoggable(level)) { 1137 StringBuffer sb = new StringBuffer (); 1138 sb.append(methodName); 1139 if (txn != null) { 1140 sb.append(" txnId=").append(txn.getId()); 1141 } 1142 sb.append(" key=").append(key.dumpData()); 1143 if (data != null) { 1144 sb.append(" data=").append(data.dumpData()); 1145 } 1146 if (lockMode != null) { 1147 sb.append(" lockMode=").append(lockMode); 1148 } 1149 logger.log(level, sb.toString()); 1150 } 1151 } 1152 1153 1158 void trace(Level level, 1159 String methodName, 1160 Transaction txn, 1161 CursorConfig config) 1162 throws DatabaseException { 1163 1164 if (logger.isLoggable(level)) { 1165 StringBuffer sb = new StringBuffer (); 1166 sb.append(methodName); 1167 sb.append(" name=" + getDebugName()); 1168 if (txn != null) { 1169 sb.append(" txnId=").append(txn.getId()); 1170 } 1171 if (config != null) { 1172 sb.append(" config=").append(config); 1173 } 1174 logger.log(level, sb.toString()); 1175 } 1176 } 1177 1178 1181 1182 1187 boolean hasTriggers() { 1188 1189 return triggerList != null; 1190 } 1191 1192 1197 private void acquireTriggerListReadLock() 1198 throws DatabaseException { 1199 1200 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 1201 env.getTriggerLatch().acquireShared(); 1202 if (triggerList == null) { 1203 triggerList = new ArrayList (); 1204 } 1205 } 1206 1207 1210 private void releaseTriggerListReadLock() 1211 throws DatabaseException { 1212 1213 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 1214 env.getTriggerLatch().release(); 1215 } 1216 1217 1222 private void acquireTriggerListWriteLock() 1223 throws DatabaseException { 1224 1225 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 1226 env.getTriggerLatch().acquireExclusive(); 1227 if (triggerList == null) { 1228 triggerList = new ArrayList (); 1229 } 1230 } 1231 1232 1237 private void releaseTriggerListWriteLock() 1238 throws DatabaseException { 1239 1240 if (triggerList.size() == 0) { 1241 triggerList = null; 1242 } 1243 EnvironmentImpl env = envHandle.getEnvironmentImpl(); 1244 env.getTriggerLatch().release(); 1245 } 1246 1247 1253 void addTrigger(DatabaseTrigger trigger, boolean insertAtFront) 1254 throws DatabaseException { 1255 1256 acquireTriggerListWriteLock(); 1257 try { 1258 if (insertAtFront) { 1259 triggerList.add(0, trigger); 1260 } else { 1261 triggerList.add(trigger); 1262 } 1263 trigger.triggerAdded(this); 1264 } finally { 1265 releaseTriggerListWriteLock(); 1266 } 1267 } 1268 1269 1273 void removeTrigger(DatabaseTrigger trigger) 1274 throws DatabaseException { 1275 1276 acquireTriggerListWriteLock(); 1277 try { 1278 triggerList.remove(trigger); 1279 trigger.triggerRemoved(this); 1280 } finally { 1281 releaseTriggerListWriteLock(); 1282 } 1283 } 1284 1285 1290 private void removeAllTriggers() 1291 throws DatabaseException { 1292 1293 acquireTriggerListWriteLock(); 1294 try { 1295 for (int i = 0; i < triggerList.size(); i += 1) { 1296 DatabaseTrigger trigger = (DatabaseTrigger) triggerList.get(i); 1297 trigger.triggerRemoved(this); 1298 } 1299 triggerList.clear(); 1300 } finally { 1301 releaseTriggerListWriteLock(); 1302 } 1303 } 1304 1305 1322 void notifyTriggers(Locker locker, 1323 DatabaseEntry priKey, 1324 DatabaseEntry oldData, 1325 DatabaseEntry newData) 1326 throws DatabaseException { 1327 1328 acquireTriggerListReadLock(); 1329 try { 1330 for (int i = 0; i < triggerList.size(); i += 1) { 1331 DatabaseTrigger trigger = (DatabaseTrigger) triggerList.get(i); 1332 1333 1334 trigger.databaseUpdated 1335 (this, locker, priKey, oldData, newData); 1336 } 1337 } finally { 1338 releaseTriggerListReadLock(); 1339 } 1340 } 1341} 1342 | Popular Tags |