1 /* Copyright (c) 2001-2016, The HSQL Development Group 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of the HSQL Development Group nor the names of its 15 * contributors may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, 22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 package org.hsqldb; 33 34 import java.util.concurrent.atomic.AtomicLong; 35 import java.util.concurrent.locks.ReentrantReadWriteLock; 36 37 import org.hsqldb.HsqlNameManager.HsqlName; 38 import org.hsqldb.error.Error; 39 import org.hsqldb.error.ErrorCode; 40 import org.hsqldb.lib.ArrayUtil; 41 import org.hsqldb.lib.HashMap; 42 import org.hsqldb.lib.HsqlArrayList; 43 import org.hsqldb.lib.Iterator; 44 import org.hsqldb.lib.LongDeque; 45 import org.hsqldb.lib.LongKeyHashMap; 46 import org.hsqldb.lib.MultiValueHashMap; 47 import org.hsqldb.lib.OrderedHashSet; 48 49 /** 50 * Shared code for TransactionManager classes 51 * 52 * @author Fred Toussi (fredt@users dot sourceforge.net) 53 * @version 2.3.4 54 * @since 2.0.0 55 */ 56 class TransactionManagerCommon { 57 58 Database database; 59 Session lobSession; 60 int txModel; 61 HsqlName[] catalogNameList; 62 63 // 64 ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 65 ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); 66 67 // functional unit - sessions involved in live transactions 68 69 /** live transactions keeping committed transactions from being merged */ 70 LongDeque liveTransactionTimestamps = new LongDeque(); 71 72 /** global timestamp for database */ 73 AtomicLong globalChangeTimestamp = new AtomicLong(1); 74 75 // 76 int transactionCount = 0; 77 78 // 79 HashMap tableWriteLocks = new HashMap(); 80 MultiValueHashMap tableReadLocks = new MultiValueHashMap(); 81 82 // functional unit - cached table transactions 83 84 /** Map : rowID -> RowAction */ 85 public LongKeyHashMap rowActionMap; 86 setTransactionControl(Session session, int mode)87 void setTransactionControl(Session session, int mode) { 88 89 TransactionManagerCommon manager = null; 90 91 if (mode == txModel) { 92 return; 93 } 94 95 // statement runs as transaction 96 writeLock.lock(); 97 98 try { 99 switch (txModel) { 100 101 case TransactionManager.MVCC : 102 case TransactionManager.MVLOCKS : 103 if (liveTransactionTimestamps.size() != 1) { 104 throw Error.error(ErrorCode.X_25001); 105 } 106 } 107 108 switch (mode) { 109 110 case TransactionManager.MVCC : { 111 manager = new TransactionManagerMVCC(database); 112 113 manager.liveTransactionTimestamps.addLast( 114 session.transactionTimestamp); 115 116 break; 117 } 118 case TransactionManager.MVLOCKS : { 119 manager = new TransactionManagerMV2PL(database); 120 121 manager.liveTransactionTimestamps.addLast( 122 session.transactionTimestamp); 123 124 break; 125 } 126 case TransactionManager.LOCKS : { 127 manager = new TransactionManager2PL(database); 128 129 break; 130 } 131 default : 132 throw Error.runtimeError(ErrorCode.U_S0500, 133 "TransactionManagerCommon"); 134 } 135 136 manager.globalChangeTimestamp.set(globalChangeTimestamp.get()); 137 138 manager.transactionCount = transactionCount; 139 database.txManager = (TransactionManager) manager; 140 } finally { 141 writeLock.unlock(); 142 } 143 } 144 adjustLobUsage(Session session)145 void adjustLobUsage(Session session) { 146 147 int limit = session.rowActionList.size(); 148 long lastActionTimestamp = session.actionTimestamp; 149 150 for (int i = 0; i < limit; i++) { 151 RowAction action = (RowAction) session.rowActionList.get(i); 152 153 if (action.type == RowActionBase.ACTION_NONE) { 154 continue; 155 } 156 157 if (action.table.hasLobColumn) { 158 int type = action.getCommitTypeOn(lastActionTimestamp); 159 Row row = action.memoryRow; 160 161 if (row == null) { 162 row = (Row) action.store.get(action.getPos(), false); 163 } 164 165 switch (type) { 166 167 case RowActionBase.ACTION_INSERT : 168 session.sessionData.adjustLobUsageCount(action.table, 169 row.getData(), 1); 170 break; 171 172 case RowActionBase.ACTION_DELETE : 173 session.sessionData.adjustLobUsageCount(action.table, 174 row.getData(), -1); 175 break; 176 177 case RowActionBase.ACTION_INSERT_DELETE : 178 default : 179 } 180 } 181 } 182 183 int newLimit = session.rowActionList.size(); 184 185 if (newLimit > limit) { 186 for (int i = limit; i < newLimit; i++) { 187 RowAction lobAction = (RowAction) session.rowActionList.get(i); 188 189 lobAction.commit(session); 190 } 191 } 192 } 193 persistCommit(Session session)194 void persistCommit(Session session) { 195 196 int limit = session.rowActionList.size(); 197 boolean writeCommit = false; 198 199 for (int i = 0; i < limit; i++) { 200 RowAction action = (RowAction) session.rowActionList.get(i); 201 202 if (action.type == RowActionBase.ACTION_NONE) { 203 continue; 204 } 205 206 int type = action.getCommitTypeOn(session.actionTimestamp); 207 Row row = action.memoryRow; 208 209 if (row == null) { 210 row = (Row) action.store.get(action.getPos(), false); 211 } 212 213 if (action.table.tableType != TableBase.TEMP_TABLE) { 214 writeCommit = true; 215 } 216 217 try { 218 action.store.commitRow(session, row, type, txModel); 219 220 if (txModel == TransactionManager.LOCKS 221 || action.table.tableType == TableBase.TEMP_TABLE) { 222 action.setAsNoOp(); 223 224 row.rowAction = null; 225 } 226 } catch (HsqlException e) { 227 database.logger.logWarningEvent("data commit failed", e); 228 } 229 } 230 231 try { 232 session.logSequences(); 233 234 if (limit > 0 && writeCommit) { 235 database.logger.writeCommitStatement(session); 236 } 237 } catch (HsqlException e) { 238 database.logger.logWarningEvent("data commit logging failed", e); 239 } 240 } 241 finaliseRows(Session session, Object[] list, int start, int limit)242 void finaliseRows(Session session, Object[] list, int start, int limit) { 243 244 for (int i = start; i < limit; i++) { 245 RowAction action = (RowAction) list[i]; 246 247 action.store.postCommitAction(session, action); 248 } 249 } 250 251 /** 252 * merge a transaction committed at a given timestamp. 253 */ mergeTransaction(Object[] list, int start, int limit, long timestamp)254 void mergeTransaction(Object[] list, int start, int limit, 255 long timestamp) { 256 257 for (int i = start; i < limit; i++) { 258 RowAction rowact = (RowAction) list[i]; 259 260 rowact.mergeToTimestamp(timestamp); 261 } 262 } 263 264 /** 265 * gets the next timestamp for an action 266 */ getNextGlobalChangeTimestamp()267 public long getNextGlobalChangeTimestamp() { 268 return globalChangeTimestamp.incrementAndGet(); 269 } 270 checkDeadlock(Session session, OrderedHashSet newWaits)271 boolean checkDeadlock(Session session, OrderedHashSet newWaits) { 272 273 int size = session.waitingSessions.size(); 274 275 for (int i = 0; i < size; i++) { 276 Session current = (Session) session.waitingSessions.get(i); 277 278 if (newWaits.contains(current)) { 279 return false; 280 } 281 282 if (!checkDeadlock(current, newWaits)) { 283 return false; 284 } 285 } 286 287 return true; 288 } 289 checkDeadlock(Session session, Session other)290 boolean checkDeadlock(Session session, Session other) { 291 292 int size = session.waitingSessions.size(); 293 294 for (int i = 0; i < size; i++) { 295 Session current = (Session) session.waitingSessions.get(i); 296 297 if (current == other) { 298 return false; 299 } 300 301 if (!checkDeadlock(current, other)) { 302 return false; 303 } 304 } 305 306 return true; 307 } 308 getTransactionSessions(Session session)309 void getTransactionSessions(Session session) { 310 311 OrderedHashSet set = session.tempSet; 312 Session[] sessions = database.sessionManager.getAllSessions(); 313 314 for (int i = 0; i < sessions.length; i++) { 315 long timestamp = sessions[i].transactionTimestamp; 316 317 if (session != sessions[i] && sessions[i].isTransaction) { 318 set.add(sessions[i]); 319 } 320 } 321 } 322 getTransactionAndPreSessions(Session session)323 void getTransactionAndPreSessions(Session session) { 324 325 OrderedHashSet set = session.tempSet; 326 Session[] sessions = database.sessionManager.getAllSessions(); 327 328 for (int i = 0; i < sessions.length; i++) { 329 long timestamp = sessions[i].transactionTimestamp; 330 331 if (session == sessions[i]) { 332 continue; 333 } 334 335 if (sessions[i].isPreTransaction) { 336 set.add(sessions[i]); 337 } else if (sessions[i].isTransaction) { 338 set.add(sessions[i]); 339 } 340 } 341 } 342 endActionTPL(Session session)343 void endActionTPL(Session session) { 344 345 if (session.isolationLevel == SessionInterface.TX_REPEATABLE_READ 346 || session.isolationLevel 347 == SessionInterface.TX_SERIALIZABLE) { 348 return; 349 } 350 351 if (session.sessionContext.currentStatement == null) { 352 353 // after java function / proc with db access 354 return; 355 } 356 357 if (session.sessionContext.depth > 0) { 358 359 // routine or trigger 360 return; 361 } 362 363 HsqlName[] readLocks = 364 session.sessionContext.currentStatement.getTableNamesForRead(); 365 366 if (readLocks.length == 0) { 367 return; 368 } 369 370 writeLock.lock(); 371 372 try { 373 unlockReadTablesTPL(session, readLocks); 374 375 final int waitingCount = session.waitingSessions.size(); 376 377 if (waitingCount == 0) { 378 return; 379 } 380 381 boolean canUnlock = false; 382 383 // if write lock was used for read lock 384 for (int i = 0; i < readLocks.length; i++) { 385 if (tableWriteLocks.get(readLocks[i]) != session) { 386 canUnlock = true; 387 388 break; 389 } 390 } 391 392 if (!canUnlock) { 393 return; 394 } 395 396 canUnlock = false; 397 398 for (int i = 0; i < waitingCount; i++) { 399 Session current = (Session) session.waitingSessions.get(i); 400 401 if (current.abortTransaction) { 402 canUnlock = true; 403 404 break; 405 } 406 407 Statement currentStatement = 408 current.sessionContext.currentStatement; 409 410 if (currentStatement == null) { 411 canUnlock = true; 412 413 break; 414 } 415 416 if (ArrayUtil.containsAny( 417 readLocks, currentStatement.getTableNamesForWrite())) { 418 canUnlock = true; 419 420 break; 421 } 422 } 423 424 if (!canUnlock) { 425 return; 426 } 427 428 resetLocks(session); 429 resetLatchesMidTransaction(session); 430 } finally { 431 writeLock.unlock(); 432 } 433 } 434 endTransactionTPL(Session session)435 void endTransactionTPL(Session session) { 436 437 unlockTablesTPL(session); 438 439 final int waitingCount = session.waitingSessions.size(); 440 441 if (waitingCount == 0) { 442 return; 443 } 444 445 resetLocks(session); 446 resetLatches(session); 447 } 448 resetLocks(Session session)449 void resetLocks(Session session) { 450 451 final int waitingCount = session.waitingSessions.size(); 452 453 for (int i = 0; i < waitingCount; i++) { 454 Session current = (Session) session.waitingSessions.get(i); 455 456 current.tempUnlocked = false; 457 458 long count = current.latch.getCount(); 459 460 if (count == 1) { 461 boolean canProceed = setWaitedSessionsTPL(current, 462 current.sessionContext.currentStatement); 463 464 if (canProceed) { 465 if (current.tempSet.isEmpty()) { 466 lockTablesTPL(current, 467 current.sessionContext.currentStatement); 468 469 current.tempUnlocked = true; 470 } 471 } 472 } 473 } 474 475 for (int i = 0; i < waitingCount; i++) { 476 Session current = (Session) session.waitingSessions.get(i); 477 478 if (current.tempUnlocked) { 479 480 // 481 } else if (current.abortTransaction) { 482 483 // 484 } else { 485 486 // this can introduce additional waits for the sessions 487 setWaitedSessionsTPL(current, 488 current.sessionContext.currentStatement); 489 } 490 } 491 } 492 resetLatches(Session session)493 void resetLatches(Session session) { 494 495 final int waitingCount = session.waitingSessions.size(); 496 497 for (int i = 0; i < waitingCount; i++) { 498 Session current = (Session) session.waitingSessions.get(i); 499 500 /* 501 if (!current.abortTransaction && current.tempSet.isEmpty()) { 502 503 504 // test code valid only for top level statements 505 boolean hasLocks = hasLocks(current, current.sessionContext.currentStatement); 506 if (!hasLocks) { 507 System.out.println("trouble"); 508 } 509 510 } 511 */ 512 setWaitingSessionTPL(current); 513 } 514 515 session.waitingSessions.clear(); 516 session.latch.setCount(0); 517 } 518 resetLatchesMidTransaction(Session session)519 void resetLatchesMidTransaction(Session session) { 520 521 session.tempSet.clear(); 522 session.tempSet.addAll(session.waitingSessions); 523 session.waitingSessions.clear(); 524 525 final int waitingCount = session.tempSet.size(); 526 527 for (int i = 0; i < waitingCount; i++) { 528 Session current = (Session) session.tempSet.get(i); 529 530 if (!current.abortTransaction && current.tempSet.isEmpty()) { 531 532 // valid for top level statements 533 // boolean hasLocks = hasLocks(current, current.sessionContext.currentStatement); 534 // if (!hasLocks) { 535 // System.out.println("trouble"); 536 // hasLocks(current, current.sessionContext.currentStatement); 537 // } 538 } 539 540 setWaitingSessionTPL(current); 541 } 542 543 session.tempSet.clear(); 544 } 545 setWaitedSessionsTPL(Session session, Statement cs)546 boolean setWaitedSessionsTPL(Session session, Statement cs) { 547 548 session.tempSet.clear(); 549 550 if (cs == null) { 551 return true; 552 } 553 554 if (session.abortTransaction) { 555 return false; 556 } 557 558 if (cs.isCatalogLock()) { 559 getTransactionSessions(session); 560 } 561 562 HsqlName[] nameList = cs.getTableNamesForWrite(); 563 564 for (int i = 0; i < nameList.length; i++) { 565 HsqlName name = nameList[i]; 566 567 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 568 continue; 569 } 570 571 Session holder = (Session) tableWriteLocks.get(name); 572 573 if (holder != null && holder != session) { 574 session.tempSet.add(holder); 575 } 576 577 Iterator it = tableReadLocks.get(name); 578 579 while (it.hasNext()) { 580 holder = (Session) it.next(); 581 582 if (holder != session) { 583 session.tempSet.add(holder); 584 } 585 } 586 } 587 588 nameList = cs.getTableNamesForRead(); 589 590 if (txModel == TransactionManager.MVLOCKS && session.isReadOnly()) { 591 if (nameList.length > 0) { 592 nameList = catalogNameList; 593 } 594 } 595 596 for (int i = 0; i < nameList.length; i++) { 597 HsqlName name = nameList[i]; 598 599 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 600 continue; 601 } 602 603 Session holder = (Session) tableWriteLocks.get(name); 604 605 if (holder != null && holder != session) { 606 session.tempSet.add(holder); 607 } 608 } 609 610 if (session.tempSet.isEmpty()) { 611 return true; 612 } 613 614 if (checkDeadlock(session, session.tempSet)) { 615 return true; 616 } 617 618 session.tempSet.clear(); 619 620 session.abortTransaction = true; 621 622 return false; 623 } 624 setWaitingSessionTPL(Session session)625 void setWaitingSessionTPL(Session session) { 626 627 int count = session.tempSet.size(); 628 629 assert session.latch.getCount() <= count + 1; 630 631 for (int i = 0; i < count; i++) { 632 Session current = (Session) session.tempSet.get(i); 633 634 current.waitingSessions.add(session); 635 } 636 637 session.tempSet.clear(); 638 session.latch.setCount(count); 639 } 640 lockTablesTPL(Session session, Statement cs)641 void lockTablesTPL(Session session, Statement cs) { 642 643 if (cs == null || session.abortTransaction) { 644 return; 645 } 646 647 HsqlName[] nameList = cs.getTableNamesForWrite(); 648 649 for (int i = 0; i < nameList.length; i++) { 650 HsqlName name = nameList[i]; 651 652 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 653 continue; 654 } 655 656 tableWriteLocks.put(name, session); 657 } 658 659 nameList = cs.getTableNamesForRead(); 660 661 if (txModel == TransactionManager.MVLOCKS && session.isReadOnly()) { 662 if (nameList.length > 0) { 663 nameList = catalogNameList; 664 } 665 } 666 667 for (int i = 0; i < nameList.length; i++) { 668 HsqlName name = nameList[i]; 669 670 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 671 continue; 672 } 673 674 tableReadLocks.put(name, session); 675 } 676 } 677 unlockTablesTPL(Session session)678 void unlockTablesTPL(Session session) { 679 680 Iterator it = tableWriteLocks.values().iterator(); 681 682 while (it.hasNext()) { 683 Session s = (Session) it.next(); 684 685 if (s == session) { 686 it.remove(); 687 } 688 } 689 690 it = tableReadLocks.values().iterator(); 691 692 while (it.hasNext()) { 693 Session s = (Session) it.next(); 694 695 if (s == session) { 696 it.remove(); 697 } 698 } 699 } 700 unlockReadTablesTPL(Session session, HsqlName[] locks)701 void unlockReadTablesTPL(Session session, HsqlName[] locks) { 702 703 for (int i = 0; i < locks.length; i++) { 704 tableReadLocks.remove(locks[i], session); 705 } 706 } 707 hasLocks(Session session, Statement cs)708 boolean hasLocks(Session session, Statement cs) { 709 710 if (cs == null) { 711 return true; 712 } 713 714 HsqlName[] nameList = cs.getTableNamesForWrite(); 715 716 for (int i = 0; i < nameList.length; i++) { 717 HsqlName name = nameList[i]; 718 719 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 720 continue; 721 } 722 723 Session holder = (Session) tableWriteLocks.get(name); 724 725 if (holder != null && holder != session) { 726 return false; 727 } 728 729 Iterator it = tableReadLocks.get(name); 730 731 while (it.hasNext()) { 732 holder = (Session) it.next(); 733 734 if (holder != session) { 735 return false; 736 } 737 } 738 } 739 740 nameList = cs.getTableNamesForRead(); 741 742 for (int i = 0; i < nameList.length; i++) { 743 HsqlName name = nameList[i]; 744 745 if (name.schema == SqlInvariants.SYSTEM_SCHEMA_HSQLNAME) { 746 continue; 747 } 748 749 Session holder = (Session) tableWriteLocks.get(name); 750 751 if (holder != null && holder != session) { 752 return false; 753 } 754 } 755 756 return true; 757 } 758 getFirstLiveTransactionTimestamp()759 long getFirstLiveTransactionTimestamp() { 760 761 if (liveTransactionTimestamps.isEmpty()) { 762 return Long.MAX_VALUE; 763 } 764 765 return liveTransactionTimestamps.get(0); 766 } 767 768 /** 769 * Return an array of all row actions sorted by System Change No. 770 */ getRowActionList()771 RowAction[] getRowActionList() { 772 773 writeLock.lock(); 774 775 try { 776 Session[] sessions = database.sessionManager.getAllSessions(); 777 int[] tIndex = new int[sessions.length]; 778 RowAction[] rowActions; 779 int rowActionCount = 0; 780 781 { 782 int actioncount = 0; 783 784 for (int i = 0; i < sessions.length; i++) { 785 actioncount += sessions[i].getTransactionSize(); 786 } 787 788 rowActions = new RowAction[actioncount]; 789 } 790 791 while (true) { 792 boolean found = false; 793 long minChangeNo = Long.MAX_VALUE; 794 int sessionIndex = 0; 795 796 // find the lowest available SCN across all sessions 797 for (int i = 0; i < sessions.length; i++) { 798 int tSize = sessions[i].getTransactionSize(); 799 800 if (tIndex[i] < tSize) { 801 RowAction current = 802 (RowAction) sessions[i].rowActionList.get( 803 tIndex[i]); 804 805 if (current.actionTimestamp < minChangeNo) { 806 minChangeNo = current.actionTimestamp; 807 sessionIndex = i; 808 } 809 810 found = true; 811 } 812 } 813 814 if (!found) { 815 break; 816 } 817 818 HsqlArrayList currentList = 819 sessions[sessionIndex].rowActionList; 820 821 for (; tIndex[sessionIndex] < currentList.size(); ) { 822 RowAction current = 823 (RowAction) currentList.get(tIndex[sessionIndex]); 824 825 // if the next change no is in this session, continue adding 826 if (current.actionTimestamp == minChangeNo + 1) { 827 minChangeNo++; 828 } 829 830 if (current.actionTimestamp == minChangeNo) { 831 rowActions[rowActionCount++] = current; 832 833 tIndex[sessionIndex]++; 834 } else { 835 break; 836 } 837 } 838 } 839 840 return rowActions; 841 } finally { 842 writeLock.unlock(); 843 } 844 } 845 resetSession(Session session, Session targetSession, int mode)846 void resetSession(Session session, Session targetSession, int mode) { 847 848 writeLock.lock(); 849 850 try { 851 switch (mode) { 852 853 case TransactionManager.resetSessionResults : 854 if (!targetSession.isInMidTransaction()) { 855 targetSession.sessionData.closeAllNavigators(); 856 } 857 break; 858 859 case TransactionManager.resetSessionTables : 860 if (!targetSession.isInMidTransaction()) { 861 targetSession.sessionData.persistentStoreCollection 862 .clearAllTables(); 863 } 864 break; 865 866 case TransactionManager.resetSessionResetAll : 867 if (!targetSession.isInMidTransaction()) { 868 targetSession.resetSession(); 869 } 870 break; 871 872 case TransactionManager.resetSessionRollback : 873 if (session == targetSession) { 874 return; 875 } 876 877 if (targetSession.isInMidTransaction()) { 878 prepareReset(targetSession); 879 880 if (targetSession.latch.getCount() > 0) { 881 targetSession.abortTransaction = true; 882 883 targetSession.latch.setCount(0); 884 } else { 885 targetSession.abortTransaction = true; 886 } 887 } 888 break; 889 890 case TransactionManager.resetSessionAbort : 891 if (session == targetSession) { 892 return; 893 } 894 895 if (targetSession.isInMidTransaction()) { 896 prepareReset(targetSession); 897 898 if (targetSession.latch.getCount() > 0) { 899 targetSession.abortAction = true; 900 901 targetSession.latch.setCount(0); 902 } else { 903 targetSession.abortAction = true; 904 } 905 } 906 break; 907 908 case TransactionManager.resetSessionClose : 909 if (session == targetSession) { 910 return; 911 } 912 913 if (!targetSession.isInMidTransaction()) { 914 targetSession.rollbackNoCheck(true); 915 targetSession.close(); 916 } 917 break; 918 } 919 } finally { 920 writeLock.unlock(); 921 } 922 } 923 prepareReset(Session session)924 void prepareReset(Session session) { 925 926 OrderedHashSet waitedSessions = session.waitedSessions; 927 928 for (int i = 0; i < waitedSessions.size(); i++) { 929 Session current = (Session) waitedSessions.get(i); 930 931 current.waitingSessions.remove(session); 932 } 933 934 waitedSessions.clear(); 935 } 936 abortAction(Session session)937 public void abortAction(Session session) {} 938 } 939