~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge Joe, plus I updated the tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2005 PrimeBase Technologies GmbH
 
1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
2
2
 *
3
3
 * PrimeBase XT
4
4
 *
14
14
 *
15
15
 * You should have received a copy of the GNU General Public License
16
16
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
 *
19
19
 * 2005-09-30   Paul McCullagh
20
20
 *
282
282
        }
283
283
 
284
284
        if ((XT_NODE_ID(wrote_pos) = XT_NODE_ID(tab->tab_ind_free))) {
285
 
                xtIndexNodeID next_node;
286
 
 
287
285
                /* Use the block on the free list: */
288
 
                if (!xt_ind_read_bytes(ot, NULL, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block))
289
 
                        goto failed;
290
 
                XT_NODE_ID(next_node) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8);
291
 
                if (XT_NODE_ID(next_node) >= XT_NODE_ID(tab->tab_ind_eof)) {
292
 
                        xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, tab->tab_name);
293
 
                        goto failed;
294
 
                }
295
 
                XT_NODE_ID(tab->tab_ind_free) = XT_NODE_ID(next_node);
 
286
                if (!xt_ind_read_bytes(ot, ind, wrote_pos, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block))
 
287
                        goto failed;
 
288
                XT_NODE_ID(tab->tab_ind_free) = (xtIndexNodeID) XT_GET_DISK_8(free_block.if_next_block_8);
296
289
                xt_unlock_mutex_ns(&tab->tab_ind_lock);
297
290
                *address = wrote_pos;
298
291
                TRACK_BLOCK_ALLOC(wrote_pos);
1573
1566
                if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
1574
1567
                        iref.ir_block->cp_del_count--;
1575
1568
        }
1576
 
 
1577
 
        if (item->i_pos.i_total_size + item_size - item->i_pos.i_item_size <= XT_INDEX_PAGE_DATA_SIZE) {
1578
 
                /* The new item is larger than the old, this can result
1579
 
                 * in overflow of the node!
1580
 
                 */
1581
 
                memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size],
1582
 
                        &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
1583
 
                        item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
1584
 
                memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset],
1585
 
                        item_buf, item_size);
1586
 
                if (ind->mi_lazy_delete) {
1587
 
                        if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
1588
 
                                iref.ir_block->cp_del_count++;
1589
 
                }
1590
 
                item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size;
1591
 
                XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size));
1592
 
                IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
 
1569
        memmove(&iref.ir_branch->tb_data[item->i_pos.i_item_offset + item_size],
 
1570
                &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
 
1571
                item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
 
1572
        memcpy(&iref.ir_branch->tb_data[item->i_pos.i_item_offset],
 
1573
                item_buf, item_size);
 
1574
        if (ind->mi_lazy_delete) {
 
1575
                if (idx_is_item_deleted(iref.ir_branch, &item->i_pos))
 
1576
                        iref.ir_block->cp_del_count++;
 
1577
        }
 
1578
        item->i_pos.i_total_size = item->i_pos.i_total_size + item_size - item->i_pos.i_item_size;
 
1579
        XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(item->i_pos.i_total_size));
 
1580
        IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
1593
1581
#ifdef IND_OPT_DATA_WRITTEN
1594
 
                iref.ir_block->cb_header = TRUE;
1595
 
                if (item->i_pos.i_item_offset < iref.ir_block->cb_min_pos)
1596
 
                        iref.ir_block->cb_min_pos = item->i_pos.i_item_offset;
1597
 
                iref.ir_block->cb_max_pos = item->i_pos.i_total_size;
1598
 
                ASSERT_NS(iref.ir_block->cb_min_pos <= iref.ir_block->cb_max_pos);
 
1582
        iref.ir_block->cb_header = TRUE;
 
1583
        if (item->i_pos.i_item_offset < iref.ir_block->cb_min_pos)
 
1584
                iref.ir_block->cb_min_pos = item->i_pos.i_item_offset;
 
1585
        iref.ir_block->cb_max_pos = item->i_pos.i_total_size;
 
1586
        ASSERT_NS(iref.ir_block->cb_min_pos <= iref.ir_block->cb_max_pos);
1599
1587
#endif
1600
 
                iref.ir_updated = TRUE;
 
1588
        iref.ir_updated = TRUE;
1601
1589
 
1602
1590
#ifdef DEBUG
 
1591
        if (ind->mi_lazy_delete)
1603
1592
                ASSERT_NS(item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE);
1604
1593
#endif
 
1594
        if (item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE)
1605
1595
                return xt_ind_release(ot, ind, XT_UNLOCK_W_UPDATE, &iref);
1606
 
        }
1607
1596
 
1608
1597
        /* The node has overflowed!! */
1609
1598
#ifdef IND_SKEW_SPLIT_ON_APPEND
1611
1600
#endif
1612
1601
        result.sr_item = item->i_pos;
1613
1602
 
1614
 
        memcpy(ot->ot_ind_wbuf.tb_data, iref.ir_branch->tb_data, item->i_pos.i_item_offset);    // First part of the buffer
1615
 
        memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset], item_buf, item_size);               // The new item
1616
 
        memcpy(&ot->ot_ind_wbuf.tb_data[item->i_pos.i_item_offset + item_size],
1617
 
                &iref.ir_branch->tb_data[item->i_pos.i_item_offset + item->i_pos.i_item_size],
1618
 
                item->i_pos.i_total_size - item->i_pos.i_item_offset - item->i_pos.i_item_size);
1619
 
        item->i_pos.i_total_size += item_size - item->i_pos.i_item_size;
1620
 
        item->i_pos.i_item_size = item_size;
1621
 
        XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_LEAF_SIZE(item->i_pos.i_total_size));
1622
 
        IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
1623
 
        ASSERT_NS(item->i_pos.i_total_size > XT_INDEX_PAGE_DATA_SIZE && item->i_pos.i_total_size <= XT_INDEX_PAGE_DATA_SIZE*2);
1624
 
 
1625
1603
        /* Adjust the stack (we want the parents of the delete node): */
1626
1604
        for (;;) {
1627
1605
                if (idx_pop(stack) == item)
1631
1609
        /* We assume that value can be overwritten (which is the case) */
1632
1610
        key_value.sv_flags = XT_SEARCH_WHOLE_KEY;
1633
1611
        key_value.sv_key = key_buf;
1634
 
        if (!idx_get_middle_branch_item(ot, ind, &ot->ot_ind_wbuf, &key_value, &result))
 
1612
        if (!idx_get_middle_branch_item(ot, ind, iref.ir_branch, &key_value, &result))
1635
1613
                goto failed_1;
1636
1614
 
1637
1615
        if (!idx_new_branch(ot, ind, &new_branch))
1639
1617
 
1640
1618
        /* Split the node: */
1641
1619
        new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size;
 
1620
        // TODO: Are 2 buffers now required?
1642
1621
        new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE];
1643
1622
        memmove(new_branch_ptr->tb_data, &iref.ir_branch->tb_data[result.sr_item.i_item_offset + result.sr_item.i_item_size], new_size);
1644
1623
 
1648
1627
                goto failed_2;
1649
1628
 
1650
1629
        /* Change the size of the old branch: */
1651
 
        XT_SET_DISK_2(ot->ot_ind_wbuf.tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset));
1652
 
        IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(ot->ot_ind_wbuf.tb_size_2));
1653
 
        memcpy(iref.ir_branch, &ot->ot_ind_wbuf, offsetof(XTIdxBranchDRec, tb_data) + result.sr_item.i_item_offset);
 
1630
        XT_SET_DISK_2(iref.ir_branch->tb_size_2, XT_MAKE_NODE_SIZE(result.sr_item.i_item_offset));
 
1631
        IDX_TRACE("%d-> %x\n", (int) XT_NODE_ID(current), (int) XT_GET_DISK_2(iref.ir_branch->tb_size_2));
1654
1632
#ifdef IND_OPT_DATA_WRITTEN
1655
1633
        iref.ir_block->cb_header = TRUE;
1656
1634
        if (result.sr_item.i_item_offset < iref.ir_block->cb_min_pos)
2424
2402
        if (!idx_new_branch(ot, ind, &new_branch))
2425
2403
                goto failed_1;
2426
2404
 
2427
 
        if (XT_NODE_ID(current) == XT_NODE_ID(new_branch)) {
2428
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
2429
 
                goto failed_1;
2430
 
        }
2431
 
 
2432
2405
        /* Copy and write the rest of the data to the new node: */
2433
2406
        new_size = result.sr_item.i_total_size - result.sr_item.i_item_offset - result.sr_item.i_item_size;
2434
2407
        new_branch_ptr = (XTIdxBranchDPtr) &ot->ot_ind_wbuf.tb_data[XT_INDEX_PAGE_DATA_SIZE];
3104
3077
#endif
3105
3078
        ASSERT_NS(iref.ir_xlock == 2);
3106
3079
        ASSERT_NS(iref.ir_updated == 2);
3107
 
        if (ind->mi_key_corrupted) {
3108
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3109
 
                return FAILED;
3110
 
        }
3111
3080
        return OK;
3112
3081
 
3113
3082
        failed:
3259
3228
        //idx_check_index(ot, ind, TRUE);
3260
3229
        //idx_check_on_key(ot);
3261
3230
#endif
3262
 
        if (ind->mi_key_corrupted) {
3263
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3264
 
                return FAILED;
3265
 
        }
3266
3231
        return OK;
3267
3232
 
3268
3233
        failed:
3353
3318
 
3354
3319
        if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) {
3355
3320
                XT_INDEX_UNLOCK(ind, ot);
3356
 
                if (ind->mi_key_corrupted) {
3357
 
                        xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3358
 
                        return FAILED;
3359
 
                }
3360
3321
                return OK;
3361
3322
        }
3362
3323
 
3464
3425
                ot->ot_curr_rec_id = 0;
3465
3426
                ot->ot_curr_row_id = 0;
3466
3427
                XT_INDEX_UNLOCK(ind, ot);
3467
 
                if (ind->mi_key_corrupted) {
3468
 
                        xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3469
 
                        return FAILED;
3470
 
                }
3471
3428
                return OK;
3472
3429
        }
3473
3430
 
3509
3466
        ot->ot_curr_row_id = result.sr_row_id;
3510
3467
        ot->ot_ind_state = result.sr_item;
3511
3468
 
3512
 
        if (ind->mi_key_corrupted) {
3513
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3514
 
                return FAILED;
3515
 
        }
3516
3469
        return OK;
3517
3470
 
3518
3471
        failed:
3579
3532
 
3580
3533
        if (!(XT_NODE_ID(current) = XT_NODE_ID(ind->mi_root))) {
3581
3534
                XT_INDEX_UNLOCK(ind, ot);
3582
 
                if (ind->mi_key_corrupted) {
3583
 
                        xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3584
 
                        return FAILED;
3585
 
                }
3586
3535
                return OK;
3587
3536
        }
3588
3537
 
3679
3628
        ot->ot_curr_row_id = 0;
3680
3629
 
3681
3630
        XT_INDEX_UNLOCK(ind, ot);
3682
 
        if (ind->mi_key_corrupted) {
3683
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3684
 
                return FAILED;
3685
 
        }
3686
3631
        return OK;
3687
3632
 
3688
3633
        unlock_check_on_key:
3711
3656
        ot->ot_curr_rec_id = result.sr_rec_id;
3712
3657
        ot->ot_curr_row_id = result.sr_row_id;
3713
3658
        ot->ot_ind_state = result.sr_item;
3714
 
        if (ind->mi_key_corrupted) {
3715
 
                xt_register_taberr(XT_REG_CONTEXT, XT_ERR_INDEX_CORRUPTED, ot->ot_table->tab_name);
3716
 
                return FAILED;
3717
 
        }
3718
3659
        return OK;
3719
3660
 
3720
3661
        failed:
4403
4344
#ifdef DUMP_INDEX
4404
4345
                        printf("%d ", (int) XT_NODE_ID(current));
4405
4346
#endif
4406
 
                        if (!xt_ind_read_bytes(ot, NULL, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) {
 
4347
                        if (!xt_ind_read_bytes(ot, *ind, current, sizeof(XTIndFreeBlockRec), (xtWord1 *) &free_block)) {
4407
4348
                                xt_log_and_clear_exception_ns();
4408
4349
                                break;
4409
4350
                        }
5203
5144
                                        if (!ilp_open_log(&il, log_id, FALSE, self))
5204
5145
                                                goto failed;
5205
5146
                                        if (il->il_tab_id && il->il_log_eof) {
5206
 
                                                char table_name[XT_IDENTIFIER_NAME_SIZE*3+3];
5207
 
 
5208
5147
                                                if (!il->il_open_table(&ot))
5209
5148
                                                        goto failed;
5210
5149
                                                if (ot) {
5211
 
                                                        xt_tab_make_table_name(ot->ot_table->tab_name, table_name, sizeof(table_name));
5212
 
                                                        xt_logf(XT_NT_INFO, "PBXT: Recovering index, table: %s, bytes to read: %llu\n", table_name, (u_llong) il->il_log_eof);
5213
 
                                                        if (!il->il_apply_log_write(ot)) {
5214
 
                                                                /* If recovery of an index fails, then it is corrupt! */
5215
 
                                                                if (ot->ot_thread->t_exception.e_xt_err != XT_ERR_NO_INDEX_CACHE)
5216
 
                                                                        goto failed;
5217
 
                                                                xt_tab_disable_index(ot->ot_table, XT_INDEX_CORRUPTED);
5218
 
                                                                xt_log_and_clear_exception_ns();
5219
 
                                                        }
5220
 
                                                        else {
5221
 
                                                                if (!il->il_apply_log_flush(ot))
5222
 
                                                                        goto failed;
5223
 
                                                        }
 
5150
                                                        if (!il->il_apply_log_write(ot))
 
5151
                                                                goto failed;
 
5152
                                                        if (!il->il_apply_log_flush(ot))
 
5153
                                                                goto failed;
5224
5154
                                                        ot->ot_thread = self;
5225
5155
                                                        il->il_close_table(ot);
5226
5156
                                                }
5234
5164
        return;
5235
5165
 
5236
5166
        failed:
 
5167
        /* TODO: Mark index as corrupted: */
5237
5168
        if (ot && il)
5238
5169
                il->il_close_table(ot);
5239
5170
        if (il)
5766
5697
                        /* Corrupt log?! */
5767
5698
                        if (il_buffer_len < req_size) {
5768
5699
                                xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
5769
 
                                return FAILED;
 
5700
                                xt_log_and_clear_exception_ns();
 
5701
                                return OK;
5770
5702
                        }
5771
5703
                        if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
5772
5704
                                return FAILED;
5975
5907
                                                /* Corrupt log?! */
5976
5908
                                                if (il_buffer_len < req_size) {
5977
5909
                                                        xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
5978
 
                                                        return FAILED;
 
5910
                                                        xt_log_and_clear_exception_ns();
 
5911
                                                        return OK;
5979
5912
                                                }
5980
5913
                                                if (!xt_pread_file(il_of, offset, il_buffer_len, il_buffer_len, il_buffer, NULL, &ot->ot_thread->st_statistics.st_ilog, ot->ot_thread))
5981
5914
                                                        return FAILED;
6064
5997
                                break;
6065
5998
                        default:
6066
5999
                                xt_register_ixterr(XT_REG_CONTEXT, XT_ERR_INDEX_LOG_CORRUPT, xt_file_path(il_of));
6067
 
                                return FAILED;
 
6000
                                xt_log_and_clear_exception_ns();
 
6001
                                return OK;
6068
6002
                }
6069
6003
#ifdef CHECK_IF_WRITE_WAS_OK
6070
6004
                if (node_id) {