我正在使用tdb来尝试熟悉Linux上C语言的数据库管理。每tdb的描述
tdb是一个简单的数据库。 在概念上,它非常类似于GDBM和BSD的DB ,只不过它允许多个同时编写器,并且使用内部锁定来防止编写人员践踏彼此的。tdb也非常小。接口 该接口与gdbm非常类似,但有以下情况:
使用tdb的一个一般规则是调用方释放任何返回的TDB_DATA结构。只需调用free(p.dptr)释放名为p的TDB_DATA返回值,这与gdbm相同。
现在我想做一个小的测试程序来测试对我的数据库的多个写连接。但失败了。
#include <tdb.h>
int main(int argc, char** argv) {
struct tdb_context * tdb = tdb_open("test.tdb", 0, 0,
O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
if(!tdb){
printf("%s\n", tdb_errorstr(tdb));
} else {
printf("Database successfully opened!\n");
}
struct tdb_context * anothertdb = tdb_open("test.tdb", 0, 0,
O_RDWR| O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP); //why does this fail?
if(!anothertdb){
printf("%s\n", tdb_errorstr(anothertdb));
} else {
printf("Another reader successfully opened!\n");
}
if(tdb_close(anothertdb)){
printf("Error while closing database!\n");
} else {
printf("closing anothertdb-connection\n");
}
if(tdb_close(tdb)){
printf("Error while closing database!\n");
} else {
printf("closing tdb-connection\n");
}
return 0;
}产出如下:
Database successfully opened!
RUN FINISHED; Segmentation fault; core dumped; real time: 240ms; user: 0ms; system: 20ms如果我只打开到数据库的单个连接,就没有问题。如何在数据库上打开多个阅读器?
发布于 2021-07-28 01:58:08
第一个问题是在tdb_errorstring失败后调用tdb_open:
if(!anothertdb){
printf("%s\n", tdb_errorstr(anothertdb));
}这可能并不明显,但我们有充分的理由怀疑它不能工作,因为在调用anothertdb时,tdb_errorstr肯定是NULL,假定tdb_errorstr的论点必须是指向struct tdb_context的有效指针是合理的。事实上,这是真的;实际上,tdb_errorstring做的第一件事就是试图取消引用它的参数,以提取最后的错误代码。
简而言之,无法从tdb_open失败的结果中提取自定义错误字符串;您所能做的就是对来自fopen():call perror()的NULL返回所做的操作,希望errno将被设置为有意义的东西。如果这样做,您将看到一条错误消息,而不是崩溃:
$ ./tdb_test
Database successfully opened!
open 2: Device or resource busy库似乎有一种将tdb_open错误发送到已配置日志系统的方法,但是默认配置的日志系统只是抛出错误调用而不做任何操作。我没有阅读文档来查看是否有关于如何配置记录器的描述;您可能需要了解这一点。
顺便说一句,我不是在为这个API设计辩护。只是报告而已。
好的,接下来是您的实际问题:如何打开到TDB数据库的多个连接?答案是,你必须通过多个过程来完成这个任务。一个单独的进程可以打开任意数量的TDB,但是它只能打开其中的每一个(一次)。根据源代码中的一条注释,这是fcntl()锁定工作方式的结果,对我来说这似乎是一个合理的解释。
因此,如果您想尝试一个多读取器、多作者方案,您必须运行多个进程,或者从父进程中分送多个子进程。线程无法工作,因为同一个进程中的两个线程也不能打开相同的TDB。每个过程都是开放的。
另外,如果您选择分叉多个子进程,请记住,只需要在分叉之后调用tdb_open,因为如果您在父进程中打开一个TDB,它仍将在子进程中打开。
最后请注意,请养成将警告和错误消息写入stderr的习惯,这通常不会被缓冲,这样您在输出错误消息时就更有可能出现错误消息,而不是稍后stdio库选择刷新stdout输出缓冲区的时候。这实际上不是一个问题,但可能是这样的,因此您最好使用stderr来实现这个目的(这是它的目的,因此也就是它的名称)。
https://stackoverflow.com/questions/68553141
复制相似问题