~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbxt/src/table_xt.cc

  • Committer: lbieber
  • Date: 2010-09-22 13:48:54 UTC
  • mfrom: (1784.1.3 build)
  • Revision ID: lbieber@orisndriz08-20100922134854-y7mae2taqhn73vsx
Merge Paul M. - latest changes from PBXT 1.0.11-7
Merge Paul M. - fix bug 641038 - pbxt rollback not working (tables reported as non-transactional)
Merge Andrew - fix show stoppers for new drizzledump

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
 
61
61
#define CHECK_TABLE_STATS
62
62
 
 
63
/* The problem is that this can take a long time
 
64
 * if the table is very large!
 
65
 */
 
66
//#define CHECK_TABLE_READ_DATA_LOG
 
67
 
63
68
#ifdef TRACE_TABLE_IDS
64
69
//#define PRINTF                xt_ftracef
65
70
#define PRINTF          xt_trace
79
84
 
80
85
/*
81
86
 * -----------------------------------------------------------------------
 
87
 * Handle Error Detected in a Table
 
88
 */
 
89
 
 
90
struct XTTableError {
 
91
        xtTableID               ter_tab_id;
 
92
        xtRecordID              ter_rec_id;
 
93
};
 
94
 
 
95
static int tab_comp_tab_error(XTThreadPtr XT_UNUSED(self), register const void *XT_UNUSED(thunk), register const void *a, register const void *b)
 
96
{
 
97
        XTTableError    *ter_a = ((XTTableError *) a);
 
98
        XTTableError    *ter_b = (XTTableError *) b;
 
99
 
 
100
        if (ter_a->ter_tab_id < ter_b->ter_tab_id)
 
101
                return -1;
 
102
        if (ter_a->ter_tab_id == ter_b->ter_tab_id) {
 
103
                if (ter_a->ter_rec_id < ter_b->ter_rec_id)
 
104
                        return -1;
 
105
                if (ter_a->ter_rec_id == ter_b->ter_rec_id)
 
106
                        return 0;
 
107
                return 1;
 
108
        }
 
109
        return 1;
 
110
}
 
111
 
 
112
static xtBool tab_record_corrupt(XTOpenTablePtr ot, xtRowID row_id, xtRecordID rec_id, bool not_valid, int where)
 
113
{
 
114
        XTTableHPtr             tab = ot->ot_table;
 
115
        XTDatabaseHPtr  db = tab->tab_db;
 
116
        XTTableError    ter;
 
117
        XTTableError    *ter_ptr;
 
118
        
 
119
        ter.ter_tab_id = tab->tab_id;
 
120
        ter.ter_rec_id = rec_id;
 
121
        
 
122
        xt_sl_lock_ns(db->db_error_list, ot->ot_thread);
 
123
        if (!(ter_ptr = (XTTableError *) xt_sl_find(NULL, db->db_error_list, &ter))) {
 
124
                xtBool  ok;
 
125
                char    table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
 
126
 
 
127
                ok = xt_sl_insert(NULL, db->db_error_list, &ter, &ter);
 
128
                xt_sl_unlock_ns(db->db_error_list);
 
129
                if (!ok)
 
130
                        return FAILED;
 
131
                xt_tab_set_table_repair_pending(tab);
 
132
                xt_tab_make_table_name(tab->tab_name, table_name, sizeof(table_name));
 
133
                xt_logf(XT_NT_ERROR, "#%d Table %s: row %llu, record %llu, is %s, REPAIR TABLE required.\n", where,
 
134
                        table_name, 
 
135
                        (u_llong) row_id,
 
136
                        (u_llong) rec_id,
 
137
                        not_valid ? "not valid" : "free");
 
138
        }
 
139
        else
 
140
                xt_sl_unlock_ns(db->db_error_list);
 
141
        return OK;
 
142
}
 
143
 
 
144
/*
 
145
 * -----------------------------------------------------------------------
82
146
 * Compare paths:
83
147
 */
84
148
 
587
651
                db->db_tables = xt_new_hashtable(self, tab_list_comp, tab_list_hash, tab_list_free, TRUE, TRUE);
588
652
        db->db_table_by_id = xt_new_sortedlist(self, sizeof(XTTableEntryRec), 20, 20, tab_comp_by_id, db, tab_free_by_id, FALSE, FALSE);
589
653
        db->db_table_paths = xt_new_sortedlist(self, sizeof(XTTablePathPtr), 20, 20, tab_comp_path, db, tab_free_path, FALSE, FALSE);
 
654
        db->db_error_list = xt_new_sortedlist(self, sizeof(XTTableError), 20, 20, tab_comp_tab_error, db, NULL, TRUE, FALSE);
590
655
 
591
656
        if (db->db_multi_path) {
592
657
                XTOpenFilePtr   of;
664
729
        }
665
730
        freer_(); // xt_describe_tables_exit(&desc)
666
731
 
 
732
        /*
 
733
         * When we open all tables, we ignore problems with foreign keys.
 
734
         * This must be done or we will not be able to load tables that
 
735
         * were created with foreign key checks off.
 
736
         */
 
737
        self->st_ignore_fkeys = 1;
667
738
        /* 
668
739
         * The purpose of this code is to ensure that all tables are opened and cached,
669
740
         * which is actually only required if tables have foreign key references.
695
766
                else
696
767
                        xt_log_and_clear_warning(self);
697
768
        }
 
769
        self->st_ignore_fkeys = 0;
698
770
 
699
771
        popr_(); // Discard xt_tab_exit_db(db)
700
772
        exit_();
871
943
                xt_free_sortedlist(self, db->db_table_paths);
872
944
                db->db_table_paths = NULL;
873
945
        }
 
946
        if (db->db_error_list) {
 
947
                xt_free_sortedlist(self, db->db_error_list);
 
948
                db->db_error_list = NULL;
 
949
        }
874
950
}
875
951
 
876
952
 
1454
1530
        if (tab->tab_dic.dic_table) {
1455
1531
                try_(a) {
1456
1532
                        tab->tab_dic.dic_table->attachReferences(self, db);
1457
 
                } catch_(a) {
1458
 
                        /* ignore problems of referenced tables */
1459
 
                        xt_log_and_clear_warning(self);
1460
 
                } cont_(a);
 
1533
                }
 
1534
                catch_(a) {
 
1535
                        /* Errors are thrown when: set foreign_key_checks = 1 */
 
1536
                        /* Undo everything done above: */
 
1537
                        xt_ht_del(self, db->db_tables, tab->tab_name);
 
1538
                        xt_throw(self);
 
1539
                }
 
1540
                cont_(a);
1461
1541
        }
1462
1542
 
1463
1543
        *r_tab = tab;
2012
2092
        exit_();
2013
2093
}
2014
2094
 
 
2095
xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool check_recs, bool correct_count)
 
2096
{
 
2097
        char                                    table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
 
2098
        register XTTableHPtr    tab = ot->ot_table;
 
2099
        xtRowID                                 prev_row_id;
 
2100
        xtRowID                                 row_id;
 
2101
        xtRefID                                 next_row_id;
 
2102
        u_llong                                 free_count;
 
2103
 
 
2104
        xt_tab_make_table_name(tab->tab_name, table_name, sizeof(table_name));
 
2105
        if (check_recs) {
 
2106
                xtRecordID              prev_rec_id;
 
2107
                xtRecordID              rec_id;
 
2108
                XTTabRecExtDRec rec_buf;
 
2109
 
 
2110
                xt_lock_mutex_ns(&tab->tab_rec_lock);
 
2111
                /* Checking the free list: */
 
2112
                prev_rec_id = 0;
 
2113
                free_count = 0;
 
2114
                rec_id = tab->tab_rec_free_id;
 
2115
                while (rec_id) {
 
2116
                        if (rec_id >= tab->tab_rec_eof_id) {
 
2117
                                xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free list: %llu, ", table_name, (u_llong) rec_id);
 
2118
                                if (prev_rec_id)
 
2119
                                        xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_rec_id);
 
2120
                                else
 
2121
                                        xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
 
2122
                                xt_tab_set_table_repair_pending(tab);
 
2123
                                break;
 
2124
                        }
 
2125
                        if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_FIX_HEADER_SIZE, (xtWord1 *) &rec_buf)) {
 
2126
                                if (self)
 
2127
                                        xt_throw(self);
 
2128
                                else
 
2129
                                        xt_log_and_clear_warning(ot->ot_thread);
 
2130
                                break;
 
2131
                        }
 
2132
                        if ((rec_buf.tr_rec_type_1 & XT_TAB_STATUS_MASK) != XT_TAB_STATUS_FREED)
 
2133
                                xt_logf(XT_NT_INFO, "Table %s: record, %llu, on free list is not free\n", table_name, (u_llong) rec_id);
 
2134
                        free_count++;
 
2135
                        prev_rec_id = rec_id;
 
2136
                        rec_id = XT_GET_DISK_4(rec_buf.tr_prev_rec_id_4);
 
2137
                }
 
2138
                if (free_count != tab->tab_rec_fnum) {
 
2139
                        if (correct_count) {
 
2140
                                tab->tab_rec_fnum = free_count;
 
2141
                                tab->tab_head_rec_fnum = free_count;
 
2142
                                tab->tab_flush_pending = TRUE;
 
2143
                                xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) has been set to the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count);
 
2144
                        }
 
2145
                        else
 
2146
                                xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) differs from the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count);
 
2147
                }
 
2148
                xt_unlock_mutex_ns(&tab->tab_rec_lock);
 
2149
        }
 
2150
 
 
2151
        /* Check the row free list: */
 
2152
        xt_lock_mutex_ns(&tab->tab_row_lock);
 
2153
 
 
2154
        prev_row_id = 0;
 
2155
        free_count = 0;
 
2156
        row_id = tab->tab_row_free_id;
 
2157
        while (row_id) {
 
2158
                if (row_id >= tab->tab_row_eof_id) {
 
2159
                        xt_logf(XT_NT_ERROR, "Table %s: invalid reference on free row: %llu, ", table_name, (u_llong) row_id);
 
2160
                        if (prev_row_id)
 
2161
                                xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_row_id);
 
2162
                        else
 
2163
                                xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
 
2164
                        xt_tab_set_table_repair_pending(tab);
 
2165
                        break;
 
2166
                }
 
2167
                if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &next_row_id, ot->ot_thread)) {
 
2168
                        if (self)
 
2169
                                xt_throw(self);
 
2170
                        else
 
2171
                                xt_log_and_clear_warning(ot->ot_thread);
 
2172
                        break;
 
2173
                }
 
2174
                free_count++;
 
2175
                prev_row_id = row_id;
 
2176
                row_id = next_row_id;
 
2177
        }
 
2178
        if (free_count != tab->tab_row_fnum) {
 
2179
                if (correct_count) {
 
2180
                        /* tab_row_fnum is the current value, and tab_head_row_fnum is the value on
 
2181
                         * disk. tab_head_row_fnum is set by the writer as the changes are applied
 
2182
                         * to the database.
 
2183
                         *
 
2184
                         * This is the value then stored in the header of the file. This value
 
2185
                         * is in sync with other changes to the file.
 
2186
                         *
 
2187
                         * So the fact that I am setting both value means this will not work at
 
2188
                         * runtime, unless all changes have been applied by the writer.
 
2189
                         *
 
2190
                         * The correct way to do this at run time would be to add the change to the
 
2191
                         * transaction log, so that it is applied by the writer.
 
2192
                         */
 
2193
                        tab->tab_row_fnum = free_count;
 
2194
                        tab->tab_head_row_fnum = free_count;
 
2195
                        tab->tab_flush_pending = TRUE;
 
2196
                        xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) has been set to the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count);
 
2197
                }
 
2198
                else
 
2199
                        xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) differs from the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count);
 
2200
        }
 
2201
 
 
2202
        xt_unlock_mutex_ns(&tab->tab_row_lock);
 
2203
}
 
2204
 
2015
2205
/*
2016
2206
 * Record buffer size:
2017
2207
 * -------------------
2092
2282
        XTTableHPtr                             tab = ot->ot_table;
2093
2283
        xtRecordID                              prec_id;
2094
2284
        XTTabRecExtDPtr                 rec_buf = (XTTabRecExtDPtr) ot->ot_row_rbuffer;
 
2285
#ifdef CHECK_TABLE_READ_DATA_LOG
2095
2286
        XTactExtRecEntryDRec    ext_rec;
2096
2287
        size_t                                  log_size;
2097
2288
        xtLogID                                 log_id;
2098
2289
        xtLogOffset                             log_offset;
 
2290
#endif
2099
2291
        xtRecordID                              rec_id;
2100
2292
        xtRecordID                              prev_rec_id;
2101
2293
        xtXactID                                xn_id;
2109
2301
        size_t                                  rec_size;
2110
2302
        size_t                                  row_size;
2111
2303
        u_llong                                 ext_data_len = 0;
 
2304
        u_llong                                 ext_rec_count = 0;
2112
2305
 
2113
2306
#if defined(DUMP_CHECK_TABLE) || defined(CHECK_TABLE_STATS)
2114
2307
        printf("\nCHECK TABLE: %s\n", tab->tab_name->ps_path);
2212
2405
                                printf("record-X ");
2213
2406
#endif
2214
2407
                                alloc_rec_count++;
 
2408
                                ext_rec_count++;
2215
2409
                                ext_data_len += XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
2216
2410
                                row_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4) + ot->ot_rec_size - XT_REC_EXT_HEADER_SIZE;
2217
2411
                                alloc_rec_bytes += row_size;
2237
2431
#endif
2238
2432
                                break;
2239
2433
                        case XT_TAB_STATUS_EXT_DLOG:
 
2434
#ifdef DUMP_CHECK_TABLE
 
2435
                                printf(" prev=%-3llu  xact=%-3llu row=%lu  Xlog=%lu Xoff=%llu Xsiz=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id, (u_long) XT_GET_DISK_2(rec_buf->re_log_id_2), (u_llong) XT_GET_DISK_6(rec_buf->re_log_offs_6), (u_long) XT_GET_DISK_4(rec_buf->re_log_dat_siz_4));
 
2436
#endif
 
2437
 
 
2438
#ifdef CHECK_TABLE_READ_DATA_LOG
2240
2439
                                xtBool ok;
2241
2440
 
2242
 
#ifdef DUMP_CHECK_TABLE
2243
 
                                printf(" prev=%-3llu  xact=%-3llu row=%lu  Xlog=%lu Xoff=%llu Xsiz=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id, (u_long) XT_GET_DISK_2(rec_buf->re_log_id_2), (u_llong) XT_GET_DISK_6(rec_buf->re_log_offs_6), (u_long) XT_GET_DISK_4(rec_buf->re_log_dat_siz_4));
2244
 
#endif
2245
 
 
2246
2441
                                log_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
2247
2442
                                XT_GET_LOG_REF(log_id, log_offset, rec_buf);
2248
2443
                                if (ot->ot_table->tab_dic.dic_tab_flags & XT_TF_MEMORY_TABLE) {
2265
2460
                                                xt_logf(XT_INFO, "Table %s: record %llu, extended record %lu:%llu not valid\n", tab->tab_name, (u_llong) rec_id, (u_long) log_id, (u_llong) log_offset);
2266
2461
                                        }
2267
2462
                                }
 
2463
#endif
2268
2464
                                break;
2269
2465
                        default:
2270
2466
#ifdef DUMP_CHECK_TABLE
2286
2482
                if (!tab->tab_dic.dic_rec_fixed) {
2287
2483
                        xt_int8_to_byte_size((xtInt8) tab->tab_mem_total, value);
2288
2484
                        printf("Ext. record memory used = %s\n", value);
 
2485
                        printf("Extended record count   = %llu\n", ext_rec_count);
2289
2486
                }
2290
2487
                xt_int8_to_byte_size((xtInt8) ind, value);
2291
2488
                printf("Index data memory used  = %s\n", value);
2298
2495
                if (!tab->tab_dic.dic_rec_fixed) {
2299
2496
                        xt_int8_to_byte_size((xtInt8) ext_data_len, value);
2300
2497
                        printf("Ext. record disk used   = %s\n", value);                
 
2498
                        printf("Extended record count   = %llu\n", ext_rec_count);
2301
2499
                }
2302
2500
                xt_int8_to_byte_size((xtInt8) ind, value);
2303
2501
                printf("Index disk space used   = %s\n", value);
2342
2540
                prec_id = rec_id;
2343
2541
                rec_id = XT_GET_DISK_4(rec_buf->tr_prev_rec_id_4);
2344
2542
        }
2345
 
        if (free_count2 < free_rec_count)
 
2543
        if (free_count2 != free_rec_count)
2346
2544
                xt_logf(XT_INFO, "Table %s: not all free blocks (%llu) on free list: %llu\n", tab->tab_name, (u_llong) free_rec_count, (u_llong) free_count2);
2347
2545
 
2348
2546
        freer_(); // xt_unlock_mutex_ns(&tab->tab_rec_lock);
2374
2572
                rec_id++;
2375
2573
        }
2376
2574
 
 
2575
        prec_id = 0;
 
2576
        free_count2 = 0;
 
2577
        row_id = tab->tab_row_free_id;
 
2578
        while (row_id) {
 
2579
                if (row_id >= tab->tab_row_eof_id) {
 
2580
                        xt_logf(XT_INFO, "Table %s: invalid reference on free row: %llu, ", tab->tab_name, (u_llong) row_id);
 
2581
                        if (prec_id)
 
2582
                                xt_logf(XT_INFO, "reference by: %llu\n", (u_llong) prec_id);
 
2583
                        else
 
2584
                                xt_logf(XT_INFO, "reference by list head pointer\n");
 
2585
                        break;
 
2586
                }
 
2587
                if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &ref_id, self)) {
 
2588
                        xt_log_and_clear_exception(self);
 
2589
                        break;
 
2590
                }
 
2591
                free_count2++;
 
2592
                prec_id = row_id;
 
2593
                row_id = ref_id;
 
2594
        }
 
2595
        if (free_count2 != tab->tab_row_fnum)
 
2596
                xt_logf(XT_INFO, "Table %s: free row count (%llu) differs from the number of row on the list: %llu\n", tab->tab_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count2);
 
2597
 
2377
2598
        freer_(); // xt_unlock_mutex(&tab->tab_row_lock);
2378
2599
 
2379
2600
#ifdef CHECK_INDEX_ON_CHECK_TABLE
3590
3811
#endif
3591
3812
                                break;
3592
3813
                        case XT_XN_REREAD:
 
3814
                                /* {RETRY-READ}
 
3815
                                 * TODO: This is not as "correct" as it could be.
 
3816
                                 * Such records should be considered to be aborted,
 
3817
                                 * and removed from the list.
 
3818
                                 */
3593
3819
                                if (invalid_rec != var_rec_id) {
3594
3820
                                        invalid_rec = var_rec_id;
3595
3821
                                        goto retry_3;
3596
3822
                                }
 
3823
                                if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 1))
 
3824
                                        goto failed;
 
3825
 
3597
3826
                                /* Assume end of list. */
3598
3827
#ifdef XT_CRASH_DEBUG
3599
3828
                                /* Should not happen! */
3781
4010
                        /* Avoid infinite loop: */
3782
4011
                        if (read_again) {
3783
4012
                                /* Should not happen! */
 
4013
                                if (!tab_record_corrupt(ot, row_id, ot->ot_curr_rec_id, true, 2))
 
4014
                                        return XT_ERR;
3784
4015
#ifdef XT_CRASH_DEBUG
3785
4016
                                /* Generate a core dump! */
3786
4017
                                xt_crash_me();
3837
4068
                        /* Avoid infinite loop: */
3838
4069
                        if (read_again) {
3839
4070
                                /* Should not happen! */
 
4071
                                if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) ot->ot_row_rbuffer)->tr_row_id_4), ot->ot_curr_rec_id, true, 3))
 
4072
                                        return XT_ERR;
3840
4073
#ifdef XT_CRASH_DEBUG
3841
4074
                                /* Generate a core dump! */
3842
4075
                                xt_crash_me();
4053
4286
        }
4054
4287
        tab->tab_row_free_id = row_id;
4055
4288
        tab->tab_row_fnum++;
 
4289
        ASSERT_NS(tab->tab_row_fnum < tab->tab_row_eof_id);
4056
4290
        xt_unlock_mutex_ns(&tab->tab_row_lock);
4057
4291
 
4058
4292
        if (!xt_xlog_modify_table(tab->tab_id, XT_LOG_ENT_ROW_FREED, op_seq, 0, 0, row_id, sizeof(XTTabRowRefDRec), (xtWord1 *) &free_row, ot->ot_thread))
4253
4487
                xt_lock_mutex_ns(&tab->tab_db->db_co_ext_lock);
4254
4488
                if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_EXT_HEADER_SIZE, ot->ot_row_rbuffer)) {
4255
4489
                        xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock);
4256
 
                        return FAILED;
 
4490
                        return XT_ERR;
4257
4491
                }
4258
4492
                xt_unlock_mutex_ns(&tab->tab_db->db_co_ext_lock);
4259
4493
 
4339
4573
        XT_SET_DISK_4(free_rec->rf_next_rec_id_4, prev_rec_id);
4340
4574
        if (!xt_tab_put_rec_data(ot, rec_id, sizeof(XTTabRecFreeDRec), ot->ot_row_rbuffer, &op_seq)) {
4341
4575
                xt_unlock_mutex_ns(&tab->tab_rec_lock);
4342
 
                return FAILED;
 
4576
                return XT_ERR;
4343
4577
        }
4344
4578
        tab->tab_rec_free_id = rec_id;
4345
4579
        ASSERT_NS(tab->tab_rec_free_id < tab->tab_rec_eof_id);
4348
4582
        xt_unlock_mutex_ns(&tab->tab_rec_lock);
4349
4583
 
4350
4584
        free_rec->rf_rec_type_1 = old_rec_type;
4351
 
        return xt_xlog_modify_table(tab->tab_id, status, op_seq, new_rec_type, prev_rec_id, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread);
 
4585
        if (!xt_xlog_modify_table(tab->tab_id, status, op_seq, new_rec_type, prev_rec_id, rec_id, rec_size, ot->ot_row_rbuffer, ot->ot_thread))
 
4586
                return XT_ERR;
 
4587
        return OK;
4352
4588
}
4353
4589
 
4354
4590
static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab)
4367
4603
                        return 0;
4368
4604
                }
4369
4605
                tab->tab_row_free_id = next_row_id;
 
4606
                ASSERT_NS(tab->tab_row_fnum > 0);
4370
4607
                tab->tab_row_fnum--;
4371
4608
        }
4372
4609
        else {
4672
4909
                        return FAILED;
4673
4910
                if (XT_REC_IS_CLEAN(var_head.tr_rec_type_1))
4674
4911
                        goto locked;
4675
 
                if (XT_REC_IS_FREE(var_head.tr_rec_type_1))
 
4912
                if (XT_REC_IS_FREE(var_head.tr_rec_type_1)) {
4676
4913
                        /* Should not happen: */
 
4914
                        if (!tab_record_corrupt(ot, row_id, var_rec_id, false, 4))
 
4915
                                return FAILED;
4677
4916
                        goto record_invalid;
 
4917
                }
4678
4918
                xn_id = XT_GET_DISK_4(var_head.tr_xact_id_4);
4679
4919
                switch (xt_xn_status(ot, xn_id, var_rec_id)) {
4680
4920
                        case XT_XN_VISIBLE:
4697
4937
                                XT_TAB_ROW_WRITE_LOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread);
4698
4938
                                goto retry;
4699
4939
                        case XT_XN_REREAD:
 
4940
                                if (!tab_record_corrupt(ot, row_id, var_rec_id, true, 5))
 
4941
                                        return FAILED;
4700
4942
                                goto record_invalid;
4701
4943
                }
4702
4944
                var_rec_id = XT_GET_DISK_4(var_head.tr_prev_rec_id_4);
4708
4950
        return FAILED;
4709
4951
        
4710
4952
        record_invalid:
 
4953
        /* {RETRY-READ} */
4711
4954
        /* Prevent an infinite loop due to a bad record: */
4712
4955
        if (invalid_rec != var_rec_id) {
4713
 
                var_rec_id = invalid_rec;
 
4956
                invalid_rec = var_rec_id;
4714
4957
                goto retry;
4715
4958
        }
4716
4959
        /* The record is invalid, it will be "overwritten"... */
4733
4976
        xtXactID                                rec_xn_id = 0;
4734
4977
        xtBool                                  wait = FALSE;
4735
4978
        xtXactID                                wait_xn_id = 0;
4736
 
        xtRowID                                 row_id;
 
4979
        xtRowID                                 row_id = 0;  // Initialized unnecessarily to satisfy (Drizzle) compile [-Wuninitialized]
4737
4980
        xtRecordID                              var_rec_id;
4738
4981
        xtXactID                                xn_id;
4739
 
        register XTTableHPtr    tab;
 
4982
        register XTTableHPtr    tab = NULL; // Initialized unnecessarily to satisfy (Drizzle) compile [-Wuninitialized]
4740
4983
#ifdef TRACE_VARIATIONS_IN_DUP_CHECK
4741
4984
        char                                    t_buf[500];
4742
4985
        int                                             len;
4782
5025
#ifdef TRACE_VARIATIONS_IN_DUP_CHECK
4783
5026
                                t_type="Re-read";
4784
5027
#endif
 
5028
                                /* {RETRY-READ} */
4785
5029
                                /* Avoid infinite loop: */
4786
5030
                                if (invalid_rec == rec_id) {
4787
5031
                                        /* Should not happen! */
 
5032
                                        if (!tab_record_corrupt(ot, XT_GET_DISK_4(rec_head.tr_row_id_4), rec_id, true, 6))
 
5033
                                                goto failed;
4788
5034
#ifdef XT_CRASH_DEBUG
4789
5035
                                        /* Generate a core dump! */
4790
5036
                                        xt_crash_me();
4829
5075
                if (XT_REC_IS_FREE(rec_head.tr_rec_type_1)) {
4830
5076
                        /* Should not happen: */
4831
5077
                        if (invalid_rec != var_rec_id) {
4832
 
                                var_rec_id = invalid_rec;
 
5078
                                invalid_rec = var_rec_id;
4833
5079
                                goto retry;
4834
5080
                        }
4835
5081
                        /* Assume end of list. */
4866
5112
                                }
4867
5113
                                break;
4868
5114
                        case XT_XN_REREAD:
 
5115
                                /* {RETRY-READ} */
4869
5116
                                if (invalid_rec != var_rec_id) {
4870
 
                                        var_rec_id = invalid_rec;
 
5117
                                        invalid_rec = var_rec_id;
4871
5118
                                        goto retry;
4872
5119
                                }
4873
5120
                                /* Assume end of list. */
 
5121
                                if (!tab_record_corrupt(ot, row_id, invalid_rec, true, 7))
 
5122
                                        goto failed;
4874
5123
#ifdef XT_CRASH_DEBUG
4875
5124
                                /* Should not happen! */
4876
5125
                                xt_crash_me();
5606
5855
                                ot->ot_on_page = FALSE;
5607
5856
                                goto next_page;
5608
5857
                        }
 
5858
                        if (!tab_record_corrupt(ot, XT_GET_DISK_4(((XTTabRecHeadDPtr) buff_ptr)->tr_row_id_4), invalid_rec, true, 8))
 
5859
                                return XT_ERR;
5609
5860
#ifdef XT_CRASH_DEBUG
5610
5861
                        /* Should not happen! */
5611
5862
                        xt_crash_me();