BerkeleyDB Db->使用自定义比较函数时无法工作
BerkeleyDB Db->get not working when using custom comparison function
在 C++ 程序中,我尝试使用 Db::set_bt_function
成员函数(DB 作为 BTREE 类型打开)为 Berkeley DB 设置自定义比较函数。当我不更改比较函数时,我的代码工作正常;我可以使用 Db::put
和 Db::get
.
放置和获取 keys/values
为了尝试 set_bt_function
方法,我定义了自己的 "lexicographic comparison" 如下:
int compkeys(Db *db, const Dbt *dbt1, const Dbt *dbt2, size_t *locp) {
size_t s = dbt1->get_size() > dbt2->get_size() ? dbt2->get_size() : dbt1->get_size();
int c = std::memcmp(dbt1->get_data(), dbt2->get_data(), s);
if(c != 0) return c;
if(dbt1->get_size() < dbt2->get_size()) return -1;
if(dbt1->get_size() > dbt2->get_size()) return 1;
return 0;
}
因此,当比较函数未更改时,这应该导致与我的参考代码完全相同的行为,因为默认情况下 Berkeley DB 使用词典顺序。
然而,当使用此比较功能时,Db::get
不再起作用。它returns-30999(DB_BUFFER_SMALL).
这是我为获取与给定键关联的值所做的工作:
Db* _dbm = ... /* DB is open */
std::vector<char> mykey;
... /* mykey is set to some content */
Dbt db_key((void*)(mykey.data()), uint32_t(mykey.size()));
Dbt db_data;
db_key.set_flags(DB_DBT_USERMEM);
db_data.set_flags(DB_DBT_MALLOC);
int status = _dbm->get(NULL, &db_key, &db_data, 0);
... /* check status, do something with db_data */
free(db_data.get_data());
知道为什么这段代码在我没有设置比较函数时有效,而在我设置时却不起作用吗?
注意:如果我使用游标 (Dbc::get
) 访问 key/values,则不会出现此问题。
本例中的 DB_BUFFER_SMALL
错误是在抱怨您的 db_key Dbt
。您需要调用 db_key.set_ulen(uint32_t(mykey.size()))
来告诉 BDB 您分配了多少 space 来保存从数据库中出来的密钥。
当您使用自定义比较函数时,事情会变得有点奇怪。您可以在不属于比较的键中包含数据 - 而不是在您传递给 get()
的键中。因此,BDB returns 它在您的 db_key.
数据库中找到的密钥
设置 ulen
时,使其足够大以容纳可以从数据库返回的任何密钥。您可能会发现,只在堆栈上保留一个 char
数组来处理此键 in/out 行为会更明智。
在 C++ 程序中,我尝试使用 Db::set_bt_function
成员函数(DB 作为 BTREE 类型打开)为 Berkeley DB 设置自定义比较函数。当我不更改比较函数时,我的代码工作正常;我可以使用 Db::put
和 Db::get
.
为了尝试 set_bt_function
方法,我定义了自己的 "lexicographic comparison" 如下:
int compkeys(Db *db, const Dbt *dbt1, const Dbt *dbt2, size_t *locp) {
size_t s = dbt1->get_size() > dbt2->get_size() ? dbt2->get_size() : dbt1->get_size();
int c = std::memcmp(dbt1->get_data(), dbt2->get_data(), s);
if(c != 0) return c;
if(dbt1->get_size() < dbt2->get_size()) return -1;
if(dbt1->get_size() > dbt2->get_size()) return 1;
return 0;
}
因此,当比较函数未更改时,这应该导致与我的参考代码完全相同的行为,因为默认情况下 Berkeley DB 使用词典顺序。
然而,当使用此比较功能时,Db::get
不再起作用。它returns-30999(DB_BUFFER_SMALL).
这是我为获取与给定键关联的值所做的工作:
Db* _dbm = ... /* DB is open */
std::vector<char> mykey;
... /* mykey is set to some content */
Dbt db_key((void*)(mykey.data()), uint32_t(mykey.size()));
Dbt db_data;
db_key.set_flags(DB_DBT_USERMEM);
db_data.set_flags(DB_DBT_MALLOC);
int status = _dbm->get(NULL, &db_key, &db_data, 0);
... /* check status, do something with db_data */
free(db_data.get_data());
知道为什么这段代码在我没有设置比较函数时有效,而在我设置时却不起作用吗?
注意:如果我使用游标 (Dbc::get
) 访问 key/values,则不会出现此问题。
本例中的 DB_BUFFER_SMALL
错误是在抱怨您的 db_key Dbt
。您需要调用 db_key.set_ulen(uint32_t(mykey.size()))
来告诉 BDB 您分配了多少 space 来保存从数据库中出来的密钥。
当您使用自定义比较函数时,事情会变得有点奇怪。您可以在不属于比较的键中包含数据 - 而不是在您传递给 get()
的键中。因此,BDB returns 它在您的 db_key.
设置 ulen
时,使其足够大以容纳可以从数据库返回的任何密钥。您可能会发现,只在堆栈上保留一个 char
数组来处理此键 in/out 行为会更明智。