/*
- * $Id: cmd_dbd_lookup.c,v 1.1 2009-05-14 13:46:08 franklahm Exp $
+ * $Id: cmd_dbd_lookup.c,v 1.2 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Frank Lahm 2009
* All Rights Reserved. See COPYING.
#include "dbd.h"
#include "cmd_dbd.h"
+/*
+ ATTENTION:
+ whatever you change here, also change cmd_dbd_lookup.c !
+ cmd_dbd_lookup has an read-only mode, but besides that it's the same.
+ */
+
+
/* Pull these in from dbd_add.c */
extern int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply);
/*
* This returns the CNID corresponding to a particular file and logs any inconsitencies.
- * If roflags == 1 we only scan, if roflag == 0, we modify, but we do _not_ *add* as does
- * dbd_lookup.
+ * If roflags == 1 we only scan, if roflag == 0, we modify i.e. call dbd_update
+ * FIXME: realign this wih dbd_lookup.
*/
int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag)
return 1;
}
+ /*
+ Order matters for the next 2 ifs because both found a CNID but they didn't match.
+ So in order to pick the CNID from "didname" it must come after devino.
+ See test cases laid out in dbd_lookup.c.
+ */
+ if (devino) {
+ dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name);
+ rqst->cnid = id_devino;
+ if (type_devino != rqst->type) {
+ /* same dev/inode but not same type: it's an inode reused, delete the record */
+ if (! roflag)
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
+ return -1;
+ }
+ else {
+ update = 1;
+ }
+ }
if (didname) {
dbd_log( LOGSTD, "CNID resolve problem: changed dev/ino for '%s/%s'", cwdbuf, rqst->name);
rqst->cnid = id_didname;
If it's the same dev or not the same type, e.g. a remove followed by a new file
with the same name */
if (!memcmp(&dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
- type_didname != rqst->type) {
+ type_didname != rqst->type) {
if (! roflag)
- if (dbd_delete(dbd, rqst, rply) < 0)
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
return -1;
}
else {
}
}
- if (devino) {
- dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name);
- rqst->cnid = id_devino;
- if (type_devino != rqst->type) {
- /* same dev/inode but not same type: it's an inode reused, delete the record */
- if (! roflag)
- if (dbd_delete(dbd, rqst, rply) < 0)
- return -1;
- }
- else {
- update = 1;
- }
- }
if (!update || roflag) {
rply->result = CNID_DBD_RES_NOTFOUND;
return 1;
}
/*
- This is taken from dbd_add.c
+ This is taken from dbd_add.c, but this func really is only "add", dbd_add calls dbd_lookup
+ before adding.
+ FIXME: realign with dbd_add using e.g. using a new arg like "int lookup".
*/
int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
{
/*
- $Id: cmd_dbd_scanvol.c,v 1.6 2009-05-25 13:52:14 franklahm Exp $
+ $Id: cmd_dbd_scanvol.c,v 1.7 2009-07-12 09:21:34 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
rqst.cnid = db_cnid;
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
dbif_txn_close(dbd, ret);
rqst.cnid = ad_cnid;
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
dbif_txn_close(dbd, ret);
ret = dbd_rebuild_add(dbd, &rqst, &rply);
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
dbd_log( LOGDEBUG, "CNID rebuild add for '%s/%s', adding with CNID from ad-file: %u", cwdbuf, name, ntohl(ad_cnid));
rqst.cnid = ad_cnid;
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
dbif_txn_close(dbd, ret);
ret = dbd_rebuild_add(dbd, &rqst, &rply);
dbif_txn_close(dbd, ret);
dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
rqst.cnid = htonl(dbd_cnid);
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
dbif_txn_close(dbd, ret);
deleted++;
}
dbd_log(LOGSTD, "Orphaned CNID in database: %u.", dbd_cnid);
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
rqst.cnid = htonl(dbd_cnid);
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
dbif_txn_close(dbd, ret);
deleted++;
}
/*
- * $Id: dbd.h,v 1.4 2009-05-06 11:54:24 franklahm Exp $
+ * $Id: dbd.h,v 1.5 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (C) Frank Lahm 2009
extern int dbd_resolve(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_update(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
-extern int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
+extern int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int idx);
extern int dbd_getstamp(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_rebuild_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
extern int dbd_check_indexes(DBD *dbd, char *);
/*
- * $Id: dbd_delete.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
+ * $Id: dbd_delete.c,v 1.5 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
#include "dbd.h"
#include "pack.h"
-int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
+int dbd_delete(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int idx)
{
DBT key;
int rc;
+ unsigned char *buf;
memset(&key, 0, sizeof(key));
-
rply->namelen = 0;
- key.data = (void *) &rqst->cnid;
- key.size = sizeof(rqst->cnid);
+ switch (idx) {
+ case DBIF_IDX_DEVINO:
+ buf = pack_cnid_data(rqst);
+ key.data = buf + CNID_DEVINO_OFS;
+ key.size = CNID_DEVINO_LEN;
+ if ((rc = dbif_del(dbd, DBIF_IDX_DEVINO, &key, 0)) < 0) {
+ LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for dev/ino: 0x%llx/0x%llx",
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ rply->result = CNID_DBD_RES_ERR_DB;
+ return -1;
+ }
+ if (rc) {
+ LOG(log_debug, logtype_cnid, "cnid_delete: deleted dev/ino: 0x%llx/0x%llx",
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ rply->result = CNID_DBD_RES_OK;
+ } else {
+ LOG(log_debug, logtype_cnid, "cnid_delete: dev/ino: 0x%llx/0x%llx not in database",
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ }
+ break;
+ case DBIF_IDX_DIDNAME:
+ buf = pack_cnid_data(rqst);
+ key.data = buf + CNID_DID_OFS;
+ key.size = CNID_DID_LEN + rqst->namelen + 1;
+ if ((rc = dbif_del(dbd, DBIF_IDX_DIDNAME, &key, 0)) < 0) {
+ LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for DID: %lu, name: %s",
+ ntohl(rqst->did), rqst->name);
+ rply->result = CNID_DBD_RES_ERR_DB;
+ return -1;
+ }
+ if (rc) {
+ LOG(log_debug, logtype_cnid, "cnid_delete: deleted DID: %lu, name: %s",
+ ntohl(rqst->did), rqst->name);
+ rply->result = CNID_DBD_RES_OK;
+ } else {
+ LOG(log_debug, logtype_cnid, "cnid_delete: DID: %lu, name: %s not in database",
+ ntohl(rqst->did), rqst->name);
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ }
+ break;
+ default:
+ key.data = (void *) &rqst->cnid;
+ key.size = sizeof(rqst->cnid);
- if ((rc = dbif_del(dbd, DBIF_CNID, &key, 0)) < 0) {
- LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for CNID %u", ntohl(rqst->cnid));
- rply->result = CNID_DBD_RES_ERR_DB;
- return -1;
+ if ((rc = dbif_del(dbd, DBIF_CNID, &key, 0)) < 0) {
+ LOG(log_error, logtype_cnid, "dbd_delete: Unable to delete entry for CNID %u", ntohl(rqst->cnid));
+ rply->result = CNID_DBD_RES_ERR_DB;
+ return -1;
+ }
+ if (rc) {
+ LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u deleted", ntohl(rqst->cnid));
+ rply->result = CNID_DBD_RES_OK;
+ } else {
+ LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u not in database", ntohl(rqst->cnid));
+ rply->result = CNID_DBD_RES_NOTFOUND;
+ }
}
- if (rc) {
- LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u deleted", ntohl(rqst->cnid));
- rply->result = CNID_DBD_RES_OK;
- } else {
- LOG(log_debug, logtype_cnid, "cnid_delete: CNID %u not in database", ntohl(rqst->cnid));
- rply->result = CNID_DBD_RES_NOTFOUND;
- }
return 1;
}
/*
- * $Id: dbd_lookup.c,v 1.8 2009-05-28 10:22:07 franklahm Exp $
+ * $Id: dbd_lookup.c,v 1.9 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
*/
+/*
+ ATTENTION:
+ whatever you change here, also change cmd_dbd_lookup.c !
+ cmd_dbd_lookup has an read-only mode but besides that it's the same.
+*/
+
+/*
+The lines...
+
+Id Did T Dev Inode Name
+============================
+a b c d e name1
+-->
+f g h i h name2
+
+...are the expected results of certain operations.
+
+
+1) UNIX rename (mv)
+-------------------
+Name is changed but inode stays the same. We should try to keep the CNID.
+
+15 2 f 1 1 file
+-->
+15 2 f 1 1 movedfile
+
+Result in dbd_lookup (-: not found, +: found):
+- devino
++ didname
+
+Possible solution:
+Update.
+
+
+2) UNIX copy (cp)
+-----------------
+Changes inode and name. Result is just a new file which will get a fresh CNID.
+Unfortunately the old one gets orphaned.
+
+15 2 f 1 1 file
+-->
+16 2 f 1 2 copyfile
+
+Result in dbd_lookup:
+- devino
+- didname
+
+Possible fixup solution:
+Not possible. Only dbd -re can delete the orphaned CNID 15
+
+
+3) Restore from backup
+----------------------
+15 2 f 1 1 file
+-->
+15 2 f 1 2 file
+
+Result in dbd_lookup:
+- devino
++ didname
+
+Possible fixup solution:
+Update.
+
+
+4) UNIX emacs
+-------------
+This one is tough:
+emacs uses a backup file (file~). When saving because of inode reusage of the fs,
+both files exchange inodes. This should just be treated like 1).
+
+15 2 f 1 1 file
+16 2 f 1 2 file~
+-->
+15 2 f 1 2 file
+16 2 f 1 1 file~
+
+Result in dbd_lookup:
++ devino
++ didname
+
+Possible fixup solution:
+Update CNID entry found via "didname"(!).
+*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
/* the same */
LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u",
- (unsigned long long )rqst->dev, (unsigned long long )rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname));
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname));
rply->cnid = id_didname;
rply->result = CNID_DBD_RES_OK;
return 1;
}
+ /*
+ Order matters for the next 2 ifs because both found a CNID but they do not match.
+ So in order to pick the CNID from "didname" it must come after devino.
+ See test cases laid out in dbd_lookup.c.
+ */
+ if (devino) {
+ LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: server side rename oder reused inode for '%s'", rqst->name);
+ rqst->cnid = id_devino;
+ if (type_devino != rqst->type) {
+ /* same dev:inode but not same type one is a folder the other
+ * is a file,it's an inode reused, delete the record
+ */
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
+ return -1;
+ }
+ }
+ else {
+ update = 1;
+ }
+ }
if (didname) {
LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: changed dev/ino for '%s'", rqst->name);
rqst->cnid = id_didname;
*/
if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
type_didname != rqst->type) {
- if (dbd_delete(dbd, rqst, rply) < 0) {
- return -1;
- }
- }
- else {
- update = 1;
- }
- }
-
- if (devino) {
- LOG(log_maxdebug, logtype_cnid, "CNID resolve problem: server side rename oder reused inode for '%s'", rqst->name);
- rqst->cnid = id_devino;
- if (type_devino != rqst->type) {
- /* same dev:inode but not same type one is a folder the other
- * is a file,it's an inode reused, delete the record
- */
- if (dbd_delete(dbd, rqst, rply) < 0) {
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0) {
return -1;
}
}
/*
- * $Id: dbd_update.c,v 1.6 2009-05-28 10:22:07 franklahm Exp $
+ * $Id: dbd_update.c,v 1.7 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
#include "dbd.h"
-/* cnid_update: takes the given cnid and updates the metadata. */
+/*
+ cnid_update: takes the given cnid and updates the metadata.
+ First, delete given CNID, then re-insert.
+*/
-/* FIXME: This calls pack_cnid_data(rqst) three times without modifying rqst */
-/* FIXME: (Only tested with DB 4.1.25):
-
- dbif_pget on the secondary index followed by dbif_del with the CNID on the
- main cnid db could be replaced by a single dbif_del on the secondary index. That
- deletes the secondary, the corresponding entry from the main cnid db as well as the
- other secondary index.
-*/
-
int dbd_update(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
{
- DBT key,pkey, data;
- int rc;
- unsigned char *buf;
- int notfound = 0;
- char getbuf[CNID_HEADER_LEN + MAXPATHLEN +1];
- cnid_t tmpcnid;
+ DBT key, data;
memset(&key, 0, sizeof(key));
- memset(&pkey, 0, sizeof(pkey));
memset(&data, 0, sizeof(data));
-
rply->namelen = 0;
- buf = pack_cnid_data(rqst);
- key.data = buf +CNID_DEVINO_OFS;
- key.size = CNID_DEVINO_LEN;
-
- data.data = getbuf;
- data.size = CNID_HEADER_LEN + MAXPATHLEN + 1;
- if ((rc = dbif_pget(dbd, DBIF_IDX_DEVINO, &key, &pkey, &data, 0)) < 0 ) {
+ /* Try to wipe everything, also using the indexes */
+ if (dbd_delete(dbd, rqst, rply, DBIF_CNID) < 0)
goto err_db;
- }
- else if (rc > 0) {
- memcpy(&tmpcnid, pkey.data, sizeof(cnid_t));
- LOG(log_debug, logtype_cnid, "dbd_update: Deleting %u corresponding to dev/ino 0x%llx/0x%llx from cnid2.db",
- ntohl(tmpcnid), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
-
- if ((rc = dbif_del(dbd, DBIF_CNID, &pkey, 0)) < 0 ) {
- goto err_db;
- }
- else if (!rc) {
- LOG(log_error, logtype_cnid, "dbd_update: delete DEVINO %u %s", ntohl(rqst->cnid), db_strerror(errno));
- }
- }
- if (!rc) {
- notfound = 1;
- }
-
- buf = pack_cnid_data(rqst);
- key.data = buf + CNID_DID_OFS;
- key.size = CNID_DID_LEN + rqst->namelen +1;
- memset(&pkey, 0, sizeof(pkey));
-
- if ((rc = dbif_pget(dbd, DBIF_IDX_DIDNAME, &key, &pkey, &data, 0)) < 0) {
+ if (dbd_delete(dbd, rqst, rply, DBIF_IDX_DEVINO) < 0)
+ goto err_db;
+ if (dbd_delete(dbd, rqst, rply, DBIF_IDX_DIDNAME) < 0)
goto err_db;
- }
- else if (rc > 0) {
-
- memcpy(&tmpcnid, pkey.data, sizeof(cnid_t));
-
- LOG(log_debug, logtype_cnid, "dbd_update: Deleting %u corresponding to did %u name %s from cnid2.db",
- ntohl(tmpcnid), ntohl(rqst->did), rqst->name);
-
- if ((rc = dbif_del(dbd, DBIF_CNID, &pkey, 0)) < 0) {
- goto err_db;
- }
- else if (!rc) {
- LOG(log_error, logtype_cnid, "dbd_update: delete DIDNAME %u %s", ntohl(rqst->cnid), db_strerror(errno));
- }
- }
- if (!rc) {
- notfound |= 2;
- }
-
- memset(&key, 0, sizeof(key));
- key.data = (cnid_t *) &rqst->cnid;
- key.size = sizeof(rqst->cnid);
- memset(&data, 0, sizeof(data));
/* Make a new entry. */
+ key.data = &rqst->cnid;
+ key.size = sizeof(rqst->cnid);
data.data = pack_cnid_data(rqst);
- memcpy(data.data, &rqst->cnid, sizeof(rqst->cnid));
data.size = CNID_HEADER_LEN + rqst->namelen + 1;
+ memcpy(data.data, &rqst->cnid, sizeof(rqst->cnid));
if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0)
goto err_db;
- LOG(log_info, logtype_cnid, "dbd_update: Updated cnid2.db with dev/ino 0x%llx/0x%llx did %u name %s cnid %u",
+ LOG(log_info, logtype_cnid, "dbd_update: Updated dbd with dev/ino: 0x%llx/0x%llx, did: %u, name: %s, cnid: %u",
(unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rqst->cnid));
rply->result = CNID_DBD_RES_OK;
return 1;
err_db:
- LOG(log_error, logtype_cnid, "dbd_update: Unable to update CNID %u dev/ino 0x%llx/0x%llx, DID %ul: %s",
- ntohl(rqst->cnid), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, rqst->did, rqst->name);
+ LOG(log_error, logtype_cnid, "dbd_update: Unable to update CNID: %u, dev/ino: 0x%llx/0x%llx, DID: %u: %s",
+ ntohl(rqst->cnid), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name);
rply->result = CNID_DBD_RES_ERR_DB;
return -1;
/*
- * $Id: main.c,v 1.8 2009-05-20 10:29:22 franklahm Exp $
+ * $Id: main.c,v 1.9 2009-07-12 09:21:34 franklahm Exp $
*
* Copyright (C) Joerg Lenneis 2003
* Copyright (c) Frank Lahm 2009
ret = dbd_update(dbd, &rqst, &rply);
break;
case CNID_DBD_OP_DELETE:
- ret = dbd_delete(dbd, &rqst, &rply);
+ ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
break;
case CNID_DBD_OP_GETSTAMP:
ret = dbd_getstamp(dbd, &rqst, &rply);