В программе на C ++ я пытаюсь установить пользовательскую функцию сравнения для БД Berkeley, используя Db::set_bt_function
функция-член (БД открывается как тип BTREE). Мой код работает нормально, когда я не меняю функцию сравнения; Я могу поставить и получить ключи / значения, используя Db::put
а также Db::get
,
Чтобы попробовать set_bt_function
Методом я определил свое собственное «лексикографическое сравнение» следующим образом:
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
больше не работает Возвращает -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
У меня нет этой проблемы.
DB_BUFFER_SMALL
ошибка в этом случае жалуется на ваш db_key Dbt
, Вам нужно позвонить db_key.set_ulen(uint32_t(mykey.size()))
сообщить BDB, сколько места вы выделили для хранения ключей, которые выходят из базы данных.
Все становится немного страннее, когда вы используете пользовательскую функцию сравнения. Вы можете иметь данные в ключе, который не является частью сравнения — и не в ключе, который вы передали get()
, По этой причине BDB возвращает ключ, найденный в базе данных в вашем ключе db_key.
При настройке ulen
сделайте его достаточно большим, чтобы вместить любой ключ, который может вернуться из базы данных. Вы можете обнаружить, что разумнее просто держать char
массив в стеке, чтобы иметь дело с этим ключом вход / выход поведение.
Других решений пока нет …