2 * $Id: cnid_open.c,v 1.54 2003-07-10 13:50:39 rlewczuk Exp $
4 * Copyright (c) 1999. Adrian Sun (asun@zoology.washington.edu)
5 * All Rights Reserved. See COPYRIGHT.
7 * CNID database support.
10 * 1) afpd already caches did's.
11 * 2) the database stores cnid's as both did/name and dev/ino pairs.
12 * 3) RootInfo holds the value of the NextID.
13 * 4) the cnid database gets called in the following manner --
15 * cnid = cnid_open(root_dir);
18 * newid = cnid_add(cnid, dev, ino, parent did,
19 * name, id); id is a hint for a specific id. pass 0 if you don't
20 * care. if the id is already assigned, you won't get what you
23 * given an id, get a did/name and dev/ino pair.
24 * name = cnid_get(cnid, &id); given an id, return the corresponding
26 * return code = cnid_delete(cnid, id); delete an entry.
28 * with AFP, CNIDs 0-2 have special meanings. here they are:
30 * 1 -- parent of root directory (handled by afpd)
31 * 2 -- root directory (handled by afpd)
33 * CNIDs 4-16 are reserved according to page 31 of the AFP 3.0 spec so,
34 * CNID_START begins at 17.
39 #endif /* HAVE_CONFIG_H */
47 #endif /* HAVE_UNISTD_H */
50 #endif /* HAVE_FCNTL_H */
51 #include <sys/param.h>
53 #include <atalk/logger.h>
54 #ifdef HAVE_SYS_TIME_H
56 #endif /* HAVE_SYS_TIME_H */
60 #include <atalk/adouble.h>
61 #include <atalk/cnid.h>
62 #include <atalk/util.h>
64 #include "cnid_private.h"
67 #define MIN(a, b) ((a) < (b) ? (a) : (b))
71 #define MAX(a, b) ((a) > (b) ? (a) : (b))
75 #define DBHOME ".AppleDB"
76 #define DBCNID "cnid.db"
77 #define DBDEVINO "devino.db"
78 #define DBDIDNAME "didname.db" /* did/full name mapping */
79 #define DBMANGLE "mangle.db" /* filename mangling */
80 #define DBLOCKFILE "cnid.lock"
81 #define DBRECOVERFILE "cnid.dbrecover"
82 #define DBCLOSEFILE "cnid.close"
87 /* we version the did/name database so that we can change the format
88 * if necessary. the key is in the form of a did/name pair. in this case,
90 #define DBVERSION_KEY "\0\0\0\0\0"
91 #define DBVERSION_KEYLEN 5
92 #define DBVERSION1 0x00000001U
93 #define DBVERSION DBVERSION1
96 #define DBOPTIONS (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL)
97 #else /* !CNID_DB_CDB */
98 #if DB_VERSION_MAJOR >= 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 1)
99 #define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
100 DB_INIT_LOG | DB_INIT_TXN)
101 #else /* DB_VERSION_MINOR < 1 */
102 /*#define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
103 DB_INIT_LOG | DB_INIT_TXN | DB_TXN_NOSYNC)*/
104 #define DBOPTIONS (DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | \
105 DB_INIT_LOG | DB_INIT_TXN)
106 #endif /* DB_VERSION_MINOR */
107 #endif /* CNID_DB_CDB */
110 /* Let's try and use the youngest lock detector if present.
111 * If we can't do that, then let BDB use its default deadlock detector. */
112 #if defined DB_LOCK_YOUNGEST
113 #define DEAD_LOCK_DETECT DB_LOCK_YOUNGEST
114 #else /* DB_LOCK_YOUNGEST */
115 #define DEAD_LOCK_DETECT DB_LOCK_DEFAULT
116 #endif /* DB_LOCK_YOUNGEST */
117 #endif /* CNID_DB_CDB */
119 static cnid_t cnid_rebuild (CNID_private *, mode_t);
120 static int cnid_recover (char *, mode_t);
122 #define MAXITER 0xFFFF /* maximum number of simultaneously open CNID
125 /* -----------------------
126 * bandaid for LanTest performance pb.
128 static int my_yield(void)
135 ret = select(0, NULL, NULL, NULL, &t);
139 /* --------------- */
140 static int my_open(DB *p, const char *f, const char *d, DBTYPE t, u_int32_t flags, int mode)
142 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
143 return p->open(p, NULL, f, d, t, flags, mode);
145 return p->open(p, f, d, t, flags, mode);
149 void *cnid_open(const char *dir, mode_t mask) {
152 char path[MAXPATHLEN + 1];
158 int can_check = 0, require_rebuild = 0;
159 u_int32_t ncnid, ndidname, ndevino;
161 static int first = 0;
163 ncnid = ndidname = ndevino = 0;
170 /* this checks .AppleDB */
171 if ((len = strlen(dir)) > (MAXPATHLEN - DBLEN - 1)) {
172 LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", dir);
176 if ((db = (CNID_private *)calloc(1, sizeof(CNID_private))) == NULL) {
177 LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
181 db->magic = CNID_DB_MAGIC;
184 if (path[len - 1] != '/') {
189 strcpy(path + len, DBHOME);
190 if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~mask) < 0)) {
191 LOG(log_error, logtype_default, "cnid_open: DBHOME mkdir failed for %s", path);
195 lock.l_type = F_WRLCK;
196 lock.l_whence = SEEK_SET;
197 /* Make sure cnid.lock goes in .AppleDB. */
201 strcat(path, DBLOCKFILE);
202 strcpy(db->lock_file, path);
203 if ( stat (path, &st) == 0)
206 if ((db->lockfd = open(path, O_RDWR | O_CREAT, 0666 & ~mask)) > -1) {
209 if (fcntl(db->lockfd, F_SETLK, &lock) < 0) {
210 /* Now try to get a shared lock */
211 lock.l_type = F_RDLCK;
213 while (fcntl(db->lockfd, F_SETLKW, &lock) < 0) {
214 if ( errno != EINTR )
220 /* We got an exclusive lock, so we're the first/only process accessing the database */
222 /* cnid.lock existed but we got an exclusive lock */
223 /* This means the previous afpd probably crashed */
224 /* or got terminated so we run recovery */
226 path[len + DBHOMELEN] = '\0';
227 if ( cnid_recover( path, mask) != 0)
231 /* We're the only process accesing the db, so lets do some constistency checks */
238 LOG(log_error, logtype_default, "cnid_open: Cannot open cnid.lock file in %s lock (lock failed)", path);
242 path[len + DBHOMELEN] = '\0';
243 open_flag = DB_CREATE;
245 /* We need to be able to open the database environment with full
246 * transaction, logging, and locking support if we ever hope to
247 * be a true multi-acess file server. */
248 if ((rc = db_env_create(&db->dbenv, 0)) != 0) {
249 LOG(log_error, logtype_default, "cnid_open: db_env_create: %s", db_strerror(rc));
253 if ((rc = db->dbenv->open(db->dbenv, path, DB_JOINENV, 0666 & ~mask)) !=0 &&
254 (rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~mask)) != 0) {
255 if (rc == DB_RUNRECOVERY) {
256 /* This is the mother of all errors. We _must_ fail here. */
257 LOG(log_error, logtype_default, "cnid_open: CATASTROPHIC ERROR opening database environment %s. Run db_recovery -c immediately", path);
261 /* We can't get a full transactional environment, so multi-access
262 * is out of the question. Let's assume a read-only environment,
263 * and try to at least get a shared memory pool. */
264 if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~mask)) != 0) {
265 /* Nope, not a MPOOL, either. Last-ditch effort: we'll try to
266 * open the environment with no flags. */
267 if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~mask)) != 0) {
268 LOG(log_error, logtype_default, "cnid_open: dbenv->open of %s failed: %s",
269 path, db_strerror(rc));
273 db->flags |= CNIDFLAG_DB_RO;
274 open_flag = DB_RDONLY;
275 LOG(log_info, logtype_default, "cnid_open: Obtained read-only database environment %s", path);
278 /* did/name reverse mapping. We use a BTree for this one. */
279 if ((rc = db_create(&db->db_didname, db->dbenv, 0)) != 0) {
280 LOG(log_error, logtype_default, "cnid_open: Failed to create did/name database: %s",
285 if ((rc = my_open(db->db_didname, DBDIDNAME, NULL, DB_HASH, open_flag, 0666 & ~mask))) {
286 LOG(log_error, logtype_default, "cnid_open: Failed to open did/name database: %s",
288 /* We leak some memory here, but otherwise sometime we run into a SIGSEGV in close */
289 db->db_didname = NULL;
298 /* Check for version. This way we can update the database if we need
299 * to change the format in any way. */
300 memset(&key, 0, sizeof(key));
301 memset(&data, 0, sizeof(data));
302 key.data = DBVERSION_KEY;
303 key.size = DBVERSION_KEYLEN;
305 if ((rc = db->db_didname->get(db->db_didname, NULL, &key, &data, 0)) != 0) {
308 u_int32_t version = htonl(DBVERSION);
310 data.data = &version;
311 data.size = sizeof(version);
313 if ((ret = db->db_didname->put(db->db_didname, NULL, &key, &data,
315 LOG(log_error, logtype_default, "cnid_open: Error putting new version: %s",
321 /* TODO In the future we might check for version number here. */
323 memcpy(&version, data.data, sizeof(version));
324 if (version != ntohl(DBVERSION)) {
329 /* dev/ino reverse mapping. Use a hash for this one. */
330 if ((rc = db_create(&db->db_devino, db->dbenv, 0)) != 0) {
331 LOG(log_error, logtype_default, "cnid_open: Failed to create dev/ino database: %s",
336 if ((rc = my_open(db->db_devino, DBDEVINO, NULL, DB_HASH, open_flag, 0666 & ~mask))) {
337 LOG(log_error, logtype_default, "cnid_open: Failed to open devino database: %s",
339 db->db_devino = NULL;
350 /* Main CNID database. Use a hash for this one. */
351 if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) {
352 LOG(log_error, logtype_default, "cnid_open: Failed to create cnid database: %s",
357 if ((rc = my_open(db->db_cnid, DBCNID, NULL, DB_HASH, open_flag, 0666 & ~mask))) {
358 LOG(log_error, logtype_default, "cnid_open: Failed to open cnid database: %s",
360 if ( require_rebuild )
361 LOG(log_error, logtype_default, "cnid_open: CNID Databases are corrupted beyond repair, your probably should delete all files in %s", path);
365 /* Check database consistency */
367 if ((db->db_didname) && ((rc = db->db_didname->stat(db->db_didname, &sp, 0)) != 0)) {
368 LOG(log_error, logtype_default, "cnid_open: Failed to stat did/macname database: %s",
373 ndidname = (sp->hash_nkeys > 2) ? sp->hash_nkeys-2 : 0;
377 if ((db->db_devino) && ((rc = db->db_devino->stat(db->db_devino, &sp, 0)) != 0)) {
378 LOG(log_error, logtype_default, "cnid_open: Failed to stat dev/ino database: %s",
383 ndevino = sp->hash_nkeys;
387 if ((rc = db->db_cnid->stat(db->db_cnid, &sp, 0)) != 0) {
388 LOG(log_error, logtype_default, "cnid_open: Failed to stat cnid database: %s",
390 LOG(log_error, logtype_default, "cnid_open: CNID Databases are corrupted beyond repair, your probably should delete all files in %s", path);
393 ncnid = sp->hash_nkeys;
395 if ( require_rebuild || ndidname != ncnid || ndevino != ncnid ) {
396 LOG(log_error, logtype_default, "cnid_open: databases corrupt, number of entries mismatch (didname: %u, devino: %u, cnid: %u)", ndidname, ndevino, ncnid);
397 if ( CNID_INVALID == cnid_rebuild(db, mask) )
400 /* now downgrade to a shared lock */
402 lock.l_type = F_RDLCK;
403 if (fcntl(db->lockfd, F_SETLK, &lock) < 0) {
404 LOG (log_error, logtype_default, "cnid_open: Cannot set shared lock");
410 /* filename mangling database. Use a hash for this one. */
411 if ((rc = db_create(&db->db_mangle, db->dbenv, 0)) != 0) {
412 LOG(log_error, logtype_default, "cnid_open: Failed to create mangle database: %s", db_strerror(rc));
416 if ((rc = my_open(db->db_mangle, DBMANGLE, NULL, DB_HASH, open_flag, 0666 & ~mask))) {
417 LOG(log_error, logtype_default, "cnid_open: Failed to open mangle database: %s", db_strerror(rc));
420 #endif /* FILE_MANGLING */
422 /* Print out the version of BDB we're linked against. only once */
425 LOG(log_info, logtype_default, "CNID DB initialized using %s", db_version(NULL, NULL, NULL));
428 db_env_set_func_yield(my_yield);
432 if (db->db_didname) db->db_didname->close(db->db_didname, 0);
433 if (db->db_devino) db->db_devino->close(db->db_devino, 0);
434 if (db->db_cnid) db->db_cnid->close(db->db_cnid, 0);
435 LOG(log_error, logtype_default, "cnid_open: Failed to setup CNID DB environment");
436 db->dbenv->close(db->dbenv, 0);
439 if (db->lockfd > -1 && !can_check ) {
441 (void)remove(db->lock_file);
452 /*-------------------------*/
454 static int cnid_recover(char *path, mode_t mask)
457 int open_flag = 0, rc = 0;
459 if ( !path || strlen(path) == 0)
462 LOG (log_info, logtype_default, "cnid_open: running recover on %s", path);
464 /* Remove any existing environment */
466 if ((rc = db_env_create(&dbenv, 0)) != 0) {
467 LOG(log_error, logtype_default, "cnid_recover: db_env_create: %s", db_strerror(rc));
470 if ((rc = dbenv->remove(dbenv, path, DB_FORCE)) != 0) {
471 LOG(log_error, logtype_default, "cnid_recover db_env_remove: %s", db_strerror(rc));
475 /* Create and open recover environment */
477 if ((rc = db_env_create(&dbenv, 0)) != 0) {
478 LOG(log_error, logtype_default, "cnid_recover: db_env_create: %s", db_strerror(rc));
482 open_flag = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_PRIVATE;
483 if ((rc = dbenv->open(dbenv, path, open_flag, 0666 & ~mask)) != 0) {
484 LOG (log_error, logtype_default, "cnid_recover: RECOVERY failed with %s", db_strerror(rc));
488 if ((rc = dbenv->close(dbenv, 0)) != 0) {
489 LOG(log_error, logtype_default, "cnid_recover: dbenv->close: %s", db_strerror(rc));
493 /* Remove recover environment */
495 if ((rc = db_env_create(&dbenv, 0)) != 0) {
496 LOG(log_error, logtype_default, "cnid_recover: db_env_create: %s", db_strerror(rc));
500 if ((rc = dbenv->remove(dbenv, path, DB_FORCE)) != 0) {
501 LOG(log_error, logtype_default, "cnid_recover: db_env_remove: %s", db_strerror(rc));
509 static cnid_t cnid_rebuild (CNID_private *db, mode_t mask)
515 DBT key, data, altkey, altdata, dupkey, dupdata;
517 cnid_t id, dupid, maxcnid = CNID_START;
521 static char buffer[MAXPATHLEN + CNID_HEADER_LEN + 1];
522 LOG(log_info, logtype_default, "starting rebuild of databases");
524 if ((rc = db->db_cnid->cursor(db->db_cnid, NULL, &cursor, DB_WRITECURSOR) ) != 0) {
525 LOG(log_error, logtype_default, "cnid_rebuild: Unable to get a cursor: %s", db_strerror(rc));
529 memset(&key, 0, sizeof(key));
530 memset(&data, 0, sizeof(data));
531 memset(&altkey, 0, sizeof(key));
532 memset(&altdata, 0, sizeof(data));
533 memset(&dupdata, 0, sizeof(dupdata));
534 memset(&dupkey, 0, sizeof(dupkey));
536 /* close didname and devino, then recreate them */
537 if (db->db_didname) db->db_didname->close(db->db_didname, 0);
538 if (db->db_devino) db->db_devino->close(db->db_devino, 0);
540 if ((rc = db_create(&db->db_didname, db->dbenv, 0)) != 0) {
541 LOG(log_error, logtype_default, "cnid_rebuild: Failed to recreate did/name database: %s",
546 if ((rc = my_open(db->db_didname, DBDIDNAME, NULL, DB_HASH, DB_CREATE|DB_TRUNCATE, 0666 & ~mask))) {
547 LOG(log_error, logtype_default, "cnid_rebuild: Failed to open did/name database: %s",
552 if ((rc = db_create(&db->db_devino, db->dbenv, 0)) != 0) {
553 LOG(log_error, logtype_default, "cnid_rebuild: Failed to recreate dev/ino database: %s",
558 if ((rc = my_open(db->db_devino, DBDEVINO, NULL, DB_HASH, DB_CREATE|DB_TRUNCATE, 0666 & ~mask))) {
559 LOG(log_error, logtype_default, "cnid_rebuild: Failed to open dev/ino database: %s",
564 db->db_devino->sync( db->db_devino, 0);
565 db->db_didname->sync( db->db_didname, 0);
568 /* now create the temporary cnid database */
569 if ((rc = db_create(&tmpdb, db->dbenv, 0)) != 0) {
570 LOG(log_error, logtype_default, "cnid_rebuild: Failed to create tmp database: %s",
575 if ((rc = my_open(tmpdb, DBRECOVERFILE, NULL, DB_HASH, DB_CREATE|DB_TRUNCATE, 0666 & ~mask))) {
576 LOG(log_error, logtype_default, "cnid_rebuild: Failed to open recover database: %s",
581 /* add rootinfo and version to didname */
583 key.data = ROOTINFO_KEY;
584 key.size = ROOTINFO_KEYLEN;
586 data.size = sizeof(id);
588 if ((rc = db->db_didname->put(db->db_didname, NULL, &key, &data, 0))) {
589 LOG(log_error, logtype_default, "cnid_rebuild: Error adding ROOTINFO: %s", db_strerror(rc));
593 memset(&key, 0, sizeof(key));
594 memset(&data, 0, sizeof(data));
595 key.data = DBVERSION_KEY;
596 key.size = DBVERSION_KEYLEN;
597 version = htonl(DBVERSION);
598 data.data = &version;
599 data.size = sizeof(version);
601 if ((rc = db->db_didname->put(db->db_didname, NULL, &key, &data, 0))) {
602 LOG(log_error, logtype_default, "cnid_rebuild: Error putting version: %s",
607 /* now recover the databases from cnid.db*/
609 memset(&key, 0, sizeof(key));
610 memset(&data, 0, sizeof(data));
612 data.ulen = MAXPATHLEN + CNID_HEADER_LEN +1;
613 data.flags = DB_DBT_USERMEM;
616 while ((rc = cursor->c_get(cursor, &key, &data, DB_NEXT)) == 0) {
617 memcpy ( &id, key.data, sizeof(id));
619 if ( id < CNID_START ) {
620 LOG(log_error, logtype_default, "cnid_rebuild: Dropping invalid entry with id: %u", id);
624 maxcnid = MAX( id, maxcnid);
626 /* check for duplicate cnid */
628 if ((rc = tmpdb->get(tmpdb, NULL, &key, &dupdata, 0))) {
629 if ( rc != DB_NOTFOUND ) {
630 LOG(log_error, logtype_default, "cnid_rebuild: Error getting entry from cnid: %s",
635 else /* duplicate cnid */
637 LOG(log_error, logtype_default, "cnid_rebuild: Dropping duplicate file entry: %u", id);
642 /* dev/ino database */
643 altkey.data = data.data;
644 altkey.size = CNID_DEVINO_LEN;
645 altdata.data = key.data;
646 altdata.size = key.size;
647 if ((rc = db->db_devino->put(db->db_devino, NULL, &altkey, &altdata, DB_NOOVERWRITE))) {
648 if ( rc != DB_KEYEXIST) {
649 LOG(log_error, logtype_default, "cnid_rebuild: Error adding entry %u to dev/ino: %s",
650 id, db_strerror(rc));
654 /* handle duplicate (file with 2 ids) */
656 dupkey.data = data.data;
657 dupkey.size = CNID_DEVINO_LEN;
658 if (( rc = db->db_devino->get(db->db_devino, NULL, &dupkey, &dupdata, 0))) {
659 LOG(log_error, logtype_default, "cnid_rebuild: Error getting entry from did/name: %s",
663 memcpy ( &dupid, dupdata.data, sizeof(id));
664 dupid = ntohl (dupid);
665 LOG(log_error, logtype_default, "cnid_rebuild: Dropping duplicate file entry: %u", MIN(id,dupid));
667 /* Use the entry with a higher cnid */
671 if ((rc = db->db_devino->put(db->db_devino, NULL, &altkey, &altdata, 0))) {
672 LOG(log_error, logtype_default, "cnid_rebuild: Error adding entry %u to dev/ino: %s",
673 id, db_strerror(rc));
678 /* did/name database */
679 altkey.data = (char *) data.data + CNID_DEVINO_LEN;
680 altkey.size = data.size - CNID_DEVINO_LEN;
681 if ((rc = db->db_didname->put(db->db_didname, NULL, &altkey, &altdata, 0))) {
682 LOG(log_error, logtype_default, "cnid_rebuild: Error adding entry to did/name: %s",
687 /* recover database */
689 if ((rc = tmpdb->put(tmpdb, NULL, &key, &data, 0))) {
690 LOG(log_error, logtype_default, "cnid_rebuild: Error adding entry to recoverdb: %s",
697 /* set ROOTINFO to maxcnid */
698 maxcnid = htonl(maxcnid);
699 key.data = ROOTINFO_KEY;
700 key.size = ROOTINFO_KEYLEN;
701 data.data = &maxcnid;
702 data.size = sizeof(maxcnid);
704 if ((rc = db->db_didname->put(db->db_didname, NULL, &key, &data, 0))) {
705 LOG (log_error, logtype_default, "cnid_rebuild: Failed to update ROOTINFO %s", db_strerror(rc));
709 /* delete cnid.db and rename cniddb.recover to cnid.db */
711 cursor->c_close(cursor);
712 db->db_cnid->close(db->db_cnid, 0);
714 if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) {
715 LOG(log_error, logtype_default, "cnid_rebuild: Failed to create database: %s", db_strerror(rc));
718 if ((rc = db->db_cnid->remove(db->db_cnid, DBCNID, NULL, 0)) != 0) {
719 LOG(log_error, logtype_default, "cnid_rebuild: Failed to remove database: %s", db_strerror(rc));
724 if ((rc = tmpdb->close(tmpdb, 0)) != 0) {
725 LOG(log_error, logtype_default, "cnid_rebuild: Failed to close database: %s", db_strerror(rc));
728 if ((rc = db_create(&tmpdb, db->dbenv, 0)) != 0) {
729 LOG(log_error, logtype_default, "cnid_rebuild: Failed to create database: %s", db_strerror(rc));
732 if ((rc = tmpdb->rename(tmpdb, DBRECOVERFILE, NULL, DBCNID, 0)) != 0) {
733 LOG(log_error, logtype_default, "cnid_rebuild: Rename database failed: %s", db_strerror(rc));
737 if ((rc = db_create(&db->db_cnid, db->dbenv, 0)) != 0) {
738 LOG(log_error, logtype_default, "cnid_rebuild: Failed to recreate cnid database: %s", db_strerror(rc));
742 if ((rc = my_open(db->db_cnid, DBCNID, NULL, DB_HASH, 0, 0666 & ~mask))) {
743 LOG(log_error, logtype_default, "cnid_rebuild: Failed to open cnid database: %s", db_strerror(rc));
747 db->db_devino->sync( db->db_devino, 0);
748 db->db_didname->sync( db->db_didname, 0);
749 db->db_cnid->sync( db->db_cnid, 0);
751 LOG (log_info, logtype_default, "cnid_rebuild: Recovered %u entries, database rebuild complete", countp);
755 cursor->c_close(cursor);
757 LOG (log_error, logtype_default, "cnid_rebuild: Database rebuild failed");