3 * $Id: cnid_db3_lookup.c,v 1.5 2009-10-29 13:38:16 didg Exp $
8 #endif /* HAVE_CONFIG_H */
10 #ifdef CNID_BACKEND_DB3
14 #include <sys/param.h>
16 #include <atalk/logger.h>
24 #include <netatalk/endian.h>
25 #include <atalk/adouble.h>
28 #include "cnid_db3_private.h"
30 #define LOGFILEMAX 100 /* kbytes */
31 #define CHECKTIMEMAX 30 /* minutes */
33 /* This returns the CNID corresponding to a particular file. It will
34 * also fix up the various databases if there's a problem. */
35 cnid_t cnid_db3_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, char *name, const size_t len)
39 DBT key, devdata, diddata;
40 int devino = 1, didname = 1;
44 if (!cdb || !(db = cdb->_private) || !st || !name) {
48 /* Do a little checkpointing if necessary. I stuck it here as cnid_lookup
49 * gets called when we do directory lookups. Only do this if we're using
50 * a read-write database. */
51 if ((db->flags & CNIDFLAG_DB_RO) == 0) {
53 LOG(log_debug9, logtype_default, "cnid_lookup: Running database checkpoint");
55 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
56 if ((rc = db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0))) {
57 LOG(log_error, logtype_default, "cnid_lookup: txn_checkpoint: %s", db_strerror(rc));
61 #if DB_VERSION_MAJOR >= 4
62 switch (rc = db->dbenv->txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
64 switch (rc = txn_checkpoint(db->dbenv, LOGFILEMAX, CHECKTIMEMAX, 0)) {
65 #endif /* DB_VERSION_MAJOR >= 4 */
70 LOG(log_error, logtype_default, "cnid_lookup: txn_checkpoint: %s", db_strerror(rc));
73 #endif /* DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1) */
76 if ((buf = make_cnid_data(st, did, name, len)) == NULL) {
77 LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
81 memset(&key, 0, sizeof(key));
82 memset(&devdata, 0, sizeof(devdata));
83 memset(&diddata, 0, sizeof(diddata));
85 /* Look for a CNID. We have two options: dev/ino or did/name. If we
86 * only get a match in one of them, that means a file has moved. */
88 key.size = CNID_DEVINO_LEN;
89 while ((rc = db->db_devino->get(db->db_devino, NULL, &key, &devdata, 0))) {
90 if (rc == DB_LOCK_DEADLOCK) {
94 if (rc == DB_NOTFOUND) {
99 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID dev %u, ino %u: %s",
100 st->st_dev, st->st_ino, db_strerror(rc));
105 key.data = buf + CNID_DEVINO_LEN;
106 key.size = CNID_DID_LEN + len + 1;
107 while ((rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0))) {
108 if (rc == DB_LOCK_DEADLOCK) {
112 if (rc == DB_NOTFOUND) {
117 LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID %u, name %s: %s",
118 ntohl(did), name, db_strerror(rc));
122 /* Set id. Honor did/name over dev/ino as dev/ino isn't necessarily
125 memcpy(&id, diddata.data, sizeof(id));
127 memcpy(&id, devdata.data, sizeof(id));
130 /* Either entries are in both databases or neither of them. */
131 if ((devino && didname) || !(devino || didname)) {
133 LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u", ntohl(did), name, ntohl(id));
138 /* Fix up the database. */
139 cnid_db3_update(cdb, id, st, did, name, len);
141 LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name,
148 #endif /* CNID_BACKEND_DB3 */