1d540f44创建于 2021年9月23日历史提交
/*
 * Copyright (c) 2020 Huawei Technologies Co.,Ltd.
 *
 * openGauss 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.
 * ---------------------------------------------------------------------------------------
 * 
 * bcm.h
 *      bcm map interface
 * 
 * 
 * IDENTIFICATION
 *        src/include/replication/bcm.h
 *
 * ---------------------------------------------------------------------------------------
 */
#ifndef BCM_H
#define BCM_H

#include "storage/buf/block.h"
#include "storage/buf/buf.h"
#include "storage/smgr/relfilenode.h"
#include "utils/relcache.h"

typedef uint32 BCMBitStatus;

#define SYNCED 0U
#define NOTSYNCED 1
#define BACKUP 0
#define NOTBACKUP 1

typedef struct BCMHeader {
    StorageEngine type;
    RelFileNode node;
    int32 blockSize; /* one bit corresponding size */
} BCMHeader;

/*
 * Size of the bitmap on each bcm map page, in bytes. There's no
 * extra headers, so the whole page minus the standard page header is
 * used for the bitmap.
 */
#define BCMMAPSIZE (BLCKSZ - MAXALIGN(SizeOfPageHeaderData))

/* Number of bits allocated for each heap block. */
#define BCM_BITS_PER_BLOCK 2

/* Number of heap blocks we can represent in one byte. */
#define BCM_BLOCKS_PER_BYTE 4

/* Number of blocks we can represent in one bcm map page. */
#define BCM_BLOCKS_PER_PAGE (BCMMAPSIZE * BCM_BLOCKS_PER_BYTE)

/* 10 */
#define BCM_SYNC_BITMASK 2U
/* 01 */
#define BCM_BACKUP_BITMASK 1

/* max continous bits which should be no more than max CU load sizes */
#define MAXCONTIBITS ((512 * 1024) / ALIGNOF_CUSIZE)

/* 1000 */
#define META_SYNC0_BITMASK 8U
/* 0100 */
#define META_BACKUP0_BITMASK 4
/* 0010 */
#define META_SYNC1_BITMASK 2U
/* 0001 */
#define META_BACKUP1_BITMASK 1

/* Number of bits allocated for each bcm block. */
#define META_BITS_PER_BLOCK 4

/* Number of bcm blocks we can represent in one byte. */
#define META_BLOCKS_PER_BYTE 2

/* Number of blocks we can represent in one mata page. */
#define META_BLOCKS_PER_PAGE (BCMMAPSIZE * META_BLOCKS_PER_BYTE)

/*
 * Mapping from bcm block number to the right bit in the right bcm meta page
 * Page0 is for bcm file header, so logically the bcm file is just like as follow:
 * Page0-Meta1-Page11-Page12-...Page1N-Meta2-Page21-Page22...
 */
#define BCMBLK_TO_BCMGROUP(x) (((x)-1) / (META_BLOCKS_PER_PAGE + 1))
#define BCMBLK_TO_METABLOCK(x) (BCMBLK_TO_BCMGROUP(x) * (META_BLOCKS_PER_PAGE + 1) + 1)
#define BCMBLK_TO_METABYTE(x) (((x)-BCMBLK_TO_METABLOCK(x) - 1) / META_BLOCKS_PER_BYTE)
#define BCMBLK_TO_METABIT(x) (((x)-BCMBLK_TO_METABLOCK(x) - 1) % META_BLOCKS_PER_BYTE)

/* Mapping from heap block number to the right bit in the BCM map */
/* Page 0 is for bcm file header, Page 1 is for meta page, so we begin from page 2 */
#define UNITBLK_TO_BCMGROUP(x) ((x) / BCM_BLOCKS_PER_PAGE / META_BLOCKS_PER_PAGE)
#define HEAPBLK_TO_BCMBLOCK(x) (((x) / BCM_BLOCKS_PER_PAGE) + UNITBLK_TO_BCMGROUP(x) + 2)
#define HEAPBLK_TO_BCMBYTE(x) (((x) % BCM_BLOCKS_PER_PAGE) / BCM_BLOCKS_PER_BYTE)
#define HEAPBLK_TO_BCMBIT(x) ((x) % BCM_BLOCKS_PER_BYTE)

#define SET_SYNC_BYTE_STATUS(byte, status, bshift)               \
    do {                                                         \
        unsigned char byteval = byte;                            \
        byteval &= ~(unsigned char)(BCM_SYNC_BITMASK << bshift); \
        byteval |= (status << (bshift + 1));                     \
        byte = byteval;                                          \
    } while (0)

#define SET_SYNC0_BYTE_STATUS(byte, status, bshift)                \
    do {                                                           \
        unsigned char byteval = byte;                              \
        byteval &= ~(unsigned char)(META_SYNC0_BITMASK << bshift); \
        byteval |= (status << (bshift + 3));                       \
        byte = byteval;                                            \
    } while (0)

#define SET_SYNC1_BYTE_STATUS(byte, status, bshift)                \
    do {                                                           \
        unsigned char byteval = byte;                              \
        byteval &= ~(unsigned char)(META_SYNC1_BITMASK << bshift); \
        byteval |= (status << (bshift + 1));                       \
        byte = byteval;                                            \
    } while (0)

/*
 * The algorithm is very clear, we devide this into two parts:
 * 1. the total heap blocks in previous actual bcm pages.
 * 2. the total heap blocks in current bcm page
 */
#define GET_HEAP_BLOCK(block, byte, bshift) \
    ((block - BCMBLK_TO_BCMGROUP(block) - 2) * BCM_BLOCKS_PER_PAGE + (byte)*BCM_BLOCKS_PER_BYTE + (bshift))

/* Here the block should be meta block */
#define GET_BCM_BLOCK(block, byte, bshift) (block + (byte)*META_BLOCKS_PER_BYTE + (bshift) + 1)

/* Create a bcm file and init the file header */
extern void createBCMFile(Relation rel);

/* record one bcm xlog for cu */
extern void BCMLogCU(Relation rel, uint64 offset, int col, BCMBitStatus status, int count);

/* Set the corresponding bit of the block as status */
extern void BCMSetStatusBit(Relation rel, uint64 heapBlk, Buffer buf, BCMBitStatus status, int col = 0);

/* BCM clear */
extern void BCMClearRel(Relation rel, int col = 0);
extern void BCM_truncate(Relation rel);

/* BCM Traversal */
extern void GetBcmFileList(bool clear);
extern void GetIncrementalBcmFileList();

/* BCM xlog for setStatusBit is (RM_HEAP2_ID, XLOG_HEAP2_BCM) type */
/* Functions in heapam.cpp: log_heap_bcm(...);heap_xlog_bcm(...)*/

/* BCM pin */
extern void BCM_pin(Relation rel, BlockNumber heapBlk, Buffer* bcmbuf);

extern void BCM_CStore_pin(Relation rel, int col, uint64 offset, Buffer* buf);

extern void check_cu_block(char* mem, int size, int alignSize);

extern uint64 cstore_offset_to_cstoreblock(uint64 offset, uint64 align_size);

extern uint64 cstore_offset_to_bcmblock(uint64 offset, uint64 align_size);

#endif