版权声明: https://blog.csdn.net/qccz123456/article/details/82110201
pmemobj中具有事务的操作,事务的意思是被指定的一系列的操作要么执行成功,要么就失败,其中某一步错误也是失败。所以可以通过状态转换来完成失败函数的资源回收。
采用如下5个状态表示TX_BEGIN(pop)、TX_ONCOMMIT、TX_ONABORT 、TX_FINALLY、TX_END,并这5个状态之间的转换关系如下,可通过pmemobj_tx_abort()等函数强行跳转。
#include <stdlib.h>
#include <stdio.h>
#include <libpmemobj.h>
int main(int argc, const char *argv[])
{
const char path[] = "/home/hostname/pmemobj_setjmp.003";
PMEMobjpool *pop = pmemobj_create(path, setjmp_example, PMEMOBJ_MIN_POOL, 0666);
if (pop == NULL) {
perror(path);
exit(1);
}
TX_BEGIN(pop) {
printf("begin\n");
} TX_ONCOMMIT {
printf("oncommit\n");
} TX_ONABORT {
printf("onabort\n");
} TX_FINALLY {
printf("finally\n");
} TX_END
printf("end\n");
printf("\n");
TX_BEGIN(pop) {
printf("begin\n");
pmemobj_tx_abort(EINVAL);
} TX_ONCOMMIT {
printf("oncommit\n");
} TX_ONABORT {
printf("onabort\n");
} TX_FINALLY {
printf("finally\n");
} TX_END
printf("end\n");
printf("\n");
TX_BEGIN(pop) {
printf("begini b\n");
TX_BEGIN(pop) {
printf("begin\n");
} TX_ONCOMMIT {
printf("oncommit\n");
} TX_ONABORT {
printf("onabort\n");
} TX_FINALLY {
printf("finally\n");
} TX_END
printf("end\n");
} TX_END
printf("end b\n");
printf("\n");
TX_BEGIN(pop) {
printf("begin b\n");
TX_BEGIN(pop) {
printf("begin\n");
pmemobj_tx_abort(EINVAL);
} TX_ONCOMMIT {
printf("oncommit\n");
} TX_ONABORT {
printf("onabort\n");
} TX_FINALLY {
printf("finally\n");
} TX_END
printf("end\n");
} TX_END
printf("end b\n");
printf("\n");
pmemobj_close(pop);
return 0;
}
运行结果如下,特别需要强调的是如果进入了TX_ONABORT,则就会跳到上一层TX_END处,并且特性需要主要多层事务嵌套的逻辑关系:
$ ./setjmp
begin
oncommit
finally
end
begin
onabort
finally
end
begini b
begin
oncommit
finally
end
end b
begin b
begin
onabort
finally
end b
以上说明的是事务逻辑,并不方便操作persist数据,可采用事务函数处理persist数据,如操作失败,操作会回滚:
pmemobj_tx_add_range(PMEMoid, offset, size) 将PMEMoid指针处,偏移offset个偏移量后,大小为size的空间,作为事务操作。
pmemobj_tx_add_range_direct(ptr, size) 将ptr指针处,size大小的空间,作为事务操作。
int *to_modify = &vectorp->x;
TX_BEGIN(pop) {
pmemobj_tx_add_range(root, offsetof(struct vector, x), sizeof(int));
vectorp->x = 5;
pmemobj_tx_add_range(root, 0, sizeof (struct vector));
vectorp->x = 5;
vectorp->y = 10;
vectorp->z = 15;
pmemobj_tx_add_range_direct(to_modify, sizeof (int));
*to_modify = 5;
} TX_END