PostgreSQL启动过程中的那些事七:初始化共享内存和信号十八:shmem中初始化WalSender和WalRecv相关结构...

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 CtlWal 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 CtlWal 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 CtlWal Receiver Ctl相关结构的共享内存结构图

为了精简上图,把创建shmem的哈希表索引"ShmemIndex"时创建的HCTL结构删掉了,这个结构的作用是记录创建可扩展哈希表的相关信息,不过这个结构在"ShmemIndex"创建完成后也会由于出了对象作用域而消失。增加了左边灰色底的部分,描述共享内存/shmem里各变量物理布局概览,由下往上,由低地址到高地址。图中黄色的索引项就是本节新增加的索引项。

Wal Sender CtlWal Receiver Ctl相关结构图