#include "postgres.h"
#include
#include "fmgr.h"
#include "access/xlog.h"
#include "replication/walreceiver.h"
#include "utils/elog.h"
#include "utils/builtins.h"
#include "utils/timestamp.h"
#include "funcapi.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "utils/pg_lsn.h" #ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif PG_FUNCTION_INFO_V1(get_rcv_replication_stat); Datum
get_rcv_replication_stat(PG_FUNCTION_ARGS)
{
Assert(PG_NARGS() == ); // 表示没有输入参数 if (!RecoveryInProgress()) // 在数据库处于恢复状态下时运行,否则不允许
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is not in progress"),
errhint("This functions can only be executed during recovery."))); /* use volatile pointer to prevent code rearrangement */
volatile WalRcvData *walrcv = WalRcv; // 共享内存中用于管理流复制的数据结构 src/include/replication/walreceiver.h
TupleDesc tupdesc; // 创建一个行描述变量
Datum DatumValue[]; // 创建一个存储值的Datum数组, 需要返回几个字段, 创建相应长度的数组
bool nulls[]; // 元组中的属性数 typedef struct TupleDescData -> natts; /* Initialise DatumValue and NULL flags arrays 初始化 */
MemSet(DatumValue, , sizeof(DatumValue));
MemSet(nulls, , sizeof(nulls)); /* Initialise attributes information in the tuple descriptor 定义字段类型和字段名, 到相应的头文件src/include/catalog/pg_type.h找到对应的类型 */ /*
CreateTemplateTupleDesc
该函数分配一个空的元组描述符结构。
元组类型的ID信息被初始设置为一个匿名记录类型;
如果需要调用者可以覆盖此。 TupleDescInitEntry: 此函数在先前分配的元组描述符中初始化单个属性结构。
如果attributeName为NULL,则attname字段将设置为空字符串(这是在我们不知道或不需要该字段名称的情况下)。
另外,某些调用者使用此功能来更改现有tupdesc中与数据类型相关的字段;例如, 它们传递attributeName = NameStr(att-> attname)来指示不应修改attname字段。
请注意,attcollation设置为指定数据类型的默认值。 如果需要非默认排序规则,请稍后使用TupleDescInitEntryCollation插入它。
*/
tupdesc = CreateTemplateTupleDesc(, false);
TupleDescInitEntry(tupdesc, (AttrNumber) , "last_walend_time",
TIMESTAMPTZOID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "last_recv_lsn",
LSNOID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "last_apply_lsn",
LSNOID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "last_apply_delay_ms",
INT4OID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "receiver_pid",
INT4OID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "receiver_state",
INT4OID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "receiver_start_time",
INT8OID, -, );
TupleDescInitEntry(tupdesc, (AttrNumber) , "receiver_conninfo",
TEXTOID, -, );
BlessTupleDesc(tupdesc); // 完成对返回类型的构造, 参考src/include/funcapi.h // 接下来将每个值转换为对应的Datum存储到DatumValue数组, 对应的nulls数组仅当值为空时设置为true.
TimestampTz receipttime;
receipttime = walrcv->latestWalEndTime; // TimestampTz latestWalEndTime;
DatumValue[] = TimestampTzGetDatum(receipttime); // #define TimestampTzGetDatum(X) Int64GetDatum(X)
XLogRecPtr recvPtr; // src/include/access/xlogdefs.h 指向XLOG中的位置的指针。 这些指针为64位宽,因为我们不希望它们溢出。 /*
src/backend/replication/walreceiverfuncs.c: GetWalRcvWriteRecPtr
返回walreceiver已写入的最后1个字节位置。
(可选)返回上一个块开始,即在最近的walreceiver刷新周期中写入的第一个字节。 对该值不感兴趣的调用者可以为lastChunkStart传递NULL。 与receiveTLI相同。
*/
recvPtr = GetWalRcvWriteRecPtr(NULL, NULL); // XLogRecPtr recptr;
if (recvPtr == )
nulls[] = true;
else
DatumValue[] = LSNGetDatum(recvPtr); // #define LSNGetDatum(X) (Int64GetDatum((int64) (X))) /*
xlog.c: GetXLogReplayRecPtr
获取最新的重做apply position。
导出以允许WALReceiver直接读取指针。 */
XLogRecPtr applyPtr;
applyPtr = GetXLogReplayRecPtr(NULL);
if (recvPtr == )
nulls[] = true;
else
DatumValue[] = LSNGetDatum(applyPtr);
int apply_delay_ms; /*
walreceiverfuncs.c: GetReplicationApplyDelay
如果没有应用延迟信息,则返回复制应用延迟(以毫秒为单位)或-1
*/
apply_delay_ms = GetReplicationApplyDelay();
if (apply_delay_ms == -)
nulls[] = true;
else
DatumValue[] = Int32GetDatum(apply_delay_ms);
DatumValue[] = Int32GetDatum(walrcv->pid);
DatumValue[] = Int32GetDatum(walrcv->walRcvState);
DatumValue[] = Int64GetDatum(walrcv->startTime);
DatumValue[] = PointerGetDatum(cstring_to_text((char *)walrcv->conninfo));
// 返回
/* Returns the record as Datum 把元组变成 datum */
PG_RETURN_DATUM(HeapTupleGetDatum( heap_form_tuple(tupdesc, DatumValue, nulls))); // heap_form_tuple 构造一个tuple 返回 HeapTupleHeader , HeapTupleGetDatum 将HeapTupleHeader指针转换为Datum。 }

学习postgresql spi(一)的更多相关文章

  1. Dubbo源码学习之-SPI介绍

    前言 学习之路还是要戒骄戒躁,一以贯之的积累前行.之前的公司部门技术达人少,自己总向往那些技术牛人多的团队,想象自己进去之后能跟别人学到多少东西.如今进到一个这样的团队之后,却发现之前自己的想法过于幼 ...

  2. postgresql spi开发笔记

    #include "postgres.h" #include "fmgr.h" #include <string.h> #ifdef PG_MODU ...

  3. Linux学习 :SPI通讯协议

    SPI接口的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的.SPI接口主要应用在E ...

  4. STM32学习笔记——SPI串行通讯(向原子哥学习)

    一.SPI  简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在  EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...

  5. gitlab不支持mysql,这就是我学习PostgreSQL的原因

    Gitlab 官方宣布,将从 12.1 版本开始不再支持 MySQL 数据库.早在 2017年7月,Gitlab 就计划将弃用对 MySQL 的支持.而目前这个决定将从 12.1 版本开始. 编辑注: ...

  6. RTT学习之SPI设备

    SPI分为主.从.设备:具体又分标准SPI/DUAL SPI/QUAD SPI(用80字节的RAMrt_err_t rt_spi_take_bus(struct rt_spi_device *devi ...

  7. #pg学习#postgresql的安装

    1.按照官网给的步骤编译安装(Mac安装是比较容易的,相比Liunx) cd /Users/renlipeng/Desktop/postgresql-9.5.1 ./configure --prefi ...

  8. PostgreSQL的hook机制初步学习

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面:PostgreSQL内部结构与源代码研究索引页    回到顶级页面:PostgreSQL索引页 本文的目的一是为了备忘,二是为了抛砖引玉,希望 ...

  9. PostgreSQL学习之【用户权限管理】说明

    背景 最近在学习PostgreSQL,看了用户权限管理文档,涉及到的知识点比较多,顺便写篇文章进行整理并不定时更新,也方便自己后续进行查阅. 说明 注意:创建好用户(角色)之后需要连接的话,还需要修改 ...

随机推荐

  1. js笔记(3)--js实现数组转置(两种方法)

      js实现数组转置   第一种方法:   <script>     window.onload=function(){     var array1=[[11,22,33,333],[4 ...

  2. shell正则表达式提取数字

    grep 提取数字 grep -Po "\d+\.\d+"

  3. 【限时免费】近1000G JAVA学习视频下载

    2020的情人节是个极特殊的情人节,面对肆虐的疫情,我们无法出门,宅在家里,也无法阻止你作为一名优秀程序员的梦想. 或许没有鲜花.没有蛋糕…… 姜小白就为大家备好了一份大礼,将自己近几年整理收藏的全网 ...

  4. JVM垃圾回收详解

    通常,我们在写java程序的时候,似乎很少关注内存分配和垃圾回收的问题.因为,这部分工作,JVM已经帮我们自动实现了. 这样看起来,好像很美好,但是任何事情都有两面性.虽然JVM会自动的进行垃圾回收, ...

  5. java程序设计原则知多少

    程序设计七大原则 一.开闭原则 ​ 针对我们设计的功能模块对扩展开放,对修改关闭:利用面向接口(抽象)编程(多态的特性),实现对功能需求扩展的同时,不允许更改原来的代码.提高对象的可复用性.可维护性. ...

  6. STM32F4相关

    常用术语 AHB与APB的地位相当于PC中的南北桥,是两道独立的片内总线.AHB:advanced high-performance bus:APB: advanced peripherals bus

  7. 风物长宜放眼量,人间正道是沧桑 - 一位北美 IT 技术人破局

    引言 我对于本科时光的印象,还停留在那所普通 211 大学的建筑物之间,我坐在大学的时光长廊里,满眼望去,都是经历的过的故事.可毕业后回首,却很少有人能说,自己从来没有迷茫过.迷茫,仿佛就是一团乌云, ...

  8. 第二篇 Springboot mybatis generate根据数据库表自动生成实体类、Mapper和Mapper.xml

    源码链接:https://pan.baidu.com/s/1iP4UguBufHbcIEv4Ux4wDw 提取码:j6z9 目录结构如下:只需增加一个generatorConfig.xml文件和在po ...

  9. 解释为什么wait()和notify(), notifyAll()要放在同步块中

    首先,wait()是释放锁的,因此wait()之前要先获得锁,而锁在同步块开始的时候获得,结束时释放,即同步块内为持有锁的阶段. 那为什么要设计同步块呢?或者说没有同步块会怎样呢?

  10. pyHamcrest

    概念 Hamcrest是用于编写匹配器对象的框架.他提供了一套匹配符Matcher,这些匹配符更接近自然语言,可读性高,更加灵活.Hamcrest还有很好的可扩展性,能够创建自定义的匹配器. 支持语言 ...