tiXactStateData *类型全局静态变量MultiXactState指向MultiXactStateData结构实例,MultiXactStateData的起始地址就是在shmem里给"Shared MultiXact State"相关结构分配的内存起始地址,设置其中MultiXactStateData结构类型的成员值。
相关变量、结构定义和初始化完成后数据结构图在下面。
static MT_LOCAL SlruCtlData MultiXactOffsetCtlData;
static MT_LOCAL SlruCtlData MultiXactMemberCtlData;
#define MultiXactOffsetCtl (&MultiXactOffsetCtlData)
#define MultiXactMemberCtl (&MultiXactMemberCtlData)
typedef struct SlruCtlData
{
SlruShared shared;
/*
* This flag tells whether to fsync writes(true for pg_clog, false for
* pg_subtrans).
*/
bool do_fsync;
/*
* Decide which of two page numbers is"older" for truncation purposes. We
* need to use comparison of TransactionIdshere in order to do the right
* thing with wraparound XID arithmetic.
*/
bool (*PagePrecedes)(int, int);
/*
* Dir is set during SimpleLruInit and does notchange thereafter. Since
* it's always the same, it doesn't need to bein shared memory.
*/
char Dir[64];
} SlruCtlData;
typedef SlruCtlData *SlruCtl;
/*
* Shared-memorystate
*/
typedef struct SlruSharedData
{
LWLockId ControlLock;
/* Number of buffers managed by this SLRU structure */
int num_slots;
/*
* Arrays holding info for each bufferslot. Page number is undefined
* when status is EMPTY, as is page_lru_count.
*/
char **page_buffer;
SlruPageStatus*page_status;
bool *page_dirty;
int *page_number;
int *page_lru_count;
LWLockId *buffer_locks;
/*----------
* We mark a page "most recentlyused" by setting
* page_lru_count[slotno]= ++cur_lru_count;
* The oldest page is therefore the one withthe highest value of
* cur_lru_count- page_lru_count[slotno]
* The counts will eventually wrap around, butthis calculation still
* works as long as no page's age exceedsINT_MAX counts.
*----------
*/
int cur_lru_count;
/*
* latest_page_number is the page number of thecurrent end of the log;
* this is not critical data, since we use itonly to avoid swapping out
* the latest page.
*/
int latest_page_number;
} SlruSharedData;
typedef SlruSharedData *SlruShared;
static MultiXactStateData *MultiXactState;
typedef structMultiXactStateData
{
/* next-to-be-assigned MultiXactId */
MultiXactIdnextMXact;
/* next-to-be-assigned offset */
MultiXactOffsetnextOffset;
/* the Offset SLRU area was last truncated at thisMultiXactId */
MultiXactIdlastTruncationPoint;
/*
* Per-backend data starts here. We have two arrays stored in the area
* immediately following the MultiXactStateDatastruct. Each is indexed by
* BackendId. (Note: valid BackendIds run from 1 to MaxBackends; element
* zero of each array is never used.)
*
* OldestMemberMXactId[k] is the oldestMultiXactId each backend's current
* transaction(s) could possibly be a memberof, or InvalidMultiXactId
* when the backend has no live transactionthat could possibly be a
* member of a MultiXact. Each backend sets its entry to the current
* nextMXact counter just before firstacquiring a shared lock in a given
* transaction, and clears it at transactionend. (This works be