| 605 | } |
| 606 | |
| 607 | CommitNumber TipCache::setState(TraNumber number, int state) |
| 608 | { |
| 609 | // Can only be called on initialized TipCache |
| 610 | fb_assert(m_tpcHeader); |
| 611 | GlobalTpcHeader* header = m_tpcHeader->getHeader(); |
| 612 | |
| 613 | TpcBlockNumber blockNumber = number / m_transactionsPerBlock; |
| 614 | ULONG offset = number % m_transactionsPerBlock; |
| 615 | |
| 616 | Sync sync(&m_sync_status, FB_FUNCTION); |
| 617 | TransactionStatusBlock* block = getTransactionStatusBlock(header, blockNumber, sync); |
| 618 | |
| 619 | // This should not really happen |
| 620 | if (!block) |
| 621 | ERR_bugcheck_msg("TPC: Attempt to change state of old transaction"); |
| 622 | |
| 623 | std::atomic<CommitNumber>* statePtr = block->data + offset; |
| 624 | CommitNumber oldStateCn = statePtr->load(std::memory_order_relaxed); |
| 625 | switch (state) |
| 626 | { |
| 627 | case tra_committed: |
| 628 | { |
| 629 | if (oldStateCn == CN_DEAD) |
| 630 | ERR_bugcheck_msg("TPC: Attempt to commit dead transaction"); |
| 631 | |
| 632 | // If transaction is already committed - do nothing |
| 633 | if (oldStateCn >= CN_PREHISTORIC && oldStateCn <= CN_MAX_NUMBER) |
| 634 | return oldStateCn; |
| 635 | |
| 636 | // We verified for all other cases, transaction must either be Active or in Limbo |
| 637 | fb_assert(oldStateCn == CN_ACTIVE || oldStateCn == CN_LIMBO); |
| 638 | |
| 639 | // Generate new commit number |
| 640 | CommitNumber newCommitNumber = header->latest_commit_number++ + 1; |
| 641 | |
| 642 | statePtr->store(newCommitNumber, std::memory_order_relaxed); |
| 643 | return newCommitNumber; |
| 644 | } |
| 645 | |
| 646 | case tra_limbo: |
| 647 | if (oldStateCn == CN_LIMBO) |
| 648 | return CN_LIMBO; |
| 649 | |
| 650 | if (oldStateCn != CN_ACTIVE) |
| 651 | ERR_bugcheck_msg("TPC: Attempt to mark inactive transaction to be in limbo"); |
| 652 | |
| 653 | statePtr->store(CN_LIMBO, std::memory_order_relaxed); |
| 654 | |
| 655 | return CN_LIMBO; |
| 656 | |
| 657 | case tra_dead: |
| 658 | if (oldStateCn == CN_DEAD) |
| 659 | return CN_DEAD; |
| 660 | |
| 661 | if (oldStateCn != CN_ACTIVE && oldStateCn != CN_LIMBO) |
| 662 | ERR_bugcheck_msg("TPC: Attempt to mark inactive transaction to be dead"); |
| 663 | |
| 664 | statePtr->store(CN_DEAD, std::memory_order_relaxed); |
no test coverage detected