| 5806 | |
| 5807 | |
| 5808 | static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& staying, int flags) |
| 5809 | { |
| 5810 | /************************************** |
| 5811 | * |
| 5812 | * l i s t _ s t a y i n g |
| 5813 | * |
| 5814 | ************************************** |
| 5815 | * |
| 5816 | * Functional description |
| 5817 | * Get all the data that's staying so we can clean up indexes etc. |
| 5818 | * without losing anything. Note that in the middle somebody could |
| 5819 | * modify the record -- worse yet, somebody could modify it, commit, |
| 5820 | * and have somebody else modify it, so if the back pointers on the |
| 5821 | * original record change throw out what we've got and start over. |
| 5822 | * "All the data that's staying" is: all the versions of the input |
| 5823 | * record (rpb) that are stored in the relation. |
| 5824 | * |
| 5825 | **************************************/ |
| 5826 | SET_TDBB(tdbb); |
| 5827 | |
| 5828 | // Use fast way if possible |
| 5829 | if (rpb->rpb_transaction_nr) |
| 5830 | { |
| 5831 | jrd_tra* transaction = tdbb->getTransaction(); |
| 5832 | if (transaction && transaction->tra_number == rpb->rpb_transaction_nr) |
| 5833 | { |
| 5834 | list_staying_fast(tdbb, rpb, staying, NULL, flags); |
| 5835 | return; |
| 5836 | } |
| 5837 | } |
| 5838 | |
| 5839 | Record* data = rpb->rpb_prior; |
| 5840 | Record* backout_rec = NULL; |
| 5841 | ULONG next_page = rpb->rpb_page; |
| 5842 | USHORT next_line = rpb->rpb_line; |
| 5843 | int max_depth = 0; |
| 5844 | int depth = 0; |
| 5845 | |
| 5846 | // 2014-09-11 NS XXX: This algorithm currently has O(n^2) complexity, but can be |
| 5847 | // significantly optimized in a case when VIO_data doesn't have to chase fragments. |
| 5848 | // I won't implement this now, because intermediate GC shall reduce likelihood |
| 5849 | // of encountering long version chains to almost zero. |
| 5850 | RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation, |
| 5851 | RuntimeStatistics::RECORD_BACKVERSION_READS); |
| 5852 | |
| 5853 | |
| 5854 | // Limit number of "restarts" if primary version constantly changed. Currently, |
| 5855 | // LS_ACTIVE_RPB is passed by VIO_intermediate_gc only and it is ok to return |
| 5856 | // empty staying in this case. |
| 5857 | // Should think on this more before merge it into Firebird tree. |
| 5858 | |
| 5859 | int n = 0, max = (flags & LS_ACTIVE_RPB) ? 3 : 0; |
| 5860 | for (;;) |
| 5861 | { |
| 5862 | // Each time thru the loop, start from the latest version of the record |
| 5863 | // because during the call to VIO_data (below), things might change. |
| 5864 | |
| 5865 | record_param temp = *rpb; |
no test coverage detected