Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Berkeley DB: replacer des clés

6 réponses
Avatar
manu
Bonjour

Problème: je parcours une base DB avec la methode seq et je veux
modifier les clés de chaque enregistrement. Pour ca je fait un put avec
l'option R_CURSOR, mais visiblement ca tourne en rond.

Voici un petit programme illustrant le problème (enfin la je ne modifie
pas la clé mais les données de l'enregistrement, mais l'idée est la
même)

#include <stdio.h>
#include <fcntl.h>mp/dbtest.db");
#include <errno.h>
#include <err.h>
#include <db.h>

int
main(void) {
DB *db;
DBT key, rec;
struct data data;
int opt, res;
int finished = 0;

unlink("/tmp/dbtest.db");

if ((db = dbopen("/tmp/dbtest.db", O_RDWR|O_EXLOCK|O_CREAT,
0644, DB_BTREE, NULL)) == NULL)
err(errno, "dbopen failed");

key.data = "test1";
key.size = strlen(key.data) + 1;
rec.data = "data test1";
rec.size = strlen(rec.data) + 1;

if (db->put(db, &key, &rec, 0) != 0)
err(errno, "db->put failed");

key.data = "test2";
key.size = strlen(key.data) + 1;
rec.data = "data test2";
rec.size = strlen(rec.data) + 1;

if (db->put(db, &key, &rec, 0) != 0)
err(errno, "db->put failed");

opt = R_FIRST;
while (!finished) {
res = db->seq(db, &key, &rec, opt);
opt = R_NEXT;

switch(res) {
case 0: /* found */
printf("key = \"%s\", rec = \"%s\"\n",
key.data, rec.data);

rec.data = "changed data";
rec.size = strlen(rec.data) + 1;

if (db->put(db, &key, &rec, R_CURSOR) != 0)
err(errno, "db->put failed");

break;

case 1: /* finished */
finished = 1;
break;

case -1:
default:
err(errno, "db->seq failed");
finished = 1;
break;
}
}

db->close(db);

return 0;
}

A l'execution:
key = "test1", rec = "data test1"
key = "test2", rec = "changed data"
key = "test2", rec = "data test2"
key = "test2", rec = "changed data"
key = "test2", rec = "changed data"
key = "test2", rec = "changed data"
(et ca boucle)
--
Emmanuel Dreyfus
Un bouquin en français sur BSD:
http://www.eyrolles.com/php.informatique/Ouvrages/9782212112443.php3
manu@netbsd.org

6 réponses

Avatar
DINH Viêt Hoà

Problème: je parcours une base DB avec la methode seq et je veux
modifier les clés de chaque enregistrement. Pour ca je fait un put avec
l'option R_CURSOR, mais visiblement ca tourne en rond.

Voici un petit programme illustrant le problème (enfin la je ne modifie
pas la clé mais les données de l'enregistrement, mais l'idée est la
même)


Problème : tu as une structure de données sur laquelle tu itères et tu
modifies en même temps le contenu.

solution : stocker la liste des clefs dans une liste et itérer sur
cette liste.

--
DINH V. Hoa,

"ben le problème c'est que les voitures à motorisations XXL
ça passe rarement inaperçu" -- raoul

Avatar
manu
DINH Viêt Hoà wrote:

Problème: je parcours une base DB avec la methode seq et je veux
modifier les clés de chaque enregistrement. Pour ca je fait un put avec
l'option R_CURSOR, mais visiblement ca tourne en rond.

Voici un petit programme illustrant le problème (enfin la je ne modifie
pas la clé mais les données de l'enregistrement, mais l'idée est la
même)


Problème : tu as une structure de données sur laquelle tu itères et tu
modifies en même temps le contenu.


Ben justement ca me paraissait ok: j'itère et je modifie l'entrée
courrante. Mais visiblement un put en R_CURSOR déplace le curseur?

solution : stocker la liste des clefs dans une liste et itérer sur
cette liste.


Je dois modifier toutes les clés, donc ca n'est pas très pratique. Ou
alors je réouvre une autre base, et une fois fini je vire l'ancienne et
je renomme.

--
Emmanuel Dreyfus
Publicité subliminale: achetez ce livre!
http://www.eyrolles.com/php.informatique/Ouvrages/9782212112443.php3



Avatar
Laurent Wacrenier
Emmanuel Dreyfus écrit:
res = db->seq(db, &key, &rec, opt);


Il faut que le curseur soit initialisé, essaye :

res = db->seq(db, &key, &rec, opt&R_CURSOR);

Je ne suis pas sûr que ça marche si l'ordre des clef change.

Avatar
manu
Laurent Wacrenier wrote:

Il faut que le curseur soit initialisé, essaye :

res = db->seq(db, &key, &rec, opt&R_CURSOR);


Ca ne change pas grand chose. Mais R_FIRST est censé l'initialiser, en
principe...

--
Emmanuel Dreyfus
Publicité subliminale: achetez ce livre!
http://www.eyrolles.com/php.informatique/Ouvrages/9782212112443.php3


Avatar
DINH Viêt Hoà

solution : stocker la liste des clefs dans une liste et itérer sur
cette liste.


Je dois modifier toutes les clés, donc ca n'est pas très pratique. Ou
alors je réouvre une autre base, et une fois fini je vire l'ancienne et
je renomme.


Cette liste peut prendre beaucoup d'espace mémoire ?

Si oui, tu peux la stocker dans une autre base berkeley DB ?

--
DINH V. Hoa,

"ben le problème c'est que les voitures à motorisations XXL
ça passe rarement inaperçu" -- raoul


Avatar
DINH Viêt Hoà

Ben justement ca me paraissait ok: j'itère et je modifie l'entrée
courrante. Mais visiblement un put en R_CURSOR déplace le curseur?


Sinon, pour rerépondre, j'utilisais la chose suivante :

<<
int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
chash * exist)
{
DB * dbp;
int r;
DBT db_key;
DBT db_data;

dbp = cache_db->internal_database;

r = dbp->seq(dbp, &db_key, &db_data, R_FIRST);
if (r == -1)
return r;

while (r == 0) {
chashdatum hash_key;
chashdatum hash_data;

hash_key.data = db_key.data;
hash_key.len = db_key.size;

r = chash_get(exist, &hash_key, &hash_data);
if (r < 0) {
r = dbp->del(dbp, &db_key, 0);
if (r != 0)
return r;
}

r = dbp->seq(dbp, &db_key, &db_data, R_NEXT);
if (r == -1)
return r;
}

return 0;
}




sachant que j'ouvre en BTREE et que chash est une simple structure de
table de hachage.

Cela fonctionnait très bien.

--
DINH V. Hoa,

"ben le problème c'est que les voitures à motorisations XXL
ça passe rarement inaperçu" -- raoul