86565656 发表于 2016-11-21 08:17:08

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 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 walsenderhas 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 walsenderwhen 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 backendscan'treload the
     * configfilesafely, so WAL writer updates this value as needed.
     * Protected bySyncRepLock.
     */
    bool       sync_standbys_defined;
 
    WalSnd     walsnds;       /* 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,             /* walreceiveris running */
    WALRCV_STOPPING             /* requested to stop, but still running */
} WalRcvState;
 
/* Shared memory area formanagement of walreceiverprocess */
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, walreceiverupdates 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 walreceiverto connect with the primary.
     */
    char       conninfo;
 
    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相关结构图
页: [1]
查看完整版本: PostgreSQL启动过程中的那些事七:初始化共享内存和信号十八:shmem中初始化WalSender和WalRecv相关结构