1 21 22 package org.apache.derby.impl.store.raw.xact; 23 24 import org.apache.derby.iapi.reference.Property; 25 import org.apache.derby.iapi.reference.SQLState; 26 27 import org.apache.derby.iapi.services.context.ContextService; 28 import org.apache.derby.iapi.services.context.ContextManager; 29 import org.apache.derby.iapi.services.daemon.DaemonService; 30 import org.apache.derby.iapi.services.daemon.Serviceable; 31 import org.apache.derby.iapi.services.locks.LockFactory; 32 import org.apache.derby.iapi.services.monitor.ModuleControl; 33 import org.apache.derby.iapi.services.monitor.ModuleSupportable; 34 import org.apache.derby.iapi.services.monitor.Monitor; 35 import org.apache.derby.iapi.services.sanity.SanityManager; 36 import org.apache.derby.iapi.services.io.Formatable; 37 import org.apache.derby.iapi.services.io.FormatIdUtil; 38 import org.apache.derby.iapi.services.uuid.UUIDFactory; 39 import org.apache.derby.catalog.UUID; 40 41 import org.apache.derby.iapi.store.access.AccessFactoryGlobals; 42 import org.apache.derby.iapi.store.access.TransactionController; 43 import org.apache.derby.iapi.store.access.TransactionInfo; 44 45 import org.apache.derby.iapi.store.access.AccessFactory; 46 47 import org.apache.derby.iapi.store.access.xa.XAResourceManager; 48 49 import org.apache.derby.iapi.store.raw.LockingPolicy; 50 import org.apache.derby.iapi.store.raw.GlobalTransactionId; 51 import org.apache.derby.iapi.store.raw.RawStoreFactory; 52 import org.apache.derby.iapi.store.raw.Transaction; 53 54 import org.apache.derby.iapi.store.raw.data.DataFactory; 55 56 import org.apache.derby.iapi.store.raw.log.LogFactory; 57 import org.apache.derby.iapi.store.raw.log.LogInstant; 58 59 import org.apache.derby.iapi.store.raw.xact.TransactionFactory; 60 import org.apache.derby.iapi.store.raw.xact.RawTransaction; 61 import org.apache.derby.iapi.store.raw.xact.TransactionId; 62 63 import org.apache.derby.iapi.error.StandardException; 64 65 import org.apache.derby.impl.store.raw.xact.XactXAResourceManager; 66 67 import java.util.Enumeration ; 68 import java.util.Properties ; 69 import java.util.Hashtable ; 70 71 public class XactFactory implements TransactionFactory, ModuleControl, ModuleSupportable 72 { 73 protected static final String USER_CONTEXT_ID = "UserTransaction"; 74 protected static final String NESTED_READONLY_USER_CONTEXT_ID = 75 "NestedRawReadOnlyUserTransaction"; 76 protected static final String NESTED_UPDATE_USER_CONTEXT_ID = 77 "NestedRawUpdateUserTransaction"; 78 protected static final String INTERNAL_CONTEXT_ID = "InternalTransaction"; 79 protected static final String NTT_CONTEXT_ID = "NestedTransaction"; 80 81 84 85 protected DaemonService rawStoreDaemon; 86 87 private UUIDFactory uuidFactory; 88 protected ContextService contextFactory; 89 protected LockFactory lockFactory; 90 protected LogFactory logFactory; 91 protected DataFactory dataFactory; 92 protected RawStoreFactory rawStoreFactory; 93 94 public TransactionTable ttab; 95 private long tranId; 96 private LockingPolicy[][] lockingPolicies = new LockingPolicy[3][6]; 97 98 private boolean inCreateNoLog = false; 100 private XAResourceManager xa_resource; 101 102 private Object backupSemaphore = new Object (); 103 private long backupBlockingOperations = 0; 104 private boolean inBackup = false; 105 106 109 110 public XactFactory() { 111 super(); 112 } 113 114 117 public boolean canSupport(Properties startParams) { 118 return true; 119 } 120 121 public void boot(boolean create, Properties properties) 122 throws StandardException 123 { 124 125 uuidFactory = Monitor.getMonitor().getUUIDFactory(); 126 127 contextFactory = ContextService.getFactory(); 128 129 lockFactory = 130 (LockFactory) Monitor.bootServiceModule(false, this, 131 org.apache.derby.iapi.reference.Module.LockFactory, properties); 132 133 134 lockingPolicies[LockingPolicy.MODE_NONE] 137 [TransactionController.ISOLATION_NOLOCK] = 138 new NoLocking(); 139 140 lockingPolicies[LockingPolicy.MODE_RECORD] 141 [TransactionController.ISOLATION_NOLOCK] = 142 new NoLocking(); 143 lockingPolicies[LockingPolicy.MODE_RECORD] 144 [TransactionController.ISOLATION_READ_UNCOMMITTED] = 145 new RowLocking1(lockFactory); 146 lockingPolicies[LockingPolicy.MODE_RECORD] 147 [TransactionController.ISOLATION_READ_COMMITTED] = 148 new RowLocking2(lockFactory); 149 lockingPolicies[LockingPolicy.MODE_RECORD] 150 [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] = 151 new RowLocking2nohold(lockFactory); 152 lockingPolicies[LockingPolicy.MODE_RECORD] 153 [TransactionController.ISOLATION_REPEATABLE_READ] = 154 new RowLockingRR(lockFactory); 155 lockingPolicies[LockingPolicy.MODE_RECORD] 156 [TransactionController.ISOLATION_SERIALIZABLE] = 157 new RowLocking3(lockFactory); 158 159 lockingPolicies[LockingPolicy.MODE_CONTAINER] 160 [TransactionController.ISOLATION_NOLOCK] = 161 new NoLocking(); 162 163 lockingPolicies[LockingPolicy.MODE_CONTAINER] 171 [TransactionController.ISOLATION_READ_UNCOMMITTED] = 172 new ContainerLocking2(lockFactory); 173 lockingPolicies[LockingPolicy.MODE_CONTAINER] 174 [TransactionController.ISOLATION_READ_COMMITTED] = 175 new ContainerLocking2(lockFactory); 176 lockingPolicies[LockingPolicy.MODE_CONTAINER] 177 [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] = 178 new ContainerLocking2(lockFactory); 179 lockingPolicies[LockingPolicy.MODE_CONTAINER] 180 [TransactionController.ISOLATION_REPEATABLE_READ] = 181 new ContainerLocking3(lockFactory); 182 lockingPolicies[LockingPolicy.MODE_CONTAINER] 183 [TransactionController.ISOLATION_SERIALIZABLE] = 184 new ContainerLocking3(lockFactory); 185 186 187 if (create) 188 { 189 ttab = new TransactionTable(); 190 191 String noLog = 192 properties.getProperty(Property.CREATE_WITH_NO_LOG); 193 194 inCreateNoLog = (noLog != null && Boolean.valueOf(noLog).booleanValue()); 195 196 } 197 } 198 199 public void stop() { 200 201 if (rawStoreDaemon != null) 202 rawStoreDaemon.stop(); 203 204 } 205 206 209 210 213 public LockFactory getLockFactory() { 214 return lockFactory; 215 } 216 217 218 222 public void createFinished() throws StandardException 223 { 224 if (!inCreateNoLog) 225 { 226 throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG); 227 } 228 229 if (ttab.hasActiveUpdateTransaction()) 231 { 232 throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG); 233 } 234 235 inCreateNoLog = false; 236 } 237 238 249 private RawTransaction startCommonTransaction( 250 RawStoreFactory rsf, 251 ContextManager cm, 252 boolean readOnly, 253 Object compatibilitySpace, 254 String xact_context_id, 255 String transName, 256 boolean excludeMe) 257 throws StandardException 258 { 259 260 if (SanityManager.DEBUG) 261 { 262 if (rawStoreFactory != null) 263 SanityManager.ASSERT( 264 rawStoreFactory == rsf, "raw store factory different"); 265 266 SanityManager.ASSERT( 267 cm == contextFactory.getCurrentContextManager()); 268 } 269 270 Xact xact = 271 new Xact(this, logFactory, dataFactory, readOnly, compatibilitySpace); 272 273 xact.setTransName(transName); 274 pushTransactionContext(cm, xact_context_id, xact, 275 false , 276 rsf, 277 excludeMe ); 278 return xact; 279 } 280 281 public RawTransaction startTransaction( 282 RawStoreFactory rsf, 283 ContextManager cm, 284 String transName) 285 throws StandardException 286 { 287 return(startCommonTransaction( 288 rsf, cm, false, null, USER_CONTEXT_ID, transName, true)); 289 } 290 291 public RawTransaction startNestedReadOnlyUserTransaction( 292 RawStoreFactory rsf, 293 Object compatibilitySpace, 294 ContextManager cm, 295 String transName) 296 throws StandardException 297 { 298 return(startCommonTransaction( 299 rsf, cm, true, compatibilitySpace, 300 NESTED_READONLY_USER_CONTEXT_ID, transName, false)); 301 } 302 303 public RawTransaction startNestedUpdateUserTransaction( 304 RawStoreFactory rsf, 305 ContextManager cm, 306 String transName) 307 throws StandardException 308 { 309 return(startCommonTransaction( 310 rsf, cm, false, null, 311 NESTED_UPDATE_USER_CONTEXT_ID, transName, true)); 312 } 313 314 public RawTransaction startGlobalTransaction( 315 RawStoreFactory rsf, 316 ContextManager cm, 317 int format_id, 318 byte[] global_id, 319 byte[] branch_id) 320 throws StandardException 321 { 322 GlobalXactId gid = new GlobalXactId(format_id, global_id, branch_id); 323 324 if (ttab.findTransactionContextByGlobalId(gid) != null) 325 { 326 throw StandardException.newException(SQLState.STORE_XA_XAER_DUPID); 327 } 328 329 RawTransaction xact = 330 startCommonTransaction( 331 rsf, cm, false, null, 332 USER_CONTEXT_ID, AccessFactoryGlobals.USER_TRANS_NAME, true); 333 334 xact.setTransactionId(gid, xact.getId()); 335 336 return(xact); 337 } 338 339 340 341 public RawTransaction findUserTransaction( 342 RawStoreFactory rsf, 343 ContextManager contextMgr, 344 String transName) 345 throws StandardException 346 { 347 if (SanityManager.DEBUG) 348 { 349 SanityManager.ASSERT( 350 contextMgr == contextFactory.getCurrentContextManager(), 351 "passed in context mgr not the same as current context mgr"); 352 353 if (rawStoreFactory != null) 354 SanityManager.ASSERT( 355 rawStoreFactory == rsf, "raw store factory different"); 356 } 357 358 XactContext xc = (XactContext)contextMgr.getContext(USER_CONTEXT_ID); 359 if (xc == null) 360 return startTransaction(rsf, contextMgr, transName); 361 else 362 return xc.getTransaction(); 363 } 364 365 366 public RawTransaction startNestedTopTransaction(RawStoreFactory rsf, ContextManager cm) 367 throws StandardException 368 { 369 370 if (SanityManager.DEBUG) 371 { 372 if (rawStoreFactory != null) 373 SanityManager.ASSERT( 374 rawStoreFactory == rsf, "raw store factory different"); 375 } 376 377 Xact xact = 378 new Xact(this, logFactory, dataFactory, false, null); 379 380 xact.setPostComplete(); 382 pushTransactionContext(cm, NTT_CONTEXT_ID, xact, 383 true , 384 rsf, 385 true ); 386 return xact; 387 } 388 389 public RawTransaction startInternalTransaction(RawStoreFactory rsf, ContextManager cm) 390 throws StandardException 391 { 392 if (SanityManager.DEBUG) 393 { 394 if (rawStoreFactory != null) 395 SanityManager.ASSERT( 396 rawStoreFactory == rsf, "raw store factory different"); 397 } 398 399 400 Xact xact = new InternalXact(this, logFactory, dataFactory); 401 pushTransactionContext(cm, INTERNAL_CONTEXT_ID, xact, 402 true , 403 rsf, 404 true ); 405 return xact; 406 } 407 408 412 413 419 public boolean findTransaction(TransactionId id, RawTransaction tran) 420 { 421 return ttab.findAndAssumeTransaction(id, tran); 422 } 423 424 425 442 public void rollbackAllTransactions( 443 RawTransaction recoveryTransaction, 444 RawStoreFactory rsf) 445 throws StandardException 446 { 447 if (SanityManager.DEBUG) 448 { 449 if (rawStoreFactory != null) 450 SanityManager.ASSERT( 451 rawStoreFactory == rsf, "raw store factory different"); 452 453 SanityManager.ASSERT( 454 recoveryTransaction != null, "recovery transaction null"); 455 } 456 457 int irbcount = 0; 458 459 if (ttab.hasRollbackFirstTransaction()) 461 { 462 RawTransaction internalTransaction = startInternalTransaction(rsf, 463 recoveryTransaction.getContextManager()); 464 465 internalTransaction.recoveryTransaction(); 467 468 if (SanityManager.DEBUG) 469 SanityManager.ASSERT( 470 internalTransaction.handlesPostTerminationWork() == false, 471 "internal recovery xact handles post termination work"); 472 473 while(ttab.getMostRecentRollbackFirstTransaction( 474 internalTransaction)) 475 { 476 irbcount++; 477 internalTransaction.abort(); 478 } 479 480 internalTransaction.close(); 481 } 482 483 if (SanityManager.DEBUG) 484 { 485 SanityManager.ASSERT( 486 ttab.hasRollbackFirstTransaction() == false, 487 "cant rollback user xacts with existing active internal xacts"); 488 } 489 490 int rbcount = 0; 491 492 while(ttab.getMostRecentTransactionForRollback(recoveryTransaction)) 494 { 495 if (SanityManager.DEBUG) 496 { 497 SanityManager.ASSERT( 498 recoveryTransaction.handlesPostTerminationWork() == false, 499 "recovery transaction handles post termination work"); 500 } 501 502 rbcount++; 503 recoveryTransaction.abort(); 504 } 505 506 if (SanityManager.DEBUG) 507 { 508 if (rbcount > 0 || irbcount > 0) 509 { 510 } 516 } 517 518 } 519 520 521 536 public void handlePreparedXacts( 537 RawStoreFactory rsf) 538 throws StandardException 539 { 540 if (SanityManager.DEBUG) 541 { 542 543 if (rawStoreFactory != null) 544 SanityManager.ASSERT( 545 rawStoreFactory == rsf, "raw store factory different"); 546 } 547 548 int prepared_count = 0; 549 550 if (ttab.hasPreparedRecoveredXact()) 551 { 552 554 559 564 while (true) 565 { 566 ContextManager cm = contextFactory.newContextManager(); 568 contextFactory.setCurrentContextManager(cm); 569 570 try { 571 RawTransaction rawtran = 572 startTransaction( 573 rawStoreFactory, cm, 574 AccessFactoryGlobals.USER_TRANS_NAME); 575 576 if (ttab.getMostRecentPreparedRecoveredXact(rawtran)) 577 { 578 rawtran.reprepare(); 582 583 if (SanityManager.DEBUG) 584 prepared_count++; 585 } 586 else 587 { 588 rawtran.destroy(); 590 break; 591 } 592 } 593 finally 594 { 595 contextFactory.resetCurrentContextManager(cm); 596 } 597 } 598 599 } 600 601 if (SanityManager.DEBUG) 602 { 603 } 607 } 608 609 610 618 619 public LogInstant firstUpdateInstant() 620 { 621 return ttab.getFirstLogInstant(); 622 } 623 624 627 628 632 public StandardException markCorrupt(StandardException originalError) { 633 logFactory.markCorrupt(originalError); 634 return originalError; 635 } 636 637 640 641 public void setNewTransactionId(TransactionId oldxid, Xact t) 642 { 643 XactId xid; 644 boolean excludeMe = true; 646 if (oldxid != null) 647 excludeMe = remove(oldxid); 648 649 synchronized(this) 650 { 651 xid = new XactId(tranId++); 652 } 653 654 t.setTransactionId(t.getGlobalId(), xid); 655 656 658 if (oldxid != null) 667 add(t, excludeMe); 668 } 669 670 673 public void resetTranId() 674 { 675 XactId xid = (XactId)ttab.largestUpdateXactId(); 676 if (xid != null) 677 tranId = xid.getId() + 1; 678 else 679 tranId = 1; 680 } 681 682 683 701 protected void pushTransactionContext(ContextManager cm, String contextName, 702 Xact xact, 703 boolean abortAll, 704 RawStoreFactory rsf, 705 boolean excludeMe) 706 throws StandardException 707 { 708 if (cm.getContext(contextName) != null) 709 { 710 throw StandardException.newException( 711 SQLState.XACT_TRANSACTION_ACTIVE); 712 } 713 714 XactContext xc = new XactContext(cm, contextName, xact, abortAll, rsf); 715 716 731 add(xact, excludeMe); 732 733 } 734 735 744 protected void addUpdateTransaction( 745 TransactionId id, 746 RawTransaction t, 747 int transactionStatus) 748 { 749 if (SanityManager.DEBUG) 750 SanityManager.ASSERT( 751 id != null, "addding update transaction with null id"); 752 753 ttab.addUpdateTransaction(id, t, transactionStatus); 754 } 755 756 760 protected void removeUpdateTransaction(TransactionId id) 761 { 762 if (SanityManager.DEBUG) 763 SanityManager.ASSERT( 764 id != null, "remove update transaction with null id"); 765 766 ttab.removeUpdateTransaction(id); 767 } 768 769 773 protected void prepareTransaction(TransactionId id) 774 { 775 if (SanityManager.DEBUG) 776 SanityManager.ASSERT( 777 id != null, "prepare transaction with null id"); 778 779 ttab.prepareTransaction(id); 780 } 781 782 785 public boolean submitPostCommitWork(Serviceable work) 786 { 787 if (rawStoreDaemon != null) 788 return rawStoreDaemon.enqueue(work, work.serviceASAP()); 789 return false; 790 } 791 792 public void setRawStoreFactory(RawStoreFactory rsf) throws StandardException 793 { 794 if (SanityManager.DEBUG) 795 { 796 SanityManager.ASSERT(rsf != null, "rawStoreFactory == null"); 797 } 798 799 rawStoreFactory = rsf; 800 801 rawStoreDaemon = rsf.getDaemon(); 804 805 logFactory = (LogFactory) Monitor.findServiceModule(this, rsf.getLogFactoryModule()); 808 809 dataFactory = (DataFactory) Monitor.findServiceModule(this, rsf.getDataFactoryModule()); 811 } 812 813 821 public boolean noActiveUpdateTransaction() 822 { 823 return (ttab.hasActiveUpdateTransaction() == false); 824 } 825 826 827 839 public boolean hasPreparedXact() 840 { 841 return (ttab.hasPreparedXact()); 842 } 843 844 845 846 850 protected boolean remove(TransactionId xactId) 851 { 852 return ttab.remove(xactId); 853 } 854 855 protected void add(Xact xact, boolean excludeMe) 856 { 857 ttab.add(xact, excludeMe); 858 } 859 860 861 864 public UUID makeNewUUID() 865 { 866 return uuidFactory.createUUID(); 867 } 868 869 873 public boolean flushLogOnCommit(String contextName) 874 { 875 return (contextName == USER_CONTEXT_ID || 881 contextName.equals(USER_CONTEXT_ID)); 882 } 883 884 885 888 final LockingPolicy getLockingPolicy( 889 int mode, 890 int isolation, 891 boolean stricterOk) 892 { 893 894 if (mode == LockingPolicy.MODE_NONE) 895 isolation = TransactionController.ISOLATION_NOLOCK; 896 897 LockingPolicy policy = lockingPolicies[mode][isolation]; 898 899 if ((policy != null) || (!stricterOk)) 900 return policy; 901 902 for (mode++; mode <= LockingPolicy.MODE_CONTAINER; mode++) 903 { 904 for (int i = isolation; 905 i <= TransactionController.ISOLATION_SERIALIZABLE; 906 i++) 907 { 908 policy = lockingPolicies[mode][i]; 909 if (policy != null) 910 return policy; 911 } 912 } 913 914 return null; 915 } 916 917 920 public Formatable getTransactionTable() 921 { 922 return ttab; 923 } 924 925 929 public void useTransactionTable(Formatable transactionTable) 930 throws StandardException 931 { 932 if (ttab != null && transactionTable != null) 933 { 934 throw StandardException.newException( 935 SQLState.XACT_TRANSACTION_TABLE_IN_USE); 936 } 937 938 if (ttab == null) 939 { 940 if (transactionTable == null) 941 ttab = new TransactionTable(); 942 else 943 { 944 if (SanityManager.DEBUG) 945 { 946 if ((transactionTable instanceof TransactionTable) == 947 false) 948 { 949 SanityManager.THROWASSERT( 950 "using transaction table which is of class " + 951 transactionTable.getClass().getName()); 952 } 953 } 954 ttab = (TransactionTable)transactionTable; 955 } 956 } 957 } 960 961 public TransactionInfo[] getTransactionInfo() 962 { 963 if (SanityManager.DEBUG) 964 SanityManager.ASSERT(ttab != null, "transaction table is null"); 965 return ttab.getTransactionInfo(); 966 } 967 968 969 public boolean inDatabaseCreation() 971 { 972 return inCreateNoLog; 973 } 974 975 981 public Object getXAResourceManager() 982 throws StandardException 983 { 984 if (xa_resource == null) 985 xa_resource = new XactXAResourceManager(rawStoreFactory, ttab); 986 987 return(xa_resource); 988 } 989 990 991 1003 protected boolean blockBackup(boolean wait) 1004 throws StandardException 1005 { 1006 synchronized(backupSemaphore) { 1007 if (inBackup) 1010 { 1011 if(wait) { 1012 while(inBackup) { 1013 try { 1014 backupSemaphore.wait(); 1015 } catch (InterruptedException ie) { 1016 throw StandardException.interrupt(ie); 1017 } 1018 } 1019 }else { 1020 return false; 1021 } 1022 } 1023 1024 backupBlockingOperations++; 1026 return true; 1027 } 1028 } 1029 1030 1031 1034 protected void unblockBackup() 1035 { 1036 synchronized(backupSemaphore) { 1037 if (SanityManager.DEBUG) 1038 SanityManager.ASSERT(backupBlockingOperations > 0, 1039 "no backup blocking opeations in progress"); 1040 1041 backupBlockingOperations--; 1042 1043 if (inBackup) { 1044 backupSemaphore.notifyAll(); 1046 } 1047 } 1048 } 1049 1050 1067 public boolean blockBackupBlockingOperations(boolean wait) 1068 throws StandardException 1069 { 1070 synchronized(backupSemaphore) { 1071 if (wait) { 1072 inBackup= true; 1075 try { 1076 while(backupBlockingOperations > 0) 1078 { 1079 try { 1080 backupSemaphore.wait(); 1081 } 1082 catch (InterruptedException ie) { 1083 1088 inBackup = false; 1089 backupSemaphore.notifyAll(); 1090 throw StandardException.interrupt(ie); 1091 } 1092 } 1093 } 1094 catch (RuntimeException rte) { 1095 inBackup= false; 1099 backupSemaphore.notifyAll(); 1100 throw rte; } 1102 } else { 1103 if (backupBlockingOperations == 0) 1105 inBackup = true; 1106 } 1107 1108 } 1109 1110 if (SanityManager.DEBUG) { 1111 if (inBackup) { 1112 SanityManager.ASSERT(backupBlockingOperations == 0 , 1113 "store is not in correct state for backup"); 1114 } 1115 } 1116 1117 return inBackup; 1118 } 1119 1120 1121 1124 public void unblockBackupBlockingOperations() 1125 { 1126 synchronized(backupSemaphore) { 1127 inBackup = false; 1128 backupSemaphore.notifyAll(); 1129 } 1130 } 1131 1132} 1133 | Popular Tags |