| 135 | } |
| 136 | |
| 137 | void TipCache::finalizeTpc(thread_db* tdbb) |
| 138 | { |
| 139 | // check for finalizeTpc() called more than once |
| 140 | if (!m_lock.hasData()) |
| 141 | return; |
| 142 | |
| 143 | // To avoid race conditions, this function might only |
| 144 | // be called during database shutdown when AST delivery is already disabled |
| 145 | |
| 146 | // wait for all initializing processes (PR) |
| 147 | if (!LCK_convert(tdbb, m_lock, LCK_SW, LCK_WAIT)) |
| 148 | ERR_bugcheck_msg("Unable to convert TPC lock (SW)"); |
| 149 | |
| 150 | // Release locks and deallocate all shared memory structures |
| 151 | if (m_blocks_memory.getFirst()) |
| 152 | { |
| 153 | do |
| 154 | { |
| 155 | StatusBlockData* cur = m_blocks_memory.current(); |
| 156 | delete cur; |
| 157 | } while (m_blocks_memory.getNext()); |
| 158 | } |
| 159 | |
| 160 | PathName nmSnap, nmHdr; |
| 161 | if (m_snapshots) |
| 162 | { |
| 163 | nmSnap = m_snapshots->getMapFileName(); |
| 164 | delete m_snapshots; |
| 165 | m_snapshots = NULL; |
| 166 | } |
| 167 | |
| 168 | if (m_tpcHeader) |
| 169 | { |
| 170 | nmHdr = m_tpcHeader->getMapFileName(); |
| 171 | delete m_tpcHeader; |
| 172 | m_tpcHeader = NULL; |
| 173 | } |
| 174 | |
| 175 | m_blocks_memory.clear(); |
| 176 | m_transactionsPerBlock = 0; |
| 177 | |
| 178 | if (nmSnap.hasData() || nmHdr.hasData()) |
| 179 | { |
| 180 | if (LCK_lock(tdbb, m_lock, LCK_EX, LCK_NO_WAIT)) |
| 181 | { |
| 182 | if (nmSnap.hasData()) |
| 183 | SharedMemoryBase::unlinkFile(nmSnap.c_str()); |
| 184 | if (nmHdr.hasData()) |
| 185 | SharedMemoryBase::unlinkFile(nmHdr.c_str()); |
| 186 | |
| 187 | LCK_release(tdbb, m_lock); |
| 188 | } |
| 189 | else |
| 190 | tdbb->tdbb_status_vector->init(); |
| 191 | } |
| 192 | else |
| 193 | LCK_release(tdbb, m_lock); |
| 194 |
no test coverage detected