2 votes

BerkeleyDB Db->get ne fonctionne pas lors de l'utilisation d'une fonction de comparaison personnalisée

Dans un programme C++, j'essaie de définir une fonction de comparaison personnalisée pour une base de données Berkeley, à l'aide de la commande Db::set_bt_function (la BD est ouverte comme un type BTREE). Mon code fonctionne bien lorsque je ne modifie pas la fonction de comparaison ; je peux mettre et récupérer des clés/valeurs en utilisant la fonction Db::put y Db::get .

Pour essayer le set_bt_function j'ai défini ma propre "comparaison lexicographique" comme suit :

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;
}

Cela devrait donc conduire exactement au même comportement que mon code de référence, lorsque la fonction de comparaison n'est pas modifiée, puisque par défaut Berkeley DB utilise l'ordre lexicographique.

Pourtant, en utilisant cette fonction de comparaison, Db::get ne fonctionne plus. Il renvoie -30999 (DB_BUFFER_SMALL).

Voici ce que je fais pour obtenir la valeur associée à une clé donnée :

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());

Savez-vous pourquoi ce code fonctionne lorsque je ne configure pas la fonction de comparaison, et ne fonctionne pas lorsque je le fais ?

Remarque : si j'accède aux touches/valeurs en utilisant un curseur ( Dbc::get ) Je n'ai pas ce problème.

2voto

gubblebozer Points 512

El DB_BUFFER_SMALL erreur dans ce cas est de se plaindre de votre db_key Dbt . Vous devez appeler db_key.set_ulen(uint32_t(mykey.size())) pour indiquer à BDB l'espace que vous avez alloué pour contenir les clés qui proviennent de la base de données.

Les choses deviennent un peu plus étranges lorsque vous utilisez une fonction de comparaison personnalisée. Vous pouvez avoir des données dans la clé qui ne font pas partie de la comparaison - et pas dans la clé que vous avez transmise à get() . Pour cette raison, BDB renvoie la clé qu'elle a trouvée dans la base de données dans votre db_key.

Lors du réglage de la ulen pour qu'il soit assez grand pour contenir toutes les clés qui peuvent revenir de la base de données. Vous pouvez trouver qu'il est plus sain de garder juste un fichier char sur la pile pour gérer ce comportement d'entrée/sortie de clé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X