PQcancelCreate #准备一条可以发送取消请求的连接。
PGcancelConn *PQcancelCreate(PGconn *conn);
PQcancelCreate
创建一个
PGcancelConn
对象,
但它不会立即开始通过这条连接发送一个取消请求。
可以用
PQcancelBlocking
以阻塞的方式,
或者用
PQcancelStart
以非阻塞的方式,
通过这条连接发送一个取消请求。
返回值可以被传递给
PQcancelStatus
来检查
PGcancelConn
对象是否被成功创建。
这个
PGcancelConn
对象是一个不透明的结构,
不预期由应用程序直接访问。
这个
PGcancelConn
对象可以用于以线程安全的方式取消正在原始连接上运行的查询。
为取消请求建立连接时会复用原始客户端的许多连接参数。
重要的是,
如果原始连接要求对连接进行加密和/或验证目标主机
(使用 sslmode 或
gssencmode),
那么取消请求的连接也会以这些相同的要求建立。
不过,
只在身份验证期间或客户端身份验证之后使用的任何连接选项都会
被忽略,
因为取消请求不需要身份验证,
并且连接会在取消请求被提交之后立即关闭。
注意,当
PQcancelCreate
返回一个非空指针时,
在用完它之后你必须调用
PQcancelFinish,
以释放该结构及任何相关的内存块。
即使取消请求失败或被放弃,
也必须这样做。
PQcancelBlocking #以阻塞的方式请求服务器放弃对当前命令的处理。
int PQcancelBlocking(PGcancelConn *cancelConn);
请求通过给定的
PGcancelConn
发出,
它需要用
PQcancelCreate
创建。
如果取消请求被成功分派,
PQcancelBlocking
的返回值为 1,
否则为 0。
如果它不成功,
可以用
PQcancelErrorMessage
检索错误消息。
然而, 取消被成功分派并不保证该请求会产生任何效果。 如果取消是有效的, 被取消的命令将提前终止并返回一个错误结果。 如果取消失败 (例如因为服务器已经完成了对该命令的处理), 则完全不会有任何可见的结果。
PQcancelStartPQcancelPoll #以非阻塞的方式请求服务器放弃对当前命令的处理。
int PQcancelStart(PGcancelConn *cancelConn); PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn);
请求通过给定的
PGcancelConn
发出,
它需要用
PQcancelCreate
创建。
如果取消请求能够被启动,
PQcancelStart
的返回值为 1,
否则为 0。
如果它不成功,
可以用
PQcancelErrorMessage
检索错误消息。
如果 PQcancelStart
成功,
下一个阶段是轮询
libpq,
以便它能够继续取消连接序列。
使用
PQcancelSocket
来获得底层数据库连接套接字的描述符。
(注意:不要假定套接字在多次
PQcancelPoll
调用之间保持不变。)
像这样循环:
如果 PQcancelPoll(cancelConn)
上次返回了
PGRES_POLLING_READING,
则等待套接字准备好读取
(由 select()、
poll()
或类似的系统函数指示)。
然后再次调用
PQcancelPoll(cancelConn)。
反过来,
如果
PQcancelPoll(cancelConn)
上次返回了
PGRES_POLLING_WRITING,
则等待套接字准备好写入,
然后再次调用
PQcancelPoll(cancelConn)。
在第一次迭代时,
即如果你还没有调用过
PQcancelPoll(cancelConn),
则表现得好像它上次返回了
PGRES_POLLING_WRITING。
持续这个循环,
直到
PQcancelPoll(cancelConn)
返回
PGRES_POLLING_FAILED
(表示连接过程已失败),
或
PGRES_POLLING_OK
(表示取消请求被成功分派)。
然而, 取消被成功分派并不保证该请求会产生任何效果。 如果取消是有效的, 被取消的命令将提前终止并返回一个错误结果。 如果取消失败 (例如因为服务器已经完成了对该命令的处理), 则完全不会有任何可见的结果。
在连接期间的任何时刻,
都可以通过调用
PQcancelStatus
来检查连接的状态。
如果这个调用返回
CONNECTION_BAD,
那么取消过程已失败;
如果这个调用返回
CONNECTION_OK,
那么取消请求被成功分派。
这两种状态都可以从
PQcancelPoll
的返回值同样检测出来
(如上文所述)。
其他状态也可能出现
(并且只出现在)
异步连接过程期间。
它们指示连接过程的当前阶段,
并且可能有助于向用户提供反馈等。
这些状态是:
CONNECTION_ALLOCATED #
等待对
PQcancelStart 或
PQcancelBlocking
的调用,
以实际打开套接字。
这是在调用
PQcancelCreate
或
PQcancelReset
之后的连接状态。
此时还没有发起任何到服务器的连接。
要实际开始发送取消请求,
请使用
PQcancelStart 或
PQcancelBlocking。
CONNECTION_STARTED #等待建立连接。
CONNECTION_MADE #连接正常;等待发送。
CONNECTION_AWAITING_RESPONSE #等待来自服务器的响应。
CONNECTION_SSL_STARTUP #Negotiating SSL encryption.
CONNECTION_GSS_STARTUP #Negotiating GSS encryption.
注意,虽然这些常量会保留 (为了保持兼容性), 但应用程序永远不应当依赖它们以某个特定顺序出现, 甚至不应当依赖它们出现, 也不应当依赖状态始终是这些已记录的值之一。 应用程序可能会这样做:
switch(PQcancelStatus(conn))
{
case CONNECTION_STARTED:
feedback = "Connecting...";
break;
case CONNECTION_MADE:
feedback = "Connected to server...";
break;
.
.
.
default:
feedback = "Connecting...";
}
在使用 PQcancelPoll 时,
connect_timeout
连接参数会被忽略;
判断是否已经过去了过多的时间是应用程序的责任。
否则,
PQcancelStart
加上一个
PQcancelPoll
循环等同于
PQcancelBlocking。
PQcancelStatus #返回取消连接的状态。
ConnStatusType PQcancelStatus(const PGcancelConn *cancelConn);
状态可以是许多值之一。
然而,
在异步取消过程之外只会看到其中的三个:
CONNECTION_ALLOCATED、
CONNECTION_OK 和
CONNECTION_BAD。
使用
PQcancelCreate
成功创建的一个
PGcancelConn
的初始状态是
CONNECTION_ALLOCATED。
被成功分派的取消请求具有状态
CONNECTION_OK。
一次失败的取消尝试由状态
CONNECTION_BAD
指示。
OK 状态会保持到
PQcancelFinish 或
PQcancelReset
被调用为止。
有关可能返回的其他状态码,
请参见
PQcancelStart
的条目。
然而, 取消被成功分派并不保证该请求会产生任何效果。 如果取消是有效的, 被取消的命令将提前终止并返回一个错误结果。 如果取消失败 (例如因为服务器已经完成了对该命令的处理), 则完全不会有任何可见的结果。
PQcancelSocket #获得到服务器的取消连接套接字的文件描述符编号。
int PQcancelSocket(const PGcancelConn *cancelConn);
一个有效的描述符将大于等于 0;
结果为 -1 表示当前没有打开的服务器连接。
当对本节中
PGcancelConn
的任何函数进行调用时
(
PQcancelErrorMessage
和 PQcancelSocket
本身除外),
这一点都可能改变。
PQcancelErrorMessage
#返回当前连接对象上发生的最近一次错误消息字符串。 an operation on the cancel connection.
char *PQcancelErrorMessage(const PGcancelConn *cancelconn);
几乎所有接受
PGcancelConn
的
libpq
函数在失败时都会为
PQcancelErrorMessage
设置一条消息。
注意,按照
libpq
的惯例,
一个非空的
PQcancelErrorMessage
结果可能由多行组成,
并且会包括一个结尾的换行符。
调用者不应当直接释放该结果。
当相关的
PGcancelConn
句柄被传递给
PQcancelFinish
时它会被释放。
不应当期望该结果字符串在
PGcancelConn
结构上的多次操作之间保持不变。
PQcancelFinish #
关闭取消连接
(如果它尚未完成取消请求的发送)。
同时释放
PGcancelConn
对象使用的内存。
void PQcancelFinish(PGcancelConn *cancelConn);
注意,即使取消尝试失败
(如
PQcancelStatus
所指示的那样),
应用程序也应当调用
PQcancelFinish
来释放
PGcancelConn
对象使用的内存。
在
PQcancelFinish
被调用之后,
不得再使用该
PGcancelConn
指针。
PQcancelReset #
重置这个
PGcancelConn,
使它可以被复用于一条新的取消连接。
void PQcancelReset(PGcancelConn *cancelConn);
如果这个
PGcancelConn
当前正被用于发送一个取消请求,
那么这条连接会被关闭。
随后它会准备好这个
PGcancelConn
对象,
使它可以被用于发送一个新的取消请求。
这可以用来为一个
PGconn
创建一个
PGcancelConn,
并在原始
PGconn
的整个生命周期内多次复用它。
这些函数代表发送取消请求的较老方法。
虽然它们仍然可以工作,
但它们已被弃用,
因为它们不以加密的方式发送取消请求,
即使原始连接指定了
sslmode 或
gssencmode
来要求加密也是如此。
因此,
强烈不鼓励在新代码中使用这些较老的方法,
并且建议把现有代码改为使用新函数。
PQgetCancel #
创建一个数据结构,
其中包含用
PQcancel
取消一条命令所需的信息。
PGcancel *PQgetCancel(PGconn *conn);
PQgetCancel
在给定一个
PGconn
连接对象的情况下创建一个
PGcancel
对象。
如果给定的
conn
为 NULL
或一条无效连接,
它将返回
NULL。
这个
PGcancel
对象是一个不透明的结构,
不预期由应用程序直接访问;
它只能被传递给
PQcancel
或
PQfreeCancel。
PQfreeCancel #
释放一个由
PQgetCancel
创建的数据结构。
void PQfreeCancel(PGcancel *cancel);
PQfreeCancel
释放一个先前由
PQgetCancel
创建的数据对象。
PQcancel #
PQcancel
是
PQcancelBlocking
的一个已弃用且不安全的变体,
但它可以从信号处理器内安全地使用。
int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize);
PQcancel
之所以存在只是出于向后兼容的原因。
应当改用
PQcancelBlocking。
PQcancel
唯一的好处是它可以从信号处理器中被安全地调用
(前提是
errbuf
是信号处理器中的一个局部变量)。
然而,
人们通常不认为这一点足以抵消这个函数存在的安全问题。
就 PQcancel
而言,
PGcancel
对象是只读的,
因此它也可以从一个与操纵
PGconn
对象的线程相分离的线程中被调用。
如果取消请求被成功分派,
PQcancel
的返回值为 1,
否则为 0。
如果不成功,
errbuf
会被填入一条解释性的错误消息。
errbuf
必须是一个大小为
errbufsize
的 char 数组
(推荐的大小为 256 字节)。
PQrequestCancel #
PQrequestCancel
是
PQcancelBlocking
的一个已弃用且不安全的变体。
int PQrequestCancel(PGconn *conn);
PQrequestCancel
之所以存在只是出于向后兼容的原因。
应当改用
PQcancelBlocking。
与
PQcancelBlocking
相比,
使用
PQrequestCancel
没有任何好处。
请求服务器放弃对当前命令的处理。
它直接在
PGconn
对象上操作,
并且在失败的情况下把错误消息存储在
PGconn
对象中
(可以通过
PQerrorMessage
检索它)。
虽然功能相同,
但这种方法在多线程程序或信号处理器中是不安全的,
因为覆盖
PGconn
的错误消息有可能破坏连接上当前正在进行的操作。