fis-gtm/sr_port/shmpool.h

185 lines
8.5 KiB
C

/****************************************************************
* *
* Copyright 2005, 2010 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef SHMPOOL_H_INCLUDED
#define SHMPOOL_H_INCLUDED
#define SBLKP_REL2ABS(base, queue) ((shmpool_blk_hdr_ptr_t)((char_ptr_t)(base) + (((que_ent_ptr_t)base)->queue)))
#define MAX_LOST_SHMPOOL_BLKS 5 /* When we have lost this many, reclaim */
#include "gdsbgtr.h"
#define SHMPOOL_BUFFER_SIZE 0x00100000 /* 1MB pool for shared memory buffers (backup and downgrade) */
/* Block types for shmpool_blk_hdr */
enum shmblk_type
{
SHMBLK_FREE = 1, /* Block is not in use */
SHMBLK_REFORMAT, /* Block contains reformat information */
SHMBLK_BACKUP /* Block in use by online backup */
};
/* These shared memory blocks are in what was called the "backup buffer" in shared memory. It is a 1MB area
of shared mem storage with (now) multiple uses. It is used by both backup and the online downgrade process
(the latter on VMS only). Free blocks are queued in shared memory.
*/
typedef struct shmpool_blk_hdr_struct
{ /* Block header for each block in shmpool buffer area. The data portion of the block immediately follows this header and
in the case of backup, is written out to the temporary file with the data block appended to it. Same holds true for
writing out incremental backup files so any change to this structure warrants consideration of changing the format
version for the incremental backup (INC_HEADER_LABEL in murest.h).
*/
que_ent sm_que; /* Main queue fields */
volatile enum shmblk_type blktype; /* free, backup or reformat? */
block_id blkid; /* block number */
union
{
struct
{ /* Use for backup */
enum db_ver ondsk_blkver; /* Version of block from cache_rec */
VMS_ONLY(int4 filler;) /* If VMS, this structure will be 2 words since rfrmt struct is */
} bkup;
#ifdef VMS
struct
{ /* Use in downgrade mode (as reformat buffer) */
volatile sm_off_t cr_off; /* Offset to cache rec associated with this reformat buffer */
volatile int4 cycle; /* cycle of given cache record (to validate we have same CR */
} rfrmt;
#endif
} use;
pid_t holder_pid; /* PID holding/using this buffer */
boolean_t valid_data; /* This buffer holds valid data (else not initialized) */
int4 image_count; /* VMS only */
VMS_ONLY(int4 filler;) /* 8 byte alignment. Only necessary for VMS since bkup struct will only
be 4 bytes for UNIX and this filler is not then necessary for alignment.
*/
} shmpool_blk_hdr;
typedef struct muinc_blk_hdr_struct
{ /* This is a mirror structure of shmpool_blk_hdr_struct to maintain compatibility with the current incremental
* backup format. The sm_que structure is replaced with a 8-byte filler.
*/
char filler_8byte[8]; /* Main queue fields */
volatile enum shmblk_type blktype; /* free, backup or reformat? */
block_id blkid; /* block number */
union
{
struct
{ /* Use for backup */
enum db_ver ondsk_blkver; /* Version of block from cache_rec */
VMS_ONLY(int4 filler;) /* If VMS, this structure will be 2 words since rfrmt struct is */
} bkup;
#ifdef VMS
struct
{ /* Use in downgrade mode (as reformat buffer) */
volatile sm_off_t cr_off; /* Offset to cache rec associated with this reformat buffer */
volatile int4 cycle; /* cycle of given cache record (to validate we have same CR */
} rfrmt;
#endif
} use;
pid_t holder_pid; /* PID holding/using this buffer */
boolean_t valid_data; /* This buffer holds valid data (else not initialized) */
int4 image_count; /* VMS only */
VMS_ONLY(int4 filler;) /* 8 byte alignment. Only necessary for VMS since bkup struct will only
be 4 bytes for UNIX and this filler is not then necessary for alignment.
*/
} muinc_blk_hdr;
/* Header of the shmpool buffer area. Describes contents */
typedef struct shmpool_buff_hdr_struct
{
global_latch_t shmpool_crit_latch; /* Latch to update header fields */
off_t dskaddr; /* Highest disk address used (backup only) */
trans_num backup_tn; /* TN at start of full backup (backup only) */
trans_num inc_backup_tn; /* TN to start from for incremental backup (backup only) */
char tempfilename[256]; /* Name of temporary file we are using (backup only) */
que_ent que_free; /* Queue header for all free elements */
que_ent que_backup; /* Queue header for all (allocated) backup elements */
VMS_ONLY(que_ent que_reformat;) /* Queue header for all (allocated) reformat elements */
volatile int4 free_cnt; /* Elements on free queue */
volatile int4 backup_cnt; /* Elements used for backup */
volatile int4 reformat_cnt; /* Elements used for reformat */
volatile int4 allocs_since_chk; /* Allocations since last lost block check */
uint4 total_blks; /* Total shmpool block buffers in 1MB buffer area */
uint4 blk_size; /* Size of the created buffers (excluding header - convenient blk_size field) */
pid_t failed; /* Process id that failed to write to temp file causing failure (backup only) */
int4 backup_errno; /* errno value when "failed" is set (backup only) */
uint4 backup_pid; /* Process id performing online backup (backup only) */
uint4 backup_image_count; /* Image count of process running online backup (VMS & backup only) */
boolean_t shmpool_blocked; /* secshr_db_clnup() detected a problem on shutdown .. force recovery */
uint4 filler; /* 8 byte alignment */
} shmpool_buff_hdr;
typedef shmpool_buff_hdr *shmpool_buff_hdr_ptr_t;
typedef muinc_blk_hdr muinc_blk_hdr_t;
typedef muinc_blk_hdr *muinc_blk_hdr_ptr_t;
typedef shmpool_blk_hdr *shmpool_blk_hdr_ptr_t;
/* Macro to allow release of a shmpool reformat block if the current cache record is pointing to it
(and we can get the shmpool critical lock).
*/
#ifdef VMS
# define SHMPOOL_FREE_CR_RFMT_BLOCK(reg, csa, cr) \
{ \
shmpool_blk_hdr_ptr_t SFCRB_sblkh_p; \
int SFCRB_sblkh_off; \
assert(csa->now_crit); \
if (0 != (SFCRB_sblkh_off = cr->shmpool_blk_off)) \
{ /* Break the link to the shmpool buffer for this cache record now that \
the IO is complete. Also allow the block to be requeued if we can get \
the shmpool lock (if not block will be harvested later). \
*/ \
cr->shmpool_blk_off = 0; \
SFCRB_sblkh_p = (shmpool_blk_hdr_ptr_t)GDS_ANY_REL2ABS(csa, SFCRB_sblkh_off); \
if (GDS_ANY_REL2ABS(csa, SFCRB_sblkh_p->use.rfrmt.cr_off) == cr \
&& SHMBLK_REFORMAT == SFCRB_sblkh_p->blktype \
&& cr->cycle == SFCRB_sblkh_p->use.rfrmt.cycle \
&& shmpool_lock_hdr_nowait(reg)) \
{ /* If it is pointing at us and we are able to get lock (check of offset pointer \
outside of lock is not definitive but allows us to avoid a lock operation if \
it isn't true). \
Recheck offset pointer/type now that we are under lock \
*/ \
if (GDS_ANY_REL2ABS(csa, SFCRB_sblkh_p->use.rfrmt.cr_off) == cr \
&& SHMBLK_REFORMAT == SFCRB_sblkh_p->blktype \
&& cr->cycle == SFCRB_sblkh_p->use.rfrmt.cycle) \
{ /* This reformat buffer is (still) pointing to us. Free it for reuse */ \
shmpool_blk_free(reg, SFCRB_sblkh_p); \
BG_TRACE_ANY(csa, refmt_blk_chk_blk_freed); \
} else \
{ \
BG_TRACE_ANY(csa, refmt_blk_chk_blk_kept); \
} \
shmpool_unlock_hdr(reg); \
} else \
{ \
BG_TRACE_ANY(csa, refmt_blk_chk_blk_kept); \
} \
} \
}
#else
# define SHMPOOL_FREE_CR_RFMT_BLOCK(reg, csa, cr)
#endif
void shmpool_buff_init(gd_region *reg);
shmpool_blk_hdr_ptr_t shmpool_blk_alloc(gd_region *reg, enum shmblk_type blktype);
void shmpool_blk_free(gd_region *reg, shmpool_blk_hdr_ptr_t sblkh_p);
VMS_ONLY(void shmpool_harvest_reformatq(gd_region *reg);)
void shmpool_abandoned_blk_chk(gd_region *reg, boolean_t force);
boolean_t shmpool_lock_hdr(gd_region *reg);
boolean_t shmpool_lock_hdr_nowait(gd_region *reg);
void shmpool_unlock_hdr(gd_region *reg);
boolean_t shmpool_lock_held_by_us(gd_region *reg);
#endif