| 2357 | |
| 2358 | |
| 2359 | static ULONG inventory_page(thread_db* tdbb, ULONG sequence) |
| 2360 | { |
| 2361 | /************************************** |
| 2362 | * |
| 2363 | * i n v e n t o r y _ p a g e |
| 2364 | * |
| 2365 | ************************************** |
| 2366 | * |
| 2367 | * Functional description |
| 2368 | * Get the physical page number of the n-th transaction inventory |
| 2369 | * page. If not found, try to reconstruct using sibling pointer |
| 2370 | * from last known TIP page. |
| 2371 | * |
| 2372 | **************************************/ |
| 2373 | SET_TDBB(tdbb); |
| 2374 | Database* dbb = tdbb->getDatabase(); |
| 2375 | CHECK_DBB(dbb); |
| 2376 | |
| 2377 | if (const ULONG pageno = dbb->getKnownPage(pag_transactions, sequence)) |
| 2378 | return pageno; |
| 2379 | |
| 2380 | while (sequence >= dbb->getKnownPagesCount(pag_transactions)) |
| 2381 | { |
| 2382 | DPM_scan_pages(tdbb); |
| 2383 | |
| 2384 | const ULONG tipCount = dbb->getKnownPagesCount(pag_transactions); |
| 2385 | if (sequence < tipCount) |
| 2386 | break; |
| 2387 | |
| 2388 | if (!tipCount) |
| 2389 | BUGCHECK(165); // msg 165 cannot find tip page |
| 2390 | |
| 2391 | WIN window(DB_PAGE_SPACE, dbb->getKnownPage(pag_transactions, tipCount - 1)); |
| 2392 | tx_inv_page* tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions); |
| 2393 | const ULONG next = tip->tip_next; |
| 2394 | CCH_RELEASE(tdbb, &window); |
| 2395 | if (!(window.win_page = next)) |
| 2396 | BUGCHECK(165); // msg 165 cannot find tip page |
| 2397 | |
| 2398 | // Type check it |
| 2399 | tip = (tx_inv_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_transactions); |
| 2400 | CCH_RELEASE(tdbb, &window); |
| 2401 | DPM_pages(tdbb, 0, pag_transactions, tipCount, window.win_page.getPageNum()); |
| 2402 | } |
| 2403 | |
| 2404 | return dbb->getKnownPage(pag_transactions, sequence); |
| 2405 | } |
| 2406 | |
| 2407 | |
| 2408 | static int limbo_transaction(thread_db* tdbb, TraNumber id) |
no test coverage detected