| 1 8 9 package com.sleepycat.je; 10 11 import java.io.File ; 12 import java.io.PrintStream ; 13 import java.util.Collections ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Set ; 18 import java.util.logging.Level ; 19 20 import com.sleepycat.je.dbi.DatabaseImpl; 21 import com.sleepycat.je.dbi.DbConfigManager; 22 import com.sleepycat.je.dbi.DbEnvPool; 23 import com.sleepycat.je.dbi.EnvironmentImpl; 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.Tracer; 28 29 33 public class Environment { 34 35 protected EnvironmentImpl environmentImpl; 36 private TransactionConfig defaultTxnConfig; 37 private EnvironmentMutableConfig handleConfig; 38 39 private Set referringDbs; 40 private Set referringDbTxns; 41 42 private boolean valid; 43 44 48 public static final String CLEANER_NAME = "Cleaner"; 49 50 54 public static final String INCOMP_NAME = "INCompressor"; 55 56 60 public static final String CHECKPOINTER_NAME = "Checkpointer"; 61 62 66 public Environment(File envHome, EnvironmentConfig configuration) 67 throws DatabaseException { 68 69 environmentImpl = null; 70 referringDbs = Collections.synchronizedSet(new HashSet ()); 71 referringDbTxns = Collections.synchronizedSet(new HashSet ()); 72 valid = false; 73 74 DatabaseUtil.checkForNullParam(envHome, "envHome"); 75 76 77 EnvironmentConfig baseConfig = 78 (configuration == null) ? 79 EnvironmentConfig.DEFAULT : 80 configuration; 81 82 83 EnvironmentConfig useConfig = baseConfig.cloneConfig(); 84 applyFileConfig(envHome, useConfig); 85 copyToHandleConfig(useConfig, useConfig); 86 87 88 DbEnvPool.EnvironmentImplInfo envInfo; 89 90 99 do { 100 envInfo = 101 DbEnvPool.getInstance().getEnvironment(envHome, useConfig); 102 environmentImpl = envInfo.envImpl; 103 104 105 environmentImpl.checkIfInvalid(); 106 107 if (!envInfo.firstHandle && configuration != null) { 108 109 110 synchronized (environmentImpl) { 111 112 128 environmentImpl.checkImmutablePropsForEquality(useConfig); 129 } 130 } 131 132 if (!valid) { 133 valid = true; 134 } 135 136 137 environmentImpl.incReferenceCount(); 138 } while (DbEnvPool.getInstance(). 139 getExistingEnvironment(envHome).envImpl != environmentImpl); 140 } 141 142 148 Environment(File envHome) 149 throws DatabaseException { 150 151 environmentImpl = null; 152 valid = false; 153 154 155 DbEnvPool.EnvironmentImplInfo envInfo; 156 while (true) { 157 envInfo = 158 DbEnvPool.getInstance().getExistingEnvironment(envHome); 159 160 EnvironmentImpl foundImpl = envInfo.envImpl; 161 if (foundImpl != null) { 162 163 foundImpl.checkIfInvalid(); 164 165 166 environmentImpl = foundImpl; 167 environmentImpl.incReferenceCount(); 168 169 179 if (DbEnvPool.getInstance(). 180 getExistingEnvironment(envHome).envImpl != 181 environmentImpl) { 182 continue; 183 } 184 185 191 EnvironmentConfig useConfig = 192 EnvironmentConfig.DEFAULT.cloneConfig(); 193 applyFileConfig(envHome, useConfig); 194 copyToHandleConfig(useConfig, useConfig); 195 196 197 referringDbs = Collections.synchronizedSet(new HashSet ()); 198 199 valid = true; 200 break; 201 } 202 } 203 } 204 205 209 private void applyFileConfig(File envHome, 210 EnvironmentMutableConfig useConfig) 211 throws IllegalArgumentException { 212 213 214 if (useConfig.getLoadPropertyFile()) { 215 DbConfigManager.applyFileConfig(envHome, 216 DbInternal.getProps(useConfig), 217 false , 218 useConfig.getClass().getName()); 219 } 220 } 221 222 226 public synchronized void close() 227 throws DatabaseException { 228 229 checkHandleIsValid(); 230 try { 231 checkEnv(); 232 } catch (RunRecoveryException e) { 233 234 240 if (environmentImpl != null) { 241 environmentImpl.closeAfterRunRecovery(); 242 } 243 return; 244 } 245 246 StringBuffer errors = new StringBuffer (); 247 try { 248 if (referringDbs != null) { 249 int nDbs = referringDbs.size(); 250 if (nDbs != 0) { 251 errors.append("There "); 252 if (nDbs == 1) { 253 errors.append 254 ("is 1 open Database in the Environment.\n"); 255 } else { 256 errors.append("are "); 257 errors.append(nDbs); 258 errors.append 259 (" open Database in the Environment.\n"); 260 } 261 errors.append("Closing the following databases:\n"); 262 263 Iterator iter = referringDbs.iterator(); 264 while (iter.hasNext()) { 265 Database db = (Database) iter.next(); 266 270 String dbName = db.getDebugName(); 271 errors.append(dbName).append(" "); 272 try { 273 db.close(); 274 } catch (RunRecoveryException e) { 275 throw e; 276 } catch (DatabaseException DBE) { 277 errors.append("\nWhile closing Database "); 278 errors.append(dbName); 279 errors.append(" encountered exception: "); 280 errors.append(DBE).append("\n"); 281 } 282 } 283 } 284 } 285 286 if (referringDbTxns != null) { 287 int nTxns = referringDbTxns.size(); 288 if (nTxns != 0) { 289 Iterator iter = referringDbTxns.iterator(); 290 errors.append("There "); 291 if (nTxns == 1) { 292 errors.append("is 1 existing transaction opened against"); 293 errors.append(" the Environment.\n"); 294 } else { 295 errors.append("are "); 296 errors.append(nTxns); 297 errors.append(" existing transactions opened against"); 298 errors.append(" the Environment.\n"); 299 } 300 errors.append("Aborting open transactions ...\n"); 301 302 while (iter.hasNext()) { 303 Transaction txn = (Transaction) iter.next(); 304 try { 305 txn.abort(); 306 } catch (RunRecoveryException e) { 307 throw e; 308 } catch (DatabaseException DBE) { 309 errors.append("\nWhile aborting transaction "); 310 errors.append(txn.getId()); 311 errors.append(" encountered exception: "); 312 errors.append(DBE).append("\n"); 313 } 314 } 315 } 316 } 317 318 try { 319 environmentImpl.close(); 320 } catch (RunRecoveryException e) { 321 throw e; 322 } catch (DatabaseException DBE) { 323 errors.append 324 ("\nWhile closing Environment encountered exception: "); 325 errors.append(DBE).append("\n"); 326 } 327 } finally { 328 environmentImpl = null; 329 valid = false; 330 if (errors.length() > 0) { 331 throw new DatabaseException(errors.toString()); 332 } 333 } 334 } 335 336 340 public synchronized Database openDatabase(Transaction txn, 341 String databaseName, 342 DatabaseConfig dbConfig) 343 throws DatabaseException { 344 345 try { 346 if (dbConfig == null) { 347 dbConfig = DatabaseConfig.DEFAULT; 348 } 349 Database db = new Database(this); 350 openDb(txn, db, databaseName, dbConfig, false); 351 return db; 352 } catch (Error E) { 353 environmentImpl.invalidate(E); 354 throw E; 355 } 356 } 357 358 362 public synchronized 363 SecondaryDatabase openSecondaryDatabase(Transaction txn, 364 String databaseName, 365 Database primaryDatabase, 366 SecondaryConfig dbConfig) 367 throws DatabaseException { 368 369 try { 370 if (dbConfig == null) { 371 dbConfig = SecondaryConfig.DEFAULT; 372 } 373 SecondaryDatabase db = 374 new SecondaryDatabase(this, dbConfig, primaryDatabase); 375 openDb(txn, db, databaseName, dbConfig, 376 dbConfig.getAllowPopulate()); 377 return db; 378 } catch (Error E) { 379 environmentImpl.invalidate(E); 380 throw E; 381 } 382 } 383 384 private void openDb(Transaction txn, 385 Database newDb, 386 String databaseName, 387 DatabaseConfig dbConfig, 388 boolean needWritableLockerForInit) 389 throws DatabaseException { 390 391 checkEnv(); 392 DatabaseUtil.checkForNullParam(databaseName, "databaseName"); 393 394 Tracer.trace(Level.FINEST, environmentImpl, "Environment.open: " + 395 " name=" + databaseName + 396 " dbConfig=" + dbConfig); 397 398 402 validateDbConfigAgainstEnv(dbConfig, databaseName); 403 404 Locker locker = null; 405 boolean operationOk = false; 406 boolean dbIsClosing = false; 407 try { 408 409 418 boolean isWritableLocker; 419 if (needWritableLockerForInit) { 420 locker = LockerFactory.getWritableLocker 421 (this, 422 txn, 423 dbConfig.getTransactional(), 424 true, null); 426 isWritableLocker = true; 427 } else { 428 locker = LockerFactory.getReadableLocker 429 (this, txn, 430 dbConfig.getTransactional(), 431 true, false); isWritableLocker = !dbConfig.getTransactional() || 434 locker.isTransactional(); 435 } 436 437 DatabaseImpl database = environmentImpl.getDb(locker, 438 databaseName, 439 newDb); 440 boolean databaseExists = 441 (database == null) ? false : 442 ((database.isDeleted()) ? false : true); 443 444 if (databaseExists) { 445 if (dbConfig.getAllowCreate() && 446 dbConfig.getExclusiveCreate()) { 447 448 dbIsClosing = true; 449 throw new DatabaseException 450 ("Database " + databaseName + " already exists"); 451 } 452 453 newDb.initExisting(this, locker, database, dbConfig); 454 } else { 455 456 if (dbConfig.getAllowCreate()) { 457 458 462 if (!isWritableLocker) { 463 locker.operationEnd(OperationStatus.SUCCESS); 464 locker = LockerFactory.getWritableLocker 465 (this, 466 txn, 467 dbConfig.getTransactional(), 468 true, null); 470 isWritableLocker = true; 471 } 472 473 newDb.initNew(this, locker, databaseName, dbConfig); 474 } else { 475 476 throw new DatabaseNotFoundException("Database " + 477 databaseName + 478 " not found."); 479 } 480 } 481 482 operationOk = true; 483 addReferringHandle(newDb); 484 } finally { 485 486 492 if (locker != null) { 493 locker.setHandleLockOwner(operationOk, newDb, dbIsClosing); 494 locker.operationEnd(operationOk); 495 } 496 } 497 } 498 499 private void validateDbConfigAgainstEnv(DatabaseConfig dbConfig, 500 String databaseName) 501 throws DatabaseException { 502 503 504 if (dbConfig.getTransactional() && 505 !(environmentImpl.isTransactional())) { 506 throw new DatabaseException 507 ("Attempted to open Database " + databaseName + 508 " transactionally, but parent Environment is" + 509 " not transactional"); 510 } 511 512 513 if (environmentImpl.isReadOnly() && (!dbConfig.getReadOnly())) { 514 throw new DatabaseException 515 ("Attempted to open Database " + databaseName + 516 " as writable but parent Environment is read only "); 517 } 518 } 519 520 524 public void removeDatabase(Transaction txn, 525 String databaseName) 526 throws DatabaseException { 527 528 checkHandleIsValid(); 529 checkEnv(); 530 DatabaseUtil.checkForNullParam(databaseName, "databaseName"); 531 532 Locker locker = null; 533 boolean operationOk = false; 534 try { 535 536 540 locker = LockerFactory.getWritableLocker 541 (this, txn, 542 environmentImpl.isTransactional(), 543 true , 544 null); 545 environmentImpl.dbRemove(locker, databaseName); 546 operationOk = true; 547 } catch (Error E) { 548 environmentImpl.invalidate(E); 549 throw E; 550 } finally { 551 if (locker != null) { 552 locker.operationEnd(operationOk); 553 } 554 } 555 } 556 557 561 public void renameDatabase(Transaction txn, 562 String databaseName, 563 String newName) 564 throws DatabaseException { 565 566 DatabaseUtil.checkForNullParam(databaseName, "databaseName"); 567 DatabaseUtil.checkForNullParam(newName, "newName"); 568 569 checkHandleIsValid(); 570 checkEnv(); 571 572 Locker locker = null; 573 boolean operationOk = false; 574 try { 575 576 580 locker = LockerFactory.getWritableLocker 581 (this, txn, 582 environmentImpl.isTransactional(), 583 true , 584 null); 585 environmentImpl.dbRename(locker, databaseName, newName); 586 operationOk = true; 587 } catch (Error E) { 588 environmentImpl.invalidate(E); 589 throw E; 590 } finally { 591 if (locker != null) { 592 locker.operationEnd(operationOk); 593 } 594 } 595 } 596 597 601 public long truncateDatabase(Transaction txn, 602 String databaseName, 603 boolean returnCount) 604 throws DatabaseException { 605 606 checkHandleIsValid(); 607 checkEnv(); 608 DatabaseUtil.checkForNullParam(databaseName, "databaseName"); 609 610 Locker locker = null; 611 boolean operationOk = false; 612 long count = 0; 613 try { 614 615 619 locker = LockerFactory.getWritableLocker 620 (this, txn, 621 environmentImpl.isTransactional(), 622 true , 623 null); 624 625 count = environmentImpl.truncate(locker, 626 databaseName, 627 returnCount); 628 629 operationOk = true; 630 } catch (Error E) { 631 environmentImpl.invalidate(E); 632 throw E; 633 } finally { 634 if (locker != null) { 635 locker.operationEnd(operationOk); 636 } 637 } 638 return count; 639 } 640 641 645 long getMemoryUsage() 646 throws DatabaseException { 647 648 checkHandleIsValid(); 649 checkEnv(); 650 651 return environmentImpl.getMemoryBudget().getCacheMemoryUsage(); 652 } 653 654 658 public File getHome() 659 throws DatabaseException { 660 661 checkHandleIsValid(); 662 return environmentImpl.getEnvironmentHome(); 663 } 664 665 668 669 672 TransactionConfig getDefaultTxnConfig() { 673 return defaultTxnConfig; 674 } 675 676 680 private void copyToHandleConfig(EnvironmentMutableConfig useConfig, 681 EnvironmentConfig initStaticConfig) 682 throws DatabaseException { 683 684 688 EnvironmentMutableConfig newHandleConfig = 689 new EnvironmentMutableConfig(); 690 useConfig.copyHandlePropsTo(newHandleConfig); 691 this.handleConfig = newHandleConfig; 692 693 TransactionConfig newTxnConfig = 694 TransactionConfig.DEFAULT.cloneConfig(); 695 newTxnConfig.setNoSync(handleConfig.getTxnNoSync()); 696 newTxnConfig.setWriteNoSync(handleConfig.getTxnWriteNoSync()); 697 if (initStaticConfig != null) { 698 newTxnConfig.setSerializableIsolation 699 (initStaticConfig.getTxnSerializableIsolation()); 700 newTxnConfig.setReadCommitted 701 (initStaticConfig.getTxnReadCommitted()); 702 } else { 703 newTxnConfig.setSerializableIsolation 704 (defaultTxnConfig.getSerializableIsolation()); 705 newTxnConfig.setReadCommitted 706 (defaultTxnConfig.getReadCommitted()); 707 } 708 this.defaultTxnConfig = newTxnConfig; 709 } 710 711 715 public Transaction beginTransaction(Transaction parent, 716 TransactionConfig txnConfig) 717 throws DatabaseException { 718 719 try { 720 return beginTransactionInternal(parent, txnConfig); 721 } catch (Error E) { 722 environmentImpl.invalidate(E); 723 throw E; 724 } 725 } 726 727 private Transaction beginTransactionInternal(Transaction parent, 728 TransactionConfig txnConfig) 729 throws DatabaseException { 730 731 checkHandleIsValid(); 732 checkEnv(); 733 734 if (!environmentImpl.isTransactional()) { 735 throw new DatabaseException 736 ("Transactions can not be used in a non-transactional " + 737 "environment"); 738 } 739 740 if (txnConfig != null && 741 ((txnConfig.getSerializableIsolation() && 742 txnConfig.getReadUncommitted()) || 743 (txnConfig.getSerializableIsolation() && 744 txnConfig.getReadCommitted()) || 745 (txnConfig.getReadUncommitted() && 746 txnConfig.getReadCommitted()))) { 747 throw new IllegalArgumentException  748 ("Only one may be specified: SerializableIsolation, " + 749 "ReadCommitted or ReadUncommitted"); 750 } 751 752 757 TransactionConfig useConfig = null; 758 if (txnConfig == null) { 759 useConfig = defaultTxnConfig; 760 } else { 761 if (defaultTxnConfig.getNoSync() || 762 defaultTxnConfig.getWriteNoSync()) { 763 764 769 if (!txnConfig.getNoSync() && 770 !txnConfig.getSync() && 771 !txnConfig.getWriteNoSync()) { 772 useConfig = txnConfig.cloneConfig(); 773 if (defaultTxnConfig.getWriteNoSync()) { 774 useConfig.setWriteNoSync(true); 775 } else { 776 useConfig.setNoSync(true); 777 } 778 } 779 } 780 781 782  
|