81
86
* -----------------------------------------------------------------------
87
* Handle Error Detected in a Table
92
xtRecordID ter_rec_id;
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)
97
XTTableError *ter_a = ((XTTableError *) a);
98
XTTableError *ter_b = (XTTableError *) b;
100
if (ter_a->ter_tab_id < ter_b->ter_tab_id)
102
if (ter_a->ter_tab_id == ter_b->ter_tab_id) {
103
if (ter_a->ter_rec_id < ter_b->ter_rec_id)
105
if (ter_a->ter_rec_id == ter_b->ter_rec_id)
112
static xtBool tab_record_corrupt(XTOpenTablePtr ot, xtRowID row_id, xtRecordID rec_id, bool not_valid, int where)
114
XTTableHPtr tab = ot->ot_table;
115
XTDatabaseHPtr db = tab->tab_db;
117
XTTableError *ter_ptr;
119
ter.ter_tab_id = tab->tab_id;
120
ter.ter_rec_id = rec_id;
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))) {
125
char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
127
ok = xt_sl_insert(NULL, db->db_error_list, &ter, &ter);
128
xt_sl_unlock_ns(db->db_error_list);
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,
137
not_valid ? "not valid" : "free");
140
xt_sl_unlock_ns(db->db_error_list);
145
* -----------------------------------------------------------------------
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);
591
656
if (db->db_multi_path) {
592
657
XTOpenFilePtr of;
2095
xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool check_recs, bool correct_count)
2097
char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
2098
register XTTableHPtr tab = ot->ot_table;
2099
xtRowID prev_row_id;
2101
xtRefID next_row_id;
2104
xt_tab_make_table_name(tab->tab_name, table_name, sizeof(table_name));
2106
xtRecordID prev_rec_id;
2108
XTTabRecExtDRec rec_buf;
2110
xt_lock_mutex_ns(&tab->tab_rec_lock);
2111
/* Checking the free list: */
2114
rec_id = tab->tab_rec_free_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);
2119
xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_rec_id);
2121
xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
2122
xt_tab_set_table_repair_pending(tab);
2125
if (!xt_tab_get_rec_data(ot, rec_id, XT_REC_FIX_HEADER_SIZE, (xtWord1 *) &rec_buf)) {
2129
xt_log_and_clear_warning(ot->ot_thread);
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);
2135
prev_rec_id = rec_id;
2136
rec_id = XT_GET_DISK_4(rec_buf.tr_prev_rec_id_4);
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);
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);
2148
xt_unlock_mutex_ns(&tab->tab_rec_lock);
2151
/* Check the row free list: */
2152
xt_lock_mutex_ns(&tab->tab_row_lock);
2156
row_id = tab->tab_row_free_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);
2161
xt_logf(XT_NT_ERROR, "reference by: %llu\n", (u_llong) prev_row_id);
2163
xt_logf(XT_NT_ERROR, "reference by list head pointer\n");
2164
xt_tab_set_table_repair_pending(tab);
2167
if (!tab->tab_rows.xt_tc_read_4(ot->ot_row_file, row_id, &next_row_id, ot->ot_thread)) {
2171
xt_log_and_clear_warning(ot->ot_thread);
2175
prev_row_id = row_id;
2176
row_id = next_row_id;
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
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.
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.
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.
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);
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);
2202
xt_unlock_mutex_ns(&tab->tab_row_lock);
2016
2206
* Record buffer size:
2017
2207
* -------------------
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));
2438
#ifdef CHECK_TABLE_READ_DATA_LOG
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));
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) {
2577
row_id = tab->tab_row_free_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);
2582
xt_logf(XT_INFO, "reference by: %llu\n", (u_llong) prec_id);
2584
xt_logf(XT_INFO, "reference by list head pointer\n");
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);
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);
2377
2598
freer_(); // xt_unlock_mutex(&tab->tab_row_lock);
2379
2600
#ifdef CHECK_INDEX_ON_CHECK_TABLE
4348
4582
xt_unlock_mutex_ns(&tab->tab_rec_lock);
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))
4354
4590
static xtRowID tab_new_row(XTOpenTablePtr ot, XTTableHPtr tab)