| 798 | } |
| 799 | |
| 800 | void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction) |
| 801 | { |
| 802 | /************************************** |
| 803 | * |
| 804 | * V I O _ b a c k o u t |
| 805 | * |
| 806 | ************************************** |
| 807 | * |
| 808 | * Functional description |
| 809 | * Backout the current version of a record. This may called |
| 810 | * either because of transaction death or because the record |
| 811 | * violated a unique index. In either case, get rid of the |
| 812 | * current version and back an old version. |
| 813 | * |
| 814 | * This routine is called with an inactive record_param, and has to |
| 815 | * take great pains to avoid conflicting with another process |
| 816 | * which is also trying to backout the same record. On exit |
| 817 | * there is no active record_param, and the record may or may not have |
| 818 | * been backed out, depending on whether we encountered conflict. |
| 819 | * But this record is doomed, and if we don't get it somebody |
| 820 | * will. |
| 821 | * |
| 822 | **************************************/ |
| 823 | SET_TDBB(tdbb); |
| 824 | Database* dbb = tdbb->getDatabase(); |
| 825 | CHECK_DBB(dbb); |
| 826 | |
| 827 | fb_assert(assert_gc_enabled(transaction, rpb->rpb_relation)); |
| 828 | |
| 829 | jrd_rel* const relation = rpb->rpb_relation; |
| 830 | |
| 831 | #ifdef VIO_DEBUG |
| 832 | VIO_trace(DEBUG_WRITES, |
| 833 | "VIO_backout (rel_id %u, record_param %" SQUADFORMAT", transaction %" SQUADFORMAT")\n", |
| 834 | relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0); |
| 835 | #endif |
| 836 | |
| 837 | // If there is data in the record, fetch it now. If the old version |
| 838 | // is a differences record, we will need it sooner. In any case, we |
| 839 | // will need it eventually to clean up blobs and indices. If the record |
| 840 | // has changed in between, stop now before things get worse. |
| 841 | |
| 842 | record_param temp = *rpb; |
| 843 | if (!DPM_get(tdbb, &temp, LCK_read)) |
| 844 | return; |
| 845 | |
| 846 | #ifdef VIO_DEBUG |
| 847 | VIO_trace(DEBUG_WRITES_INFO, |
| 848 | " record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT |
| 849 | ", flags %d, back %" SLONGFORMAT":%d, fragment %" SLONGFORMAT":%d\n", |
| 850 | temp.rpb_page, temp.rpb_line, temp.rpb_transaction_nr, |
| 851 | temp.rpb_flags, temp.rpb_b_page, temp.rpb_b_line, |
| 852 | temp.rpb_f_page, temp.rpb_f_line); |
| 853 | |
| 854 | if (temp.rpb_b_page != rpb->rpb_b_page || temp.rpb_b_line != rpb->rpb_b_line || |
| 855 | temp.rpb_transaction_nr != rpb->rpb_transaction_nr) |
| 856 | { |
| 857 | VIO_trace(DEBUG_WRITES_INFO, |
no test coverage detected