| 501 | } |
| 502 | |
| 503 | TipCache::TransactionStatusBlock* TipCache::getTransactionStatusBlock(GlobalTpcHeader* header, TpcBlockNumber blockNumber, Sync& sync) |
| 504 | { |
| 505 | fb_assert(sync.getState() == SYNC_NONE); |
| 506 | |
| 507 | // This is a double-checked locking pattern. SyncLockGuard uses atomic ops internally and should be cheap |
| 508 | TransactionStatusBlock* block = NULL; |
| 509 | { |
| 510 | sync.lock(SYNC_SHARED); |
| 511 | BlocksMemoryMap::ConstAccessor acc(&m_blocks_memory); |
| 512 | if (acc.locate(blockNumber)) |
| 513 | block = acc.current()->memory->getHeader(); |
| 514 | else |
| 515 | sync.unlock(); |
| 516 | } |
| 517 | |
| 518 | if (!block) |
| 519 | { |
| 520 | sync.lock(SYNC_EXCLUSIVE); |
| 521 | BlocksMemoryMap::ConstAccessor acc(&m_blocks_memory); |
| 522 | if (acc.locate(blockNumber)) |
| 523 | block = acc.current()->memory->getHeader(); |
| 524 | else |
| 525 | { |
| 526 | // Check if block might be too old to be created. |
| 527 | TraNumber oldest = header->oldest_transaction.load(std::memory_order_relaxed); |
| 528 | if (blockNumber >= oldest / m_transactionsPerBlock) |
| 529 | block = createTransactionStatusBlock(header->tpc_block_size, blockNumber); |
| 530 | else |
| 531 | sync.unlock(); |
| 532 | } |
| 533 | } |
| 534 | return block; |
| 535 | } |
| 536 | |
| 537 | TraNumber TipCache::findStates(TraNumber minNumber, TraNumber maxNumber, ULONG mask, int& state) |
| 538 | { |