* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* og_page.c
*
*
* IDENTIFICATION
* src/ogbox/og_page.c
*
* -------------------------------------------------------------------------
*/
#include "og_tbox_module.h"
#include "og_page.h"
#include "cm_file.h"
#include "og_miner.h"
#include "rcr_btree.h"
#include "knl_undo.h"
#include "knl_lob.h"
#include "pcr_heap.h"
#include "pcr_btree.h"
#include "temp_btree.h"
#define MAX_VALUE_LEN 256
#define REPAIR_MAX_KEY_NUM 16
knl_session_t *g_page_se = NULL;
knl_instance_t *g_page_instance = NULL;
typedef struct st_repair_key_item {
char name[OG_MAX_NAME_LEN];
uint32 index;
} repair_key_item_t;
typedef struct st_repair_key {
repair_key_item_t item[REPAIR_MAX_KEY_NUM];
uint32 page_size;
} repair_key_t;
typedef status_t(*repair_page_proc)(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
typedef enum en_repair_page_part {
REPAIR_PAGE_HEAD = 1,
REPAIR_PAGE_CTRL = 2,
REPAIR_PAGE_TAIL = 4
} repair_page_part_t;
typedef struct st_page_repair {
const char *name;
uint32 item_size;
uint32 item_offset;
repair_page_proc repair_proc;
struct st_page_repair *child_items;
uint32 child_num;
} page_repair_t;
typedef struct st_page_type_repair {
page_type_t type;
uint32 page_offset;
page_repair_t page_item;
} page_type_repair_t;
status_t repair_set_page_ctrl(repair_key_t *rkeys, page_head_t *head, text_t *name, text_t *value);
status_t repair_set_page_head(page_head_t *head, text_t *name, text_t *value);
status_t repair_set_page_tail(page_tail_t *tail, text_t *name, text_t *value);
static status_t repair_int64(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_uint64(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_uint32(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_uint16(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_uint8(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_knl_scn_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pagid_data_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_page_id_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_undo_page_id_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_rowid_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_btree_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_pcrb_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_undo_row_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_row_head_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_row_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_map_node_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_map_index_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_temp_btree_page_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset);
static status_t repair_bitof_btree_page_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset);
static status_t repair_bitof_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_pcr_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_bitof_heap_segment_t(repair_key_t *rkeys, text_t *value, uint32 curr_id,
char *page, uint32 offset);
static status_t repair_pdata_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_row_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_row_head_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_map_node_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_undo_row_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_btree_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
static status_t repair_pdata_btree_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset);
#define CHILDREN_NUM(parent) ((uint32)(sizeof(parent) / sizeof(page_repair_t)))
#define REPAIR_PAGE_TYPE(page, type, offset) \
{ (page), (uint32)(offset), { #type, 0, 0, NULL, g_##type##_items, CHILDREN_NUM(g_##type##_items) } }
#define REPAIR_ITEM_WITH_CHILD(obj, item, type) \
{ #item, (uint32)sizeof(type), (uint32)OFFSET_OF(obj, item), \
NULL, g_##type##_items, CHILDREN_NUM(g_##type##_items) }
#define REPAIR_ITEM_WITH_PEER(offset, obj, item, type) \
{ #item, (uint32)sizeof(type), (offset) + (uint32)OFFSET_OF(obj, item), \
NULL, g_##type##_items, CHILDREN_NUM(g_##type##_items) }
#define REPAIR_ITEM_NO_CHILD(obj, item, type) \
{ #item, (uint32)sizeof(type), (uint32)OFFSET_OF(obj, item), repair_##type, NULL, 0 }
#define REPAIR_BIT_ITEM(obj, item) { #item, 0, 0, repair_bitof_##obj, NULL, 0 }
#define REPAIR_PAGE_DATA_ITEM(obj, item) { #item, 0, 0, repair_pdata_##obj, NULL, 0 }
static page_repair_t g_xmap_t_items[] = {
REPAIR_ITEM_NO_CHILD(xmap_t, seg_id, uint16),
REPAIR_ITEM_NO_CHILD(xmap_t, slot, uint16),
};
static page_repair_t g_xid_t_items[] = {
REPAIR_ITEM_WITH_CHILD(xid_t, xmap, xmap_t),
REPAIR_ITEM_NO_CHILD(xid_t, xnum, uint32),
};
static page_repair_t g_undo_row_t_items[] = {
REPAIR_ITEM_NO_CHILD(undo_row_t, rowid, rowid_t),
REPAIR_BIT_ITEM(undo_row_t, seg_file),
REPAIR_BIT_ITEM(undo_row_t, seg_page),
REPAIR_BIT_ITEM(undo_row_t, user_id),
REPAIR_BIT_ITEM(undo_row_t, index_id),
REPAIR_ITEM_NO_CHILD(undo_row_t, prev_page, undo_page_id_t),
REPAIR_ITEM_NO_CHILD(undo_row_t, prev_slot, uint16),
REPAIR_ITEM_NO_CHILD(undo_row_t, data_size, uint16),
REPAIR_BIT_ITEM(undo_row_t, is_xfirst),
REPAIR_BIT_ITEM(undo_row_t, is_owscn),
REPAIR_BIT_ITEM(undo_row_t, is_cleaned),
REPAIR_BIT_ITEM(undo_row_t, type),
REPAIR_ITEM_NO_CHILD(undo_row_t, ssn, uint16),
REPAIR_ITEM_NO_CHILD(undo_row_t, scn, knl_scn_t),
REPAIR_ITEM_WITH_CHILD(undo_row_t, xid, xid_t),
};
static page_repair_t g_undo_page_t_items[] = {
REPAIR_ITEM_NO_CHILD(undo_page_t, ss_time, uint64),
REPAIR_ITEM_NO_CHILD(undo_page_t, prev, undo_page_id_t),
REPAIR_ITEM_NO_CHILD(undo_page_t, rows, uint16),
REPAIR_ITEM_NO_CHILD(undo_page_t, free_size, uint16),
REPAIR_ITEM_NO_CHILD(undo_page_t, free_begin, uint16),
REPAIR_ITEM_NO_CHILD(undo_page_t, begin_slot, uint16),
REPAIR_PAGE_DATA_ITEM(undo_row_t, page_rows),
};
static page_repair_t g_knl_tree_info_t_items[] = {
REPAIR_ITEM_NO_CHILD(knl_tree_info_t, root, pagid_data_t),
REPAIR_ITEM_NO_CHILD(knl_tree_info_t, level, uint16),
};
static page_repair_t g_page_list_t_items[] = {
REPAIR_ITEM_NO_CHILD(page_list_t, count, uint32),
REPAIR_ITEM_NO_CHILD(page_list_t, first, page_id_t),
REPAIR_ITEM_NO_CHILD(page_list_t, last, page_id_t),
};
static page_repair_t g_heap_segment_t_items[] = {
REPAIR_ITEM_WITH_CHILD(heap_segment_t, tree_info, knl_tree_info_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, seg_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, oid, uint32),
REPAIR_ITEM_NO_CHILD(heap_segment_t, uid, uint16),
REPAIR_ITEM_NO_CHILD(heap_segment_t, space_id, uint16),
REPAIR_ITEM_NO_CHILD(heap_segment_t, serial, int64),
REPAIR_ITEM_NO_CHILD(heap_segment_t, ufp_count, uint64),
REPAIR_ITEM_WITH_CHILD(heap_segment_t, extents, page_list_t),
REPAIR_ITEM_WITH_CHILD(heap_segment_t, free_extents, page_list_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, free_ufp, page_id_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, data_first, page_id_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, data_last, page_id_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, initrans, uint8),
REPAIR_ITEM_NO_CHILD(heap_segment_t, cr_mode, uint8),
REPAIR_ITEM_NO_CHILD(heap_segment_t, list_range, uint16),
REPAIR_ITEM_NO_CHILD(heap_segment_t, map_count, uint32),
REPAIR_ITEM_NO_CHILD(heap_segment_t, curr_map, page_id_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, cmp_hwm, page_id_t),
REPAIR_ITEM_NO_CHILD(heap_segment_t, page_count, uint32),
REPAIR_ITEM_NO_CHILD(heap_segment_t, free_page_count, uint32),
REPAIR_BIT_ITEM(heap_segment_t, last_ext_size),
REPAIR_BIT_ITEM(heap_segment_t, compress)
};
static page_repair_t g_map_list_t_items[] = {
REPAIR_ITEM_NO_CHILD(map_list_t, count, uint16),
REPAIR_ITEM_NO_CHILD(map_list_t, first, uint16),
};
static page_repair_t g_map_node_t_items[] = {
REPAIR_BIT_ITEM(map_node_t, file),
REPAIR_BIT_ITEM(map_node_t, page),
REPAIR_BIT_ITEM(map_node_t, prev),
REPAIR_BIT_ITEM(map_node_t, next),
};
static page_repair_t g_map_index_t_items[] = {
REPAIR_BIT_ITEM(map_index_t, file),
REPAIR_BIT_ITEM(map_index_t, page),
REPAIR_BIT_ITEM(map_index_t, slot),
REPAIR_BIT_ITEM(map_index_t, list_id),
};
static page_repair_t g_map_page_t_items[] = {
REPAIR_ITEM_WITH_CHILD(map_page_t, map, map_index_t),
REPAIR_ITEM_WITH_CHILD(map_page_t, lists, map_list_t),
REPAIR_ITEM_NO_CHILD(map_page_t, hwm, uint16),
REPAIR_PAGE_DATA_ITEM(map_node_t, nodes),
};
static page_repair_t g_itl_t_items[] = {
REPAIR_ITEM_NO_CHILD(itl_t, scn, knl_scn_t),
REPAIR_ITEM_WITH_CHILD(itl_t, xid, xid_t),
REPAIR_ITEM_NO_CHILD(itl_t, fsc, uint16),
REPAIR_BIT_ITEM(itl_t, is_active),
REPAIR_BIT_ITEM(itl_t, is_owscn),
REPAIR_BIT_ITEM(itl_t, is_copied),
};
static page_repair_t g_pcr_itl_t_items[] = {
REPAIR_ITEM_NO_CHILD(pcr_itl_t, scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(pcr_itl_t, ssn, uint32),
REPAIR_ITEM_NO_CHILD(pcr_itl_t, fsc, uint16),
REPAIR_ITEM_WITH_CHILD(pcr_itl_t, xid, xid_t),
REPAIR_ITEM_NO_CHILD(pcr_itl_t, undo_page, undo_page_id_t),
REPAIR_ITEM_NO_CHILD(pcr_itl_t, undo_slot, uint16),
REPAIR_BIT_ITEM(pcr_itl_t, is_active),
REPAIR_BIT_ITEM(pcr_itl_t, is_owscn),
REPAIR_BIT_ITEM(pcr_itl_t, is_copied),
REPAIR_BIT_ITEM(pcr_itl_t, is_hist),
REPAIR_BIT_ITEM(pcr_itl_t, is_fast),
};
static page_repair_t g_pcrb_key_t_items[] = {
REPAIR_ITEM_NO_CHILD(pcrb_key_t, rowid, rowid_t),
REPAIR_BIT_ITEM(pcrb_key_t, size),
REPAIR_BIT_ITEM(pcrb_key_t, is_deleted),
REPAIR_BIT_ITEM(pcrb_key_t, is_infinite),
REPAIR_BIT_ITEM(pcrb_key_t, is_cleaned),
REPAIR_ITEM_NO_CHILD(pcrb_key_t, itl_id, uint8),
REPAIR_ITEM_NO_CHILD(pcrb_key_t, bitmap, uint16),
};
static page_repair_t g_row_dir_t_items[] = {
REPAIR_ITEM_NO_CHILD(row_dir_t, offset, uint16),
REPAIR_BIT_ITEM(row_dir_t, is_owscn),
REPAIR_BIT_ITEM(row_dir_t, undo_slot),
REPAIR_BIT_ITEM(row_dir_t, is_free),
REPAIR_BIT_ITEM(row_dir_t, next_slot),
REPAIR_ITEM_NO_CHILD(row_dir_t, undo_page, undo_page_id_t),
REPAIR_ITEM_NO_CHILD(row_dir_t, scn, knl_scn_t),
};
static page_repair_t g_row_head_t_items[] = {
REPAIR_ITEM_NO_CHILD(row_head_t, size, uint16),
REPAIR_BIT_ITEM(row_head_t, column_count),
REPAIR_BIT_ITEM(row_head_t, is_deleted),
REPAIR_BIT_ITEM(row_head_t, is_link),
REPAIR_BIT_ITEM(row_head_t, is_migr),
REPAIR_BIT_ITEM(row_head_t, self_chg),
REPAIR_BIT_ITEM(row_head_t, is_changed),
REPAIR_BIT_ITEM(row_head_t, is_csf),
REPAIR_ITEM_NO_CHILD(row_head_t, sprs_count, uint16),
REPAIR_ITEM_NO_CHILD(row_head_t, sprs_itl_id, uint8),
REPAIR_ITEM_NO_CHILD(row_head_t, sprs_bitmap, uint8),
REPAIR_ITEM_NO_CHILD(row_head_t, itl_id, uint8),
REPAIR_ITEM_NO_CHILD(row_head_t, bitmap, uint8),
};
static page_repair_t g_heap_page_t_items[] = {
REPAIR_ITEM_WITH_CHILD(heap_page_t, map, map_index_t),
REPAIR_ITEM_NO_CHILD(heap_page_t, seg_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(heap_page_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(heap_page_t, oid, uint32),
REPAIR_ITEM_NO_CHILD(heap_page_t, uid, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, first_free_dir, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, next, pagid_data_t),
REPAIR_ITEM_NO_CHILD(heap_page_t, free_begin, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, free_end, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, free_size, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, rows, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, dirs, uint16),
REPAIR_ITEM_NO_CHILD(heap_page_t, itls, uint8),
REPAIR_ITEM_NO_CHILD(heap_page_t, scn, knl_scn_t),
REPAIR_PAGE_DATA_ITEM(itl_t, page_itls),
REPAIR_PAGE_DATA_ITEM(row_dir_t, page_dirs),
REPAIR_PAGE_DATA_ITEM(row_head_t, page_rows),
};
static page_repair_t g_space_head_t_items[] = {
REPAIR_ITEM_NO_CHILD(space_head_t, segment_count, uint32),
REPAIR_ITEM_WITH_CHILD(space_head_t, free_extents, page_list_t),
REPAIR_ITEM_NO_CHILD(space_head_t, datafile_count, uint32),
REPAIR_ITEM_NO_CHILD(space_head_t, hwms, uint32),
REPAIR_ITEM_WITH_PEER(sizeof(space_head_t), spc_punch_head_t, punching_exts, page_list_t),
REPAIR_ITEM_WITH_PEER(sizeof(space_head_t), spc_punch_head_t, punched_exts, page_list_t),
};
static page_repair_t g_undo_page_list_t_items[] = {
REPAIR_ITEM_NO_CHILD(undo_page_list_t, count, uint32),
REPAIR_ITEM_NO_CHILD(undo_page_list_t, first, undo_page_id_t),
REPAIR_ITEM_NO_CHILD(undo_page_list_t, last, undo_page_id_t),
};
static page_repair_t g_undo_segment_t_items[] = {
REPAIR_ITEM_WITH_CHILD(undo_segment_t, page_list, undo_page_list_t),
REPAIR_ITEM_NO_CHILD(undo_segment_t, txn_page_count, uint32),
REPAIR_ITEM_NO_CHILD(undo_segment_t, txn_page, undo_page_id_t),
};
static page_repair_t g_txn_t_items[] = {
REPAIR_ITEM_NO_CHILD(txn_t, scn, knl_scn_t),
REPAIR_ITEM_WITH_CHILD(txn_t, undo_pages, undo_page_list_t),
REPAIR_ITEM_NO_CHILD(txn_t, xnum, uint32),
REPAIR_ITEM_NO_CHILD(txn_t, status, uint8),
};
static page_repair_t g_df_map_group_t_items[] = {
REPAIR_ITEM_NO_CHILD(df_map_group_t, first_map, page_id_t),
REPAIR_ITEM_NO_CHILD(df_map_group_t, page_count, uint8),
};
static page_repair_t g_txn_page_t_items[] = {
REPAIR_ITEM_WITH_CHILD(txn_page_t, items, txn_t),
};
static page_repair_t g_btree_segment_t_items[] = {
REPAIR_ITEM_WITH_CHILD(btree_segment_t, tree_info, knl_tree_info_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, seg_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, table_id, uint32),
REPAIR_ITEM_NO_CHILD(btree_segment_t, uid, uint16),
REPAIR_ITEM_NO_CHILD(btree_segment_t, index_id, uint16),
REPAIR_ITEM_NO_CHILD(btree_segment_t, space_id, uint16),
REPAIR_ITEM_NO_CHILD(btree_segment_t, initrans, uint8),
REPAIR_ITEM_NO_CHILD(btree_segment_t, cr_mode, uint8),
REPAIR_ITEM_WITH_CHILD(btree_segment_t, extents, page_list_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, ufp_count, uint32),
REPAIR_ITEM_NO_CHILD(btree_segment_t, ufp_first, page_id_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, ufp_extent, page_id_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, del_scn, knl_scn_t),
REPAIR_ITEM_WITH_CHILD(btree_segment_t, del_pages, page_list_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, pctfree, uint32),
REPAIR_ITEM_NO_CHILD(btree_segment_t, page_count, uint32),
REPAIR_ITEM_NO_CHILD(btree_segment_t, garbage_size, uint64),
REPAIR_ITEM_NO_CHILD(btree_segment_t, first_recycle_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, ow_del_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, ow_recycle_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, last_recycle_scn, knl_scn_t),
REPAIR_ITEM_WITH_CHILD(btree_segment_t, recycled_pages, page_list_t),
REPAIR_ITEM_NO_CHILD(btree_segment_t, recycle_ver_scn, knl_scn_t),
};
static page_repair_t g_btree_dir_t_items[] = {
REPAIR_ITEM_NO_CHILD(btree_dir_t, offset, uint16),
REPAIR_ITEM_NO_CHILD(btree_dir_t, itl_id, uint8),
};
static page_repair_t g_btree_key_t_items[] = {
REPAIR_ITEM_NO_CHILD(btree_key_t, scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(btree_key_t, child, page_id_t),
REPAIR_ITEM_NO_CHILD(btree_key_t, rowid, rowid_t),
REPAIR_BIT_ITEM(btree_key_t, size),
REPAIR_ITEM_NO_CHILD(btree_key_t, undo_page, undo_page_id_t),
REPAIR_BIT_ITEM(btree_key_t, undo_slot),
REPAIR_BIT_ITEM(btree_key_t, is_deleted),
REPAIR_BIT_ITEM(btree_key_t, is_infinite),
REPAIR_BIT_ITEM(btree_key_t, is_owscn),
REPAIR_BIT_ITEM(btree_key_t, is_cleaned),
REPAIR_ITEM_NO_CHILD(btree_key_t, bitmap, uint16),
};
static page_repair_t g_btree_page_t_items[] = {
REPAIR_ITEM_NO_CHILD(btree_page_t, seg_scn, knl_scn_t),
REPAIR_BIT_ITEM(btree_page_t, is_recycled),
REPAIR_ITEM_NO_CHILD(btree_page_t, keys, uint16),
REPAIR_ITEM_NO_CHILD(btree_page_t, prev, pagid_data_t),
REPAIR_ITEM_NO_CHILD(btree_page_t, level, uint8),
REPAIR_ITEM_NO_CHILD(btree_page_t, itls, uint8),
REPAIR_ITEM_NO_CHILD(btree_page_t, next, pagid_data_t),
REPAIR_ITEM_NO_CHILD(btree_page_t, free_begin, uint16),
REPAIR_ITEM_NO_CHILD(btree_page_t, free_end, uint16),
REPAIR_ITEM_NO_CHILD(btree_page_t, free_size, uint16),
REPAIR_ITEM_NO_CHILD(btree_page_t, scn, knl_scn_t),
REPAIR_PAGE_DATA_ITEM(btree_dir_t, page_dirs),
REPAIR_PAGE_DATA_ITEM(btree_key_t, page_keys),
};
static page_repair_t g_lob_segment_t_items[] = {
REPAIR_ITEM_NO_CHILD(lob_segment_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(lob_segment_t, seg_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(lob_segment_t, table_id, uint32),
REPAIR_ITEM_NO_CHILD(lob_segment_t, uid, uint16),
REPAIR_ITEM_NO_CHILD(lob_segment_t, space_id, uint16),
REPAIR_ITEM_NO_CHILD(lob_segment_t, column_id, uint16),
REPAIR_ITEM_WITH_CHILD(lob_segment_t, extents, page_list_t),
REPAIR_ITEM_WITH_CHILD(lob_segment_t, free_list, page_list_t),
REPAIR_ITEM_NO_CHILD(lob_segment_t, ufp_count, uint32),
REPAIR_ITEM_NO_CHILD(lob_segment_t, ufp_first, page_id_t),
REPAIR_ITEM_NO_CHILD(lob_segment_t, ufp_extent, page_id_t),
REPAIR_ITEM_NO_CHILD(lob_segment_t, shrink_scn, knl_scn_t),
};
static page_repair_t g_lob_chunk_t_items[] = {
REPAIR_ITEM_WITH_CHILD(lob_chunk_t, ins_xid, xid_t),
REPAIR_ITEM_WITH_CHILD(lob_chunk_t, del_xid, xid_t),
REPAIR_ITEM_NO_CHILD(lob_chunk_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(lob_chunk_t, size, uint32),
REPAIR_ITEM_NO_CHILD(lob_chunk_t, next, page_id_t),
REPAIR_ITEM_NO_CHILD(lob_chunk_t, free_next, page_id_t),
REPAIR_ITEM_NO_CHILD(lob_chunk_t, is_recycled, uint32),
};
static page_repair_t g_lob_data_page_t_items[] = {
REPAIR_ITEM_WITH_CHILD(lob_data_page_t, chunk, lob_chunk_t),
};
static page_repair_t g_temp_heap_page_t_items[] = {
REPAIR_ITEM_WITH_CHILD(temp_heap_page_t, map, map_index_t),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, org_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, seg_scn, knl_scn_t),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, oid, uint32),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, uid, uint16),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, first_free_dir, uint16),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, next, pagid_data_t),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, free_begin, uint32),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, free_end, uint32),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, free_size, uint32),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, rows, uint16),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, dirs, uint16),
REPAIR_ITEM_NO_CHILD(temp_heap_page_t, itls, uint8),
};
static page_repair_t g_temp_btree_page_t_items[] = {
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, seg_scn, knl_scn_t),
REPAIR_BIT_ITEM(temp_btree_page_t, is_recycled),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, keys, uint16),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, prev, pagid_data_t),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, level, uint8),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, itls, uint8),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, next, pagid_data_t),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, free_begin, uint32),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, free_end, uint32),
REPAIR_ITEM_NO_CHILD(temp_btree_page_t, free_size, uint32),
};
static page_repair_t g_df_map_head_t_items[] = {
REPAIR_ITEM_NO_CHILD(df_map_head_t, bit_unit, uint16),
REPAIR_ITEM_NO_CHILD(df_map_head_t, group_count, uint16),
REPAIR_ITEM_WITH_CHILD(df_map_head_t, groups, df_map_group_t),
};
static page_repair_t g_df_map_page_t_items[] = {
REPAIR_ITEM_NO_CHILD(df_map_page_t, first_page, page_id_t),
REPAIR_ITEM_NO_CHILD(df_map_page_t, free_begin, uint16),
REPAIR_ITEM_NO_CHILD(df_map_page_t, free_bits, uint16),
REPAIR_ITEM_NO_CHILD(df_map_page_t, bitmap, uint8),
};
static page_type_repair_t g_page_ctrl_items[] = {
REPAIR_PAGE_TYPE(PAGE_TYPE_SPACE_HEAD, space_head_t, PAGE_HEAD_SIZE),
REPAIR_PAGE_TYPE(PAGE_TYPE_HEAP_HEAD, heap_segment_t, PAGE_HEAD_SIZE),
REPAIR_PAGE_TYPE(PAGE_TYPE_HEAP_MAP, map_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_HEAP_DATA, heap_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_UNDO_HEAD, undo_segment_t, PAGE_HEAD_SIZE),
REPAIR_PAGE_TYPE(PAGE_TYPE_TXN, txn_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_UNDO, undo_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_BTREE_HEAD, btree_segment_t, CM_ALIGN8(sizeof(btree_page_t))),
REPAIR_PAGE_TYPE(PAGE_TYPE_BTREE_NODE, btree_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_LOB_HEAD, lob_segment_t, PAGE_HEAD_SIZE),
REPAIR_PAGE_TYPE(PAGE_TYPE_LOB_DATA, lob_data_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_TEMP_HEAP, temp_heap_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_TEMP_INDEX, temp_btree_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_PCRH_DATA, heap_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_PCRB_NODE, btree_page_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_DF_MAP_HEAD, df_map_head_t, 0),
REPAIR_PAGE_TYPE(PAGE_TYPE_DF_MAP_DATA, df_map_page_t, 0),
};
#define REPAIR_PAGE_TYPE_NUM (sizeof(g_page_ctrl_items) / sizeof(page_type_repair_t))
page_repair_t *repair_get_child_item(page_repair_t *parent, const char *child_name)
{
for (uint32 i = 0; i < parent->child_num; i++) {
if (cm_str_equal(child_name, parent->child_items[i].name)) {
return &parent->child_items[i];
}
}
return NULL;
}
static status_t repair_common_entry(repair_key_t *rkeys, text_t *value, char *page, uint32 curr_id, uint32 item_offset,
page_repair_t *curr_item)
{
uint32 child_offset;
page_repair_t *child = NULL;
if (rkeys->item[curr_id].name[0] == '\0') {
printf("expect more child item after \'%s\'\n", rkeys->item[curr_id - 1].name);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id].name);
return OG_ERROR;
}
if (curr_item->child_items == NULL) {
if (curr_item->repair_proc == NULL) {
printf("no repair_proc implement for item \'%s\'\n", rkeys->item[curr_id].name);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id].name);
return OG_ERROR;
}
if (item_offset + curr_item->item_size > rkeys->page_size) {
printf("invalid offset %u for item \'%s\', page size is %u\n",
item_offset, rkeys->item[curr_id].name, rkeys->page_size);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id].name);
return OG_ERROR;
}
return curr_item->repair_proc(rkeys, value, curr_id, page, item_offset);
}
child = repair_get_child_item(curr_item, rkeys->item[curr_id + 1].name);
if (child == NULL) {
printf("child item \'%s\' is not found in object \'%s\'\n",
rkeys->item[curr_id + 1].name, rkeys->item[curr_id].name);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id + 1].name);
return OG_ERROR;
}
child_offset = item_offset + child->item_offset;
if (rkeys->item[curr_id + 1].index != OG_INVALID_ID32) {
child_offset += child->item_size * rkeys->item[curr_id + 1].index;
}
return repair_common_entry(rkeys, value, page, curr_id + 1, child_offset, child);
}
static status_t repair_expect_end(repair_key_t *rkeys, uint32 curr_id)
{
if (rkeys->item[curr_id + 1].name[0] != '\0') {
printf("expect end but found child item \'%s\' after \'%s\'\n",
rkeys->item[curr_id + 1].name, rkeys->item[curr_id].name);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id + 1].name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_uint64(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *child = page + offset;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
return cm_text2uint64_ex(value, (uint64 *)child);
}
static status_t repair_int64(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *child = page + offset;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
return cm_text2bigint(value, (int64 *)child);
}
static status_t repair_uint32(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *child = page + offset;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
return cm_text2uint32(value, (uint32 *)child);
}
static status_t repair_uint16(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *child = page + offset;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
return cm_text2uint16(value, (uint16 *)child);
}
static status_t repair_uint8(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
uint8 *child = (uint8 *)(page + offset);
uint16 u16_value;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &u16_value) != OG_SUCCESS) {
return OG_ERROR;
}
*child = (uint8)u16_value;
return OG_SUCCESS;
}
static status_t repair_knl_scn_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
return repair_uint64(keys, value, curr_id, page, offset);
}
static status_t repair_undo_page_id_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
undo_page_id_t *undo_page_id = (undo_page_id_t *)(page + offset);
text_t file_str;
text_t page_str;
uint32 uint32_value;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
cm_split_text(value, '-', '\0', &file_str, &page_str);
cm_trim_text(&file_str);
cm_trim_text(&page_str);
if (cm_text2uint32(&file_str, &uint32_value) != OG_SUCCESS) {
return OG_ERROR;
}
undo_page_id->file = uint32_value;
if (cm_text2uint32(&page_str, &uint32_value) != OG_SUCCESS) {
return OG_ERROR;
}
undo_page_id->page = uint32_value;
return OG_SUCCESS;
}
static status_t repair_pagid_data_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
pagid_data_t *page_data = (pagid_data_t *)(page + offset);
text_t file_str;
text_t page_str;
page_id_t page_id;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
cm_split_text(value, '-', '\0', &file_str, &page_str);
cm_trim_text(&file_str);
cm_trim_text(&page_str);
if (cm_text2uint16(&file_str, &page_id.file) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint32(&page_str, &page_id.page) != OG_SUCCESS) {
return OG_ERROR;
}
TO_PAGID_DATA(page_id, page_data);
return OG_SUCCESS;
}
static status_t repair_page_id_t(repair_key_t *keys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
page_id_t *page_id = (page_id_t *)(page + offset);
text_t file_str;
text_t page_str;
uint16 uint16_value;
uint32 uint32_value;
if (repair_expect_end(keys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
cm_split_text(value, '-', '\0', &file_str, &page_str);
cm_trim_text(&file_str);
cm_trim_text(&page_str);
if (cm_text2uint16(&file_str, &uint16_value) != OG_SUCCESS) {
return OG_ERROR;
}
page_id->file = uint16_value;
if (cm_text2uint32(&page_str, &uint32_value) != OG_SUCCESS) {
return OG_ERROR;
}
page_id->page = uint32_value;
return OG_SUCCESS;
}
static status_t repair_bitof_row_head_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
row_head_t *heap_row = (row_head_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of row_head_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "column_count")) {
heap_row->column_count = uint16_value;
} else if (cm_str_equal(name, "is_deleted")) {
heap_row->is_deleted = uint16_value;
} else if (cm_str_equal(name, "is_link")) {
heap_row->is_link = uint16_value;
} else if (cm_str_equal(name, "is_migr")) {
heap_row->is_migr = uint16_value;
} else if (cm_str_equal(name, "self_chg")) {
heap_row->self_chg = uint16_value;
} else if (cm_str_equal(name, "is_changed")) {
heap_row->is_changed = uint16_value;
} else if (cm_str_equal(name, "is_csf")) {
heap_row->is_csf = uint16_value;
} else {
printf("bit value \'%s\' is not found in row_head_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_row_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
row_dir_t *heap_dir = (row_dir_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of row_dir_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "is_owscn")) {
heap_dir->is_owscn = uint16_value;
} else if (cm_str_equal(name, "undo_slot")) {
heap_dir->undo_slot = uint16_value;
} else if (cm_str_equal(name, "is_free")) {
heap_dir->is_free = uint16_value;
} else if (cm_str_equal(name, "next_slot")) {
heap_dir->next_slot = uint16_value;
} else {
printf("bit value \'%s\' is not found in row_dir_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_undo_row_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset)
{
char *name = rkeys->item[curr_id].name;
undo_row_t *undo_row = (undo_row_t *)(page + offset);
uint64 uint64_value;
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of undo_row_t\n", value->str, name);
return OG_ERROR;
}
uint16_value = (uint16)uint64_value;
if (cm_str_equal(name, "seg_file")) {
undo_row->seg_file = uint64_value;
} else if (cm_str_equal(name, "seg_page")) {
undo_row->seg_page = uint64_value;
} else if (cm_str_equal(name, "user_id")) {
undo_row->user_id = uint64_value;
} else if (cm_str_equal(name, "index_id")) {
undo_row->index_id = uint64_value;
} else if (cm_str_equal(name, "is_xfirst")) {
undo_row->is_xfirst = uint16_value;
} else if (cm_str_equal(name, "is_owscn")) {
undo_row->is_owscn = uint16_value;
} else if (cm_str_equal(name, "is_cleaned")) {
undo_row->is_cleaned = uint16_value;
} else if (cm_str_equal(name, "type")) {
undo_row->type = uint16_value;
} else {
printf("bit value \'%s\' is not found in undo_row_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_temp_btree_page_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset)
{
char *name = rkeys->item[curr_id].name;
temp_btree_page_t *temp_btree_page = (temp_btree_page_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of temp_btree_page_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "is_recycled")) {
temp_btree_page->is_recycled = uint16_value;
} else {
printf("bit value \'%s\' is not found in temp_btree_page_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_btree_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
btree_key_t *key = (btree_key_t *)(page + offset);
uint64 uint64_value;
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of btree_key_t\n", value->str, name);
return OG_ERROR;
}
uint16_value = (uint16)uint64_value;
if (cm_str_equal(name, "size")) {
key->size = uint64_value;
} else if (cm_str_equal(name, "undo_slot")) {
key->undo_slot = uint16_value;
} else if (cm_str_equal(name, "is_deleted")) {
key->is_deleted = uint16_value;
} else if (cm_str_equal(name, "is_infinite")) {
key->is_infinite = uint16_value;
} else if (cm_str_equal(name, "is_owscn")) {
key->is_owscn = uint16_value;
} else if (cm_str_equal(name, "is_cleaned")) {
key->is_cleaned = uint16_value;
} else {
printf("bit value \'%s\' is not found in btree_key_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_btree_page_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset)
{
char *name = rkeys->item[curr_id].name;
btree_page_t *btree_page = (btree_page_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of btree_page_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "is_recycled")) {
btree_page->is_recycled = uint16_value;
} else {
printf("bit value \'%s\' is not found in btree_page_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
itl_t *heap_itl = (itl_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of itl_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "is_active")) {
heap_itl->is_active = uint16_value;
} else if (cm_str_equal(name, "is_owscn")) {
heap_itl->is_owscn = uint16_value;
} else if (cm_str_equal(name, "is_copied")) {
heap_itl->is_copied = uint16_value;
} else {
printf("bit value \'%s\' is not found in itl_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_pcrb_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
pcrb_key_t *pcrb_key = (pcrb_key_t *)(page + offset);
uint64 uint64_value;
uint8 uint8_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of pcrb_key_t\n", value->str, name);
return OG_ERROR;
}
uint8_value = (uint8)uint64_value;
if (cm_str_equal(name, "size")) {
pcrb_key->size = uint64_value;
} else if (cm_str_equal(name, "is_deleted")) {
pcrb_key->is_deleted = uint8_value;
} else if (cm_str_equal(name, "is_infinite")) {
pcrb_key->is_infinite = uint8_value;
} else if (cm_str_equal(name, "is_cleaned")) {
pcrb_key->is_cleaned = uint8_value;
} else {
printf("bit value \'%s\' is not found in pcrb_key_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_pcr_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
pcr_itl_t *pcr_itl = (pcr_itl_t *)(page + offset);
uint16 uint16_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint16(value, &uint16_value) != OG_SUCCESS) {
printf("\'%s\' cannot convert to uint16 when repair \'%s\' of pcr_itl_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "is_active")) {
pcr_itl->is_active = uint16_value;
} else if (cm_str_equal(name, "is_owscn")) {
pcr_itl->is_owscn = uint16_value;
} else if (cm_str_equal(name, "is_copied")) {
pcr_itl->is_copied = uint16_value;
} else if (cm_str_equal(name, "is_hist")) {
pcr_itl->is_hist = uint16_value;
} else if (cm_str_equal(name, "is_fast")) {
pcr_itl->is_fast = uint16_value;
} else {
printf("bit value \'%s\' is not found in pcr_itl_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_map_node_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
map_node_t *map_node = (map_node_t *)(page + offset);
uint64 uint64_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of map_node_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "file")) {
map_node->file = uint64_value;
} else if (cm_str_equal(name, "page")) {
map_node->page = uint64_value;
} else if (cm_str_equal(name, "prev")) {
map_node->prev = uint64_value;
} else if (cm_str_equal(name, "next")) {
map_node->next = uint64_value;
} else {
printf("bit value \'%s\' is not found in map_node_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_map_index_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
map_index_t *map_index = (map_index_t *)(page + offset);
uint64 uint64_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of map_index_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "file")) {
map_index->file = uint64_value;
} else if (cm_str_equal(name, "page")) {
map_index->page = uint64_value;
} else if (cm_str_equal(name, "slot")) {
map_index->slot = uint64_value;
} else if (cm_str_equal(name, "list_id")) {
map_index->list_id = uint64_value;
} else {
printf("bit value \'%s\' is not found in map_index_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_bitof_heap_segment_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page,
uint32 offset)
{
char *name = rkeys->item[curr_id].name;
heap_segment_t *segment = (heap_segment_t *)(page + offset);
uint32 uint32_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint32_ex(value, &uint32_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint32 when repair \'%s\' of heap_segment_t\n", value->str, name);
return OG_ERROR;
}
uint8 uint8_value = (uint8)uint32_value;
if (cm_str_equal(name, "last_ext_size")) {
segment->last_ext_size = uint8_value;
} else if (cm_str_equal(name, "compress")) {
segment->compress = (uint8)uint32_value;
} else {
printf("bit value \'%s\' is not found in heap_segment_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_rowid_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
char *name = rkeys->item[curr_id].name;
rowid_t *child = (rowid_t *)(page + offset);
uint64 uint64_value;
if (repair_expect_end(rkeys, curr_id) != OG_SUCCESS) {
return OG_ERROR;
}
if (cm_text2uint64_ex(value, &uint64_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint64 when repair \'%s\' of rowid_t\n", value->str, name);
return OG_ERROR;
}
if (cm_str_equal(name, "value")) {
child->value = uint64_value;
} else if (cm_str_equal(name, "file")) {
child->file = uint64_value;
} else if (cm_str_equal(name, "page")) {
child->page = uint64_value;
} else if (cm_str_equal(name, "slot")) {
child->slot = uint64_value;
} else if (cm_str_equal(name, "vmid")) {
child->vmid = uint64_value;
} else if (cm_str_equal(name, "vm_slot")) {
child->vm_slot = uint64_value;
} else if (cm_str_equal(name, "vm_tag")) {
child->vm_tag = uint64_value;
} else {
printf("bit value \'%s\' is not found in rowid_t\n", name);
return OG_ERROR;
}
return OG_SUCCESS;
}
static status_t repair_item_of_object(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *obj_ptr,
page_repair_t *object, uint32 items_num)
{
uint32 item_offset;
for (uint32 id = 0; id < items_num; id++) {
if (cm_str_equal(rkeys->item[curr_id + 1].name, object[id].name)) {
item_offset = object[id].item_offset;
return repair_common_entry(rkeys, value, obj_ptr, curr_id + 1, item_offset, &object[id]);
}
}
printf("expect valid child item after \'%s\'\n", rkeys->item[curr_id].name);
OG_THROW_ERROR(ERR_INVALID_PARAMETER, rkeys->item[curr_id + 1].name);
return OG_ERROR;
}
static status_t repair_pdata_btree_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
btree_page_t *btree_page = (btree_page_t *)(page + offset);
uint32 index = rkeys->item[curr_id].index;
if (index >= btree_page->keys) {
printf("index is large than max key number %u\n", btree_page->keys);
return OG_ERROR;
}
if (btree_page->head.type == PAGE_TYPE_BTREE_NODE) {
btree_dir_t *btree_dir = BTREE_GET_DIR(btree_page, index);
uint32 items_num = CHILDREN_NUM(g_btree_dir_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)btree_dir, g_btree_dir_t_items, items_num);
} else {
pcrb_dir_t *pcrb_dir = pcrb_get_dir(btree_page, (uint16)index);
uint16 u16_value;
if (cm_text2uint16(value, &u16_value)) {
return OG_ERROR;
}
*pcrb_dir = (pcrb_dir_t)u16_value;
return OG_SUCCESS;
}
}
static status_t repair_pdata_btree_key_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
btree_page_t *btree_page = (btree_page_t *)(page + offset);
uint32 index = rkeys->item[curr_id].index;
if (index >= btree_page->keys) {
printf("index is large than max key number %u\n", btree_page->keys);
return OG_ERROR;
}
if (btree_page->head.type == PAGE_TYPE_BTREE_NODE) {
btree_dir_t *btree_dir = BTREE_GET_DIR(btree_page, index);
btree_key_t *key = BTREE_GET_KEY(btree_page, btree_dir);
uint32 items_num = CHILDREN_NUM(g_btree_key_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)key, g_btree_key_t_items, items_num);
} else {
pcrb_dir_t *pcrb_dir = pcrb_get_dir(btree_page, (uint16)index);
pcrb_key_t *key = PCRB_GET_KEY(btree_page, pcrb_dir);
uint32 items_num = CHILDREN_NUM(g_pcrb_key_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)key, g_pcrb_key_t_items, items_num);
}
}
static status_t repair_pdata_map_node_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
map_page_t *map_page = (map_page_t *)(page + offset);
uint32 index = rkeys->item[curr_id].index;
map_node_t *node = (map_node_t *)((char *)map_page + sizeof(map_page_t) + index * sizeof(map_node_t));
uint32 items_num = CHILDREN_NUM(g_map_node_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)node, g_map_node_t_items, items_num);
}
static status_t repair_pdata_itl_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
heap_page_t *heap_page = (heap_page_t *)(page + offset);
uint32 index = rkeys->item[curr_id].index;
if (index >= heap_page->itls) {
printf("index is large than max itl number %u\n", heap_page->itls);
return OG_ERROR;
}
if (heap_page->head.type == PAGE_TYPE_HEAP_DATA) {
itl_t *heap_itl = heap_get_itl(heap_page, (uint8)index);
uint32 items_num = CHILDREN_NUM(g_itl_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)heap_itl, g_itl_t_items, items_num);
} else {
pcr_itl_t *pcr_itl = pcrh_get_itl(heap_page, (uint8)index);
uint32 items_num = CHILDREN_NUM(g_pcr_itl_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)pcr_itl, g_pcr_itl_t_items, items_num);
}
}
static status_t repair_pdata_row_dir_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
heap_page_t *heap_page = (heap_page_t *)(page + offset);
uint32 index = rkeys->item[curr_id].index;
if (index >= heap_page->dirs) {
printf("index is large than max dir number %u\n", heap_page->dirs);
return OG_ERROR;
}
if (heap_page->head.type == PAGE_TYPE_HEAP_DATA) {
row_dir_t *heap_dir = heap_get_dir(heap_page, index);
uint32 items_num = CHILDREN_NUM(g_row_dir_t_items);
return repair_item_of_object(rkeys, value, curr_id, (char *)heap_dir, g_row_dir_t_items, items_num);
} else {
pcr_row_dir_t *pcr_dir = pcrh_get_dir(heap_page, (uint16)index);
uint16 u16_value;
if (cm_text2uint16(value, &u16_value)) {
return OG_ERROR;
}
*pcr_dir = (pcr_row_dir_t)u16_value;
return OG_SUCCESS;
}
}
static status_t repair_pdata_row_head_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
heap_page_t *heap_page = (heap_page_t *)(page + offset);
row_head_t *row = NULL;
uint32 index = rkeys->item[curr_id].index;
uint32 items_num = CHILDREN_NUM(g_row_head_t_items);
if (index >= heap_page->dirs) {
printf("index is large than max dir number %u\n", heap_page->dirs);
return OG_ERROR;
}
if (heap_page->head.type == PAGE_TYPE_HEAP_DATA) {
row_dir_t *heap_dir = heap_get_dir(heap_page, index);
row = HEAP_GET_ROW(heap_page, heap_dir);
} else {
pcr_row_dir_t *pcr_dir = pcrh_get_dir(heap_page, (uint16)index);
row = PCRH_GET_ROW(heap_page, pcr_dir);
}
return repair_item_of_object(rkeys, value, curr_id, (char *)row, g_row_head_t_items, items_num);
}
static status_t repair_pdata_undo_row_t(repair_key_t *rkeys, text_t *value, uint32 curr_id, char *page, uint32 offset)
{
undo_page_t *undo_page = (undo_page_t *)(page + offset);
undo_row_t *row = NULL;
uint32 items_num = CHILDREN_NUM(g_undo_row_t_items);
knl_session_t *session = g_page_se;
if (rkeys->item[curr_id].index >= undo_page->rows) {
printf("index is large than max row number %u\n", undo_page->rows);
return OG_ERROR;
}
g_page_se->kernel = g_page_instance;
session->kernel->attr.page_size = PAGE_SIZE(*(page_head_t *)page);
row = UNDO_ROW(session, undo_page, rkeys->item[curr_id].index);
return repair_item_of_object(rkeys, value, curr_id, (char *)row, g_undo_row_t_items, items_num);
}
status_t repair_parse_kv(text_t *text, text_t *name, text_t *value, uint32 *line_no, bool32 *is_eof)
{
text_t line;
*is_eof = OG_TRUE;
while (cm_fetch_text(text, '\n', '\0', &line)) {
if (line.len == 0) {
continue;
}
(*line_no)++;
cm_trim_text(&line);
if (line.len >= OG_MAX_CONFIG_LINE_SIZE) {
OG_THROW_ERROR(ERR_LINE_SIZE_TOO_LONG, *line_no);
return OG_ERROR;
}
if (*line.str == '#' || line.len == 0) {
continue;
}
cm_split_text(&line, '=', '\0', name, value);
cm_trim_text(name);
cm_trim_text(value);
*is_eof = OG_FALSE;
break;
}
return OG_SUCCESS;
}
status_t repair_get_item_index(text_t *name, uint32 *array_index)
{
text_t part1;
text_t part2;
text_t part3;
cm_split_text(name, '[', '\0', &part1, &part2);
*name = part1;
cm_split_text(&part2, ']', '\0', &part1, &part3);
if (part1.len == 0) {
*array_index = OG_INVALID_ID32;
} else {
if (cm_text2uint32(&part1, array_index) != OG_SUCCESS) {
return OG_ERROR;
}
}
return OG_SUCCESS;
}
static status_t repair_split_input_name(repair_key_t *rkeys, uint32 key_max_num, text_t *name)
{
text_t part1;
text_t part2;
text_t remain_text = { "page", 4 };
uint32 id = 0;
errno_t ret;
ret = memset_s(rkeys, sizeof(repair_key_t), 0, sizeof(repair_key_t));
knl_securec_check(ret);
if (cm_text2str(&remain_text, rkeys->item[id].name, OG_MAX_NAME_LEN) != OG_SUCCESS) {
return OG_ERROR;
}
rkeys->item[id].index = OG_INVALID_ID32;
cm_split_text(name, '.', '\0', &part1, &part2);
while (part1.len != 0) {
id++;
if (id >= key_max_num) {
printf("too many keys, max count is %u\n", key_max_num);
return OG_ERROR;
}
if (repair_get_item_index(&part1, &rkeys->item[id].index)) {
return OG_ERROR;
}
if (cm_text2str(&part1, rkeys->item[id].name, OG_MAX_NAME_LEN) != OG_SUCCESS) {
return OG_ERROR;
}
remain_text = part2;
cm_split_text(&remain_text, '.', '\0', &part1, &part2);
}
return OG_SUCCESS;
}
static status_t repair_set_page_kv(page_head_t *head, text_t *name, text_t *value, repair_page_part_t type)
{
repair_key_t rkeys;
if (repair_split_input_name(&rkeys, REPAIR_MAX_KEY_NUM, name) != OG_SUCCESS) {
return OG_ERROR;
}
cm_trim_text(name);
cm_trim_text(value);
cm_text_lower(name);
cm_text_lower(value);
switch (type) {
case REPAIR_PAGE_HEAD:
return repair_set_page_head(head, name, value);
case REPAIR_PAGE_CTRL:
return repair_set_page_ctrl(&rkeys, head, name, value);
case REPAIR_PAGE_TAIL:
return repair_set_page_tail(PAGE_TAIL(head), name, value);
default:
OG_THROW_ERROR(ERR_INVALID_DATABASE_DEF, "invalid repair type");
return OG_ERROR;
}
}
status_t repair_format_input(input_data_t input, char *buf, int32 buf_len, int32 *real_len)
{
int32 i;
if (input.is_file) {
(void)cm_seek_file(input.file_handle, 0, SEEK_SET);
if (cm_read_file(input.file_handle, buf, (int32)buf_len, real_len) != OG_SUCCESS) {
return OG_ERROR;
}
} else {
errno_t ret = memcpy_s(buf, buf_len, input.input_str, *real_len);
if (ret != EOK) {
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)OG_MAX_LOG_BUFFER_SIZE, "format input");
return OG_ERROR;
}
}
knl_panic(buf_len >= (*real_len));
for (i = 0; i < (*real_len); i++) {
if (buf[i] == ',') {
buf[i] = '\n';
}
}
return OG_SUCCESS;
}
static status_t repair_page_with_input(page_head_t *head, input_data_t input, repair_page_part_t type)
{
int32 buf_len = input.is_file ? (int32)cm_file_size(input.file_handle) : (int32)strlen(input.input_str) + 1;
int32 real_len = buf_len;
char *buf = NULL;
bool32 is_eof = OG_FALSE;
uint32 line_no;
text_t text;
text_t name;
text_t value;
if (buf_len <= 0 || buf_len >= (int32)SIZE_M(16)) {
OG_THROW_ERROR(ERR_ALLOC_MEMORY, buf_len, "repair load head");
return OG_ERROR;
}
buf = (char *)malloc(buf_len);
if (buf == NULL) {
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)buf_len, "repair load head");
return OG_ERROR;
}
if (repair_format_input(input, buf, buf_len, &real_len) != OG_SUCCESS) {
CM_FREE_PTR(buf);
return OG_ERROR;
}
text.len = (uint32)buf_len;
text.str = buf;
line_no = 0;
for (;;) {
if (repair_parse_kv(&text, &name, &value, &line_no, &is_eof) != OG_SUCCESS) {
CM_FREE_PTR(buf);
return OG_ERROR;
}
if (is_eof) {
break;
}
if (repair_set_page_kv(head, &name, &value, type) != OG_SUCCESS) {
CM_FREE_PTR(buf);
return OG_ERROR;
}
}
CM_FREE_PTR(buf);
return OG_SUCCESS;
}
status_t repair_write_page(int32 handle, char *buf, int64 offset, uint32 page_size)
{
cm_seek_file(handle, offset, SEEK_SET);
return cm_write_file(handle, buf, page_size);
}
static void repair_closefiles(repair_page_def_t *page_input, int32 dfilehandle)
{
cm_close_file(dfilehandle);
if (page_input->head_input.file_handle != OG_INVALID_INT32) {
cm_close_file(page_input->head_input.file_handle);
page_input->head_input.file_handle = OG_INVALID_INT32;
}
if (page_input->ctrl_input.file_handle != OG_INVALID_INT32) {
cm_close_file(page_input->ctrl_input.file_handle);
page_input->ctrl_input.file_handle = OG_INVALID_INT32;
}
if (page_input->tail_input.file_handle != OG_INVALID_INT32) {
cm_close_file(page_input->tail_input.file_handle);
page_input->tail_input.file_handle = OG_INVALID_INT32;
}
}
static status_t repair_openfiles(repair_page_def_t *page_input, int32 *dfilehandle)
{
if (cm_open_file(page_input->datafile, O_RDWR | O_BINARY | O_SYNC, dfilehandle) != OG_SUCCESS) {
return OG_ERROR;
}
if (page_input->head_input.input_str != NULL && cm_file_exist(page_input->head_input.input_str)) {
page_input->head_input.is_file = OG_TRUE;
if (cm_open_file(page_input->head_input.input_str, O_RDONLY | O_BINARY, &page_input->head_input.file_handle) !=
OG_SUCCESS) {
repair_closefiles(page_input, *dfilehandle);
return OG_ERROR;
}
}
if (page_input->ctrl_input.input_str != NULL && cm_file_exist(page_input->ctrl_input.input_str)) {
page_input->ctrl_input.is_file = OG_TRUE;
if (cm_open_file(page_input->ctrl_input.input_str, O_RDONLY | O_BINARY, &page_input->ctrl_input.file_handle) !=
OG_SUCCESS) {
repair_closefiles(page_input, *dfilehandle);
return OG_ERROR;
}
}
if (page_input->tail_input.input_str != NULL && cm_file_exist(page_input->tail_input.input_str)) {
page_input->tail_input.is_file = OG_TRUE;
if (cm_open_file(page_input->tail_input.input_str, O_RDONLY | O_BINARY, &page_input->tail_input.file_handle) !=
OG_SUCCESS) {
repair_closefiles(page_input, *dfilehandle);
return OG_ERROR;
}
}
return OG_SUCCESS;
}
static status_t repair_pages(int32 dfilehandle, char *buf, uint64 start, uint32 input_count, uint32 page_size,
repair_page_def_t *page_input)
{
uint32 hack_count = 0;
uint32 count = (input_count != OG_INVALID_ID32) ? input_count : 1;
page_head_t *head = NULL;
int64 i = (start != OG_INVALID_ID64) ? (int64)start : 0;
uint8 size_uints_new;
while (miner_read_page(dfilehandle, buf, i * page_size, page_size) == OG_SUCCESS) {
head = (page_head_t *)buf;
hack_count++;
if (page_input->head_input.input_str != NULL) {
if (repair_page_with_input(head, page_input->head_input, REPAIR_PAGE_HEAD) != OG_SUCCESS) {
return OG_ERROR;
}
}
size_uints_new = head->size_units;
if (page_input->ctrl_input.input_str != NULL) {
if (head->compressed) {
printf("this is a compress page, page_id %lld", i);
continue;
}
if (repair_page_with_input(head, page_input->ctrl_input, REPAIR_PAGE_CTRL) != OG_SUCCESS) {
return OG_ERROR;
}
}
head->size_units = page_size / PAGE_UNIT_SIZE;
if (page_input->tail_input.input_str != NULL) {
if (repair_page_with_input(head, page_input->tail_input, REPAIR_PAGE_TAIL) != OG_SUCCESS) {
return OG_ERROR;
}
}
head->size_units = size_uints_new;
if (page_input->is_checksum) {
page_calc_checksum(head, page_size);
}
if (repair_write_page(dfilehandle, buf, i * page_size, page_size) != OG_SUCCESS) {
return OG_ERROR;
}
if (count != OG_INVALID_ID32 && hack_count >= count) {
return OG_SUCCESS;
}
i++;
}
return OG_SUCCESS;
}
static status_t repair_init(repair_page_def_t *page_input, int32 *dfilehandle, uint32 page_size, char **buf)
{
errno_t ret;
if (repair_openfiles(page_input, dfilehandle) != OG_SUCCESS) {
return OG_ERROR;
}
if (page_size == 0 || page_size >= SIZE_M(4)) {
repair_closefiles(page_input, *dfilehandle);
OG_THROW_ERROR(ERR_ALLOC_MEMORY, page_size, "repair datafile");
return OG_ERROR;
}
*buf = (char *)malloc(page_size);
if (*buf == NULL) {
repair_closefiles(page_input, *dfilehandle);
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)page_size, "repair datafile");
return OG_ERROR;
}
ret = memset_sp(*buf, page_size, 0, page_size);
if (ret != EOK) {
CM_FREE_PTR(*buf);
repair_closefiles(page_input, *dfilehandle);
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)OG_MAX_LOG_BUFFER_SIZE, "repair datafile");
return OG_ERROR;
}
g_page_se = (knl_session_t *)malloc(sizeof(knl_session_t));
if (g_page_se == NULL) {
repair_closefiles(page_input, *dfilehandle);
CM_FREE_PTR(*buf);
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)sizeof(knl_session_t), "repair datafile");
return OG_ERROR;
}
g_page_instance = (knl_instance_t *)malloc(sizeof(knl_instance_t));
if (g_page_instance == NULL) {
repair_closefiles(page_input, *dfilehandle);
CM_FREE_PTR(*buf);
CM_FREE_PTR(g_page_se);
OG_THROW_ERROR(ERR_ALLOC_MEMORY, (uint64)sizeof(knl_instance_t), "repair datafile");
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t repair_datafile(repair_page_def_t *page_input, repair_input_common_t *input_common)
{
status_t status;
char *buf = NULL;
int32 dfilehandle;
status = repair_init(page_input, &dfilehandle, input_common->page_size, &buf);
if (status != OG_SUCCESS) {
printf("repair datafile init failed.\n");
return status;
}
status = repair_pages(dfilehandle, buf, input_common->start, input_common->count,
input_common->page_size, page_input);
repair_closefiles(page_input, dfilehandle);
CM_FREE_PTR(buf);
CM_FREE_PTR(g_page_se);
CM_FREE_PTR(g_page_instance);
return status;
}
status_t repair_set_page_ctrl(repair_key_t *rkeys, page_head_t *head, text_t *name, text_t *value)
{
char *page = (char *)head;
uint32 offset;
uint32 i;
rkeys->page_size = (head->size_units > 0) ? PAGE_SIZE(*head) : MINER_DEF_PAGE_SIZE ;
for (i = 0; i < REPAIR_PAGE_TYPE_NUM; i++) {
if (g_page_ctrl_items[i].type == head->type) {
offset = g_page_ctrl_items[i].page_offset;
if (repair_common_entry(rkeys, value, page, 0, offset, &g_page_ctrl_items[i].page_item) != OG_SUCCESS) {
printf("failed to proccess repairing %s, page type %s\n",
T2S(name), g_page_ctrl_items[i].page_item.name);
return OG_ERROR;
}
return OG_SUCCESS;
}
}
OG_THROW_ERROR(ERR_NOT_SUPPORT_TYPE, (int32)head->type);
return OG_ERROR;
}
static status_t repair_set_page_func_uint8(void *item_ptr, text_t *value)
{
uint16 val;
if (cm_text2uint16(value, &val) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint16 type.\n", value->str);
return OG_ERROR;
}
*(uint8 *)item_ptr = (uint8)val;
return OG_SUCCESS;
}
static status_t repair_set_page_func_uint16(void *item_ptr, text_t *value)
{
uint16 val;
if (cm_text2uint16(value, &val) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint16 type.\n", value->str);
return OG_ERROR;
}
*(uint16 *)item_ptr = val;
return OG_SUCCESS;
}
static status_t repair_set_page_func_uint32(void *item_ptr, text_t *value)
{
uint32 val;
if (cm_text2uint32(value, &val) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint16 type.\n", value->str);
return OG_ERROR;
}
*(uint32 *)item_ptr = val;
return OG_SUCCESS;
}
static status_t repair_set_page_func_uint64(void *item_ptr, text_t *value)
{
uint64 val;
if (cm_text2uint64(value, &val) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint16 type.\n", value->str);
return OG_ERROR;
}
*(uint64 *)item_ptr = val;
return OG_SUCCESS;
}
static status_t repair_set_page_func_pagid_data_t(void *item_ptr, text_t *value)
{
char *pgid = (char *)item_ptr;
text_t file;
text_t page;
page_id_t id;
id.vmid = 0;
cm_split_text(value, '-', '\0', &file, &page);
cm_trim_text(&file);
cm_trim_text(&page);
if (cm_text2uint32(&page, &id.page) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint32 type.\n", page.str);
return OG_ERROR;
}
if (cm_text2uint16(&file, &id.file) != OG_SUCCESS) {
printf("param value \'%s\' can not be converted to uint32 type.\n", file.str);
return OG_ERROR;
}
TO_PAGID_DATA(id, pgid);
return OG_SUCCESS;
}
typedef status_t (*repair_set_page_func_t)(void *item_ptr, text_t *value);
typedef struct st_repair_set_page_items {
const char *name;
uint32 item_offset;
repair_set_page_func_t repair_func;
} repair_set_page_items_t;
#define REPAIR_SET_PAGE_ITEM(name, obj, item, type) \
{ (name), (uint32)(OFFSET_OF(obj, item)), repair_set_page_func_##type}
#define REPAIR_PAGE_HEAD_ITEM_COUNT \
(sizeof(g_repair_page_head_items_list) / sizeof(repair_set_page_items_t))
repair_set_page_items_t g_repair_page_head_items_list[] = {
REPAIR_SET_PAGE_ITEM("id", page_head_t, id, pagid_data_t),
REPAIR_SET_PAGE_ITEM("type", page_head_t, type, uint8),
REPAIR_SET_PAGE_ITEM("size_units", page_head_t, size_units, uint8),
REPAIR_SET_PAGE_ITEM("next_ext", page_head_t, next_ext, pagid_data_t),
REPAIR_SET_PAGE_ITEM("pcn", page_head_t, pcn, uint32),
REPAIR_SET_PAGE_ITEM("lsn", page_head_t, lsn, uint64),
};
#define REPAIR_PAGE_TAIL_ITEM_COUNT \
(sizeof(g_repair_page_tail_items_list) / sizeof(repair_set_page_items_t))
repair_set_page_items_t g_repair_page_tail_items_list[] = {
REPAIR_SET_PAGE_ITEM("checksum", page_tail_t, checksum, uint16),
REPAIR_SET_PAGE_ITEM("pcn", page_tail_t, pcn, uint32),
};
static status_t repair_set_page_head_bit(page_head_t *head, text_t *name, text_t *value)
{
uint32 uint32_value;
if (cm_text2uint32_ex(value, &uint32_value) != NERR_SUCCESS) {
printf("\'%s\' cannot convert to uint32 when repair \'%s\' of page_head_t\n", value->str, name->str);
return OG_ERROR;
}
uint8 uint8_value = (uint8)uint32_value;
if (cm_text_str_equal(
name, "ext_size")) {
head->ext_size = uint8_value;
} else if (cm_text_str_equal(name, "encrypted")) {
head->encrypted = uint8_value;
} else if (cm_text_str_equal(name, "compressed")) {
head->compressed = uint8_value;
} else if (cm_text_str_equal(name, "soft_damage")) {
head->soft_damage = uint8_value;
} else if (cm_text_str_equal(name, "hard_damage")) {
head->hard_damage = uint8_value;
} else if (cm_text_str_equal(name, "compressed_size")) {
COMPRESS_PAGE_HEAD(head)->compressed_size = uint8_value;
} else if (cm_text_str_equal(name, "compress_algo")) {
COMPRESS_PAGE_HEAD(head)->compress_algo = uint8_value;
} else if (cm_text_str_equal(name, "group_cnt")) {
COMPRESS_PAGE_HEAD(head)->group_cnt = uint8_value;
} else if (cm_text_str_equal(name, "unused")) {
COMPRESS_PAGE_HEAD(head)->unused = uint8_value;
} else {
printf("bit value \'%s\' is not found in page_head_t\n", name->str);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t repair_set_page_head(page_head_t *head, text_t *name, text_t *value)
{
uint32 i = 0;
for (; i < REPAIR_PAGE_HEAD_ITEM_COUNT; i++) {
repair_set_page_items_t *item = &g_repair_page_head_items_list[i];
if (cm_text_str_equal(name, item->name)) {
return item->repair_func((void *)(((char *)head) + item->item_offset), value);
}
}
if (repair_set_page_head_bit(head, name, value) == OG_SUCCESS) {
return OG_SUCCESS;
}
printf("param value \'%s\' is not supported.\n", name->str);
return OG_ERROR;
}
status_t repair_set_page_tail(page_tail_t *tail, text_t *name, text_t *value)
{
uint32 i = 0;
for (; i < REPAIR_PAGE_TAIL_ITEM_COUNT; i++) {
repair_set_page_items_t *item = &g_repair_page_tail_items_list[i];
if (cm_text_str_equal(name, item->name)) {
return item->repair_func((void *)(((char *)tail) + item->item_offset), value);
}
}
printf("param value \'%s\' is not supported.\n", name->str);
return OG_ERROR;
}
uint32 extent_begin_page_sn(uint32 page_sn)
{
return PAGE_GROUP_COUNT * (page_sn / PAGE_GROUP_COUNT);
}