NotifyMyFrontEnd 函数背后的数据缓冲区(一)
async.c的
static void
NotifyMyFrontEnd(const char *channel, const char *payload, int32 srcPid) 函数中的主要逻辑是这样的:
if (whereToSendOutput == DestRemote) { StringInfoData buf; pq_beginmessage(&buf, 'A'); //cursor 为 A pq_sendint(&buf, srcPid, sizeof(int32)); //追加 srcPid pq_sendstring(&buf, channel); //追加消息通道名 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) pq_sendstring(&buf, payload); //追加消息字节流 pq_endmessage(&buf); //发送消息 ...... }
从上面看到,向StringInfoData 数据结构填充信息,就表示信息发送结束。
static void
NotifyMyFrontEnd(const char *channel, const char *payload, int32 srcPid)
pq_endmessage是 pqformat.c 中函数它 调用 pqcomm.c 中的 pq_putmessage函数
pq_putmessage 调用 internal_putbyes函数
internal_putbyes 中 对pqSendPointer 进行操作
关于 pqSendPointer/pqRevPointer,有如下定义:
--------------------------------------------------------------------------------------------
static char PqSendBuffer[PQ_BUFFER_SIZE];
static int PqSendPointer; /* Next index to store a byte in PqSendBuffer */
static char PqRecvBuffer[PQ_BUFFER_SIZE];
static int c; /* Next index to read a byte from PqRecvBuffer */
static int PqRecvLength; /* End of data available in PqRecvBuffer */
---------------------------------------------------------------------------------------------
查阅文档资料:《PostgreSQL数据库内核分析》中2.6.6中也有所说明。
从 internal_putbyes 中的代码逻辑看到,移动指针未加任何锁定机制。
static int internal_putbytes(const char *s, size_t len) { size_t amount; while (len > 0) { /* If buffer is full, then flush it out */ if (PqSendPointer >= PQ_BUFFER_SIZE) if (internal_flush()) return EOF; amount = PQ_BUFFER_SIZE - PqSendPointer; if (amount > len) amount = len; memcpy(PqSendBuffer + PqSendPointer, s, amount); PqSendPointer += amount; s += amount; len -= amount; } return 0; }
既然未加锁,那么就可以这样推断:
在每一对客户端和服务器端进程之间,都有这样一个内存缓冲区。
换句话说,有多少个客户端,就会产生多少个这样的 内存缓冲区。
具体如何,还需进一步的验证。