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 中写上 "Wal Sender Ctl" 。返回 ShmemInitStruct() ,再调用 ShmemAlloc() 在共享内存上给 "Wal Sender 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 中写上 "Wal Receiver Ctl" 。返回 ShmemInitStruct() ,再调用 ShmemAlloc() 在共享内存上给 "Wal Receiver 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 struct in 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 xlog locations that have been written, flushed, and applied by

      * standby-side. These may be 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 backends to wake up this walsender when it has work to

      * do.

      */

    Latch       latch ;

 

    /*

      * The priority order of the standby managed by this WALSender, as listed

      * in synchronous_standby_names, or 0 if not-listed. Protected by

      * SyncRepLock.

      */

    int         sync_standby_priority ;

} WalSnd ;

 

extern WalSnd *MyWalSnd;

 

/* There is one WalSndCtl struct for the whole database cluster */

typedef struct

{

    /*

      * Synchronous replication queue. Protected by SyncRepLock.

      */

    SHM_QUEUE   SyncRepQueue ;

 

    /*

      * Current location of the head of the queue. All waiters should have a

      * waitLSN that follows this value. Protected by SyncRepLock.

      */

    XLogRecPtr lsn ;

 

    /*

      * Are any sync standbys defined?  Waiting backends can't reload the

      * config file safely, so WAL writer updates this value as needed.

      * Protected by SyncRepLock.

      */

    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 for management of walreceiver process */

typedef struct

{

    /*

      * PID of currently active walreceiver process, 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 the first byte position that will be received. When

      * startup process starts the walreceiver , it sets receiveStart to the

      * point where it wants the streaming to begin.

      */

    XLogRecPtr receiveStart ;

 

    /*

      * receivedUpto-1 is the last byte position that has already been

      * received.  At the first startup of walreceiver , receivedUpto is set to

      * receiveStart. After that, walreceiver updates this whenever it flushes

      * the received WAL to disk.

      */

    XLogRecPtr receivedUpto ;

 

    /*

      * latestChunkStart is the starting byte position of the current "batch"

      * of received WAL.  It's actually the same as the previous value of

      * receivedUpto before the last flush to disk.   Startup process can use

      * this to detect whether it's keeping up or not.

      */

    XLogRecPtr latestChunkStart ;

 

    /*

      * connection string; is used 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 相关结构图

猜你喜欢

转载自beigang.iteye.com/blog/1488753
今日推荐