| 772 | |
| 773 | |
| 774 | void TipCache::releaseSharedMemory(thread_db* tdbb, TraNumber oldest_old, TraNumber oldest_new) |
| 775 | { |
| 776 | Database* dbb = tdbb->getDatabase(); |
| 777 | |
| 778 | TpcBlockNumber lastInterestingBlockNumber = oldest_new / m_transactionsPerBlock; |
| 779 | |
| 780 | // If we didn't cross block boundary - there is nothing to do. |
| 781 | // Note that due to the fuzziness of our caller's memory access to variables |
| 782 | // there is an unlikely possibility that we might lose one such event. |
| 783 | // This is not too bad, and next such event will clean things up. |
| 784 | if (oldest_old / m_transactionsPerBlock == lastInterestingBlockNumber) |
| 785 | return; |
| 786 | |
| 787 | // Populate array of blocks that might be unmapped and deleted. |
| 788 | // We scan for blocks to clean up in descending order, but delete them in |
| 789 | // ascending order to ensure for robust operation. |
| 790 | PathName fileName; |
| 791 | HalfStaticArray<TpcBlockNumber, 16> blocksToCleanup; |
| 792 | |
| 793 | for (TpcBlockNumber cleanupCounter = lastInterestingBlockNumber - SAFETY_GAP_BLOCKS; |
| 794 | cleanupCounter; cleanupCounter--) |
| 795 | { |
| 796 | TpcBlockNumber blockNumber = cleanupCounter - 1; |
| 797 | PathName fileName = StatusBlockData::makeSharedMemoryFileName(dbb, blockNumber, true); |
| 798 | |
| 799 | struct stat st; |
| 800 | // If file is not found -- look no further |
| 801 | if (stat(fileName.c_str(), &st) != 0) |
| 802 | break; |
| 803 | |
| 804 | blocksToCleanup.add(blockNumber); |
| 805 | } |
| 806 | |
| 807 | if (blocksToCleanup.isEmpty()) |
| 808 | return; |
| 809 | |
| 810 | SyncLockGuard sync(&m_sync_status, SYNC_EXCLUSIVE, FB_FUNCTION); |
| 811 | while (blocksToCleanup.hasData()) |
| 812 | { |
| 813 | TpcBlockNumber blockNumber = blocksToCleanup.pop(); |
| 814 | |
| 815 | if (m_blocks_memory.locate(blockNumber)) |
| 816 | { |
| 817 | StatusBlockData* block = m_blocks_memory.current(); |
| 818 | m_blocks_memory.fastRemove(); |
| 819 | delete block; |
| 820 | } |
| 821 | |
| 822 | // Signal other processes to release resources |
| 823 | Lock temp(tdbb, sizeof(TpcBlockNumber), LCK_tpc_block); |
| 824 | temp.setKey(blockNumber); |
| 825 | if (!LCK_lock(tdbb, &temp, LCK_EX, LCK_WAIT)) |
| 826 | { |
| 827 | gds__log("TPC BUG: Unable to obtain cleanup lock for block %" UQUADFORMAT, blockNumber); |
| 828 | fb_assert(false); |
| 829 | break; |
| 830 | } |
| 831 |
nothing calls this directly
no test coverage detected