1先上个图,看一下函数调用过程梗概,中间略过部分细节
初始化walsender和walreceiver相关结构方法调用流程图
2初始化xlog相关结构
话说main()->…->PostmasterMain()->…->reset_shared() ->CreateSharedMemoryAndSemaphores()>…->WalSndShmemInit(),调用ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"Wal Sender Ctl",如果没有,就在shmemIndex中给"Wal Sender Ctl"分一个HashElement和ShmemIndexEnt(entry),在其中的Entry中写上"WalSender Ctl"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"WalSender Ctl"相关结构(见下面“Wal Sender Ctl和Wal Receiver Ctl相关结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回WalSndShmemInit(),让WalSndCtlData*类型全局变量WalSndCtl指向所分配内存,初始化WalSndCtlData结构类型的成员值。
接着WalRcvShmemInit()-> ShmemInitStruct(),在其中调用hash_search()在哈希表索引"ShmemIndex"中查找"Wal Receiver Ctl",如果没有,就在shmemIndex中给"Wal Receiver Ctl"分一个HashElement和ShmemIndexEnt(entry),在其中的Entry中写上"WalReceiver Ctl"。返回ShmemInitStruct(),再调用ShmemAlloc()在共享内存上给"WalReceiver Ctl"相关结构(见下面“Wal Sender Ctl和Wal Receiver Ctl相关结构图”)分配空间,设置entry(在这儿及ShmemIndexEnt类型变量)的成员location指向该空间,size成员记录该空间大小,最后返回WalRcvShmemInit(),让WalRcvData*类型全局变量WalRcv指向所分配内存,初始化WalRcvData结构类型的成员值。
相关结构定义和图见下面:
typedef enum WalSndState
{
WALSNDSTATE_STARTUP = 0,
WALSNDSTATE_BACKUP,
WALSNDSTATE_CATCHUP,
WALSNDSTATE_STREAMING
} WalSndState;
/*
* Each walsender has a WalSnd structin shared memory.
*/
typedef struct WalSnd
{
pid_t pid; /* this walsender's process id, or 0 */
WalSndState state; /* this walsender's state */
XLogRecPtr sentPtr; /* WAL has been sent up to this point */
/*
* The xloglocations that have been written, flushed, and applied by
* standby-side. These maybe invalid if the standby-side has not offered
* values yet.
*/
XLogRecPtr write;
XLogRecPtr flush;
XLogRecPtr apply;
/* Protects shared variables shown above.*/
slock_t mutex;
/*
* Latch used by backendsto wake up this walsender when it has work to
* do.
*/
Latch latch;
/*
* The priority order ofthe standby managed by this WALSender, as listed
* insynchronous_standby_names, or 0 if not-listed. Protected by
* SyncRepLock.
*/
int sync_standby_priority;
} WalSnd;
extern WalSnd *MyWalSnd;
/* There is one WalSndCtl structfor the whole database cluster */
typedef struct
{
/*
* Synchronous replicationqueue. Protected by SyncRepLock.
*/
SHM_QUEUE SyncRepQueue;
/*
* Current location of thehead of the queue. All waiters should have a
* waitLSN that followsthis value. Protected by SyncRepLock.
*/
XLogRecPtr lsn;
/*
* Are any sync standbysdefined? Waiting backends can'treload the
* config filesafely, so WAL writer updates this value as needed.
* Protected bySyncRepLock.
*/
bool sync_standbys_defined;
WalSnd walsnds[1]; /* VARIABLE LENGTH ARRAY */
} WalSndCtlData;
extern WalSndCtlData *WalSndCtl;
typedef enum
{
WALRCV_STOPPED, /* stopped and mustn't start up again */
WALRCV_STARTING, /* launched, but the process hasn't
*initialized yet */
WALRCV_RUNNING, /* walreceiver is running */
WALRCV_STOPPING /* requested to stop, but still running */
} WalRcvState;
/* Shared memory area formanagement of walreceiver process */
typedef struct
{
/*
* PID of currently active walreceiverprocess, its current state and
* start time (actually,the time at which it was requested to be
* started).
*/
pid_t pid;
WalRcvState walRcvState;
pg_time_t startTime;
/*
* receiveStart is thefirst byte position that will be received. When
* startup process startsthe walreceiver, it sets receiveStart to the
* point where it wants thestreaming to begin.
*/
XLogRecPtr receiveStart;
/*
* receivedUpto-1 is thelast byte position that has already been
* received. At the first startup of walreceiver,receivedUpto is set to
* receiveStart. Afterthat, walreceiver updates this whenever it flushes
* the received WAL todisk.
*/
XLogRecPtr receivedUpto;
/*
* latestChunkStart is thestarting byte position of the current "batch"
* of received WAL. It's actually the same as the previous valueof
* receivedUpto before thelast flush to disk. Startup process canuse
* this to detect whetherit's keeping up or not.
*/
XLogRecPtr latestChunkStart;
/*
* connection string; isused for walreceiver to connect with the primary.
*/
char conninfo[MAXCONNINFO];
slock_t mutex; /* locks shared variables shown above */
} WalRcvData;
extern WalRcvData *WalRcv;
初始化完Wal Receiver Ctl和Wal Receiver Ctl相关结构的共享内存结构图
为了精简上图,把创建shmem的哈希表索引"ShmemIndex"时创建的HCTL结构删掉了,这个结构的作用是记录创建可扩展哈希表的相关信息,不过这个结构在"ShmemIndex"创建完成后也会由于出了对象作用域而消失。增加了左边灰色底的部分,描述共享内存/shmem里各变量物理布局概览,由下往上,由低地址到高地址。图中黄色的索引项就是本节新增加的索引项。
Wal Sender Ctl和Wal Receiver Ctl相关结构图