64 * 1024, /* bdb cachesize (64 MB) */
DEFAULT_MAXLOCKS, /* maxlocks */
DEFAULT_MAXLOCKOBJS, /* maxlockobjs */
- -1, /* not used ... */
- -1,
- "",
- -1,
- -1,
- -1
+ 0, /* flush_interval */
+ 0, /* flush_frequency */
+ 1000, /* txn_frequency */
+ 0, /* usock_file */
+ -1, /* fd_table_size */
+ -1, /* idle_timeout */
+ -1 /* max_vols */
};
static char dbpath[MAXPATHLEN+1]; /* Path to the dbd database */
/* Cleanup */
dbd_log(LOGDEBUG, "Closing db");
- if (! nocniddb && dbif_close(dbd) < 0) {
- dbd_log( LOGSTD, "Error closing database");
- goto exit_failure;
+ if (! nocniddb) {
+ if (dbif_close(dbd) < 0) {
+ dbd_log( LOGSTD, "Error closing database");
+ goto exit_failure;
+ }
}
exit_success:
cnid_t db_cnid, ad_cnid;
struct adouble ad;
+ /* Force checkout every X items */
+ static int cnidcount = 0;
+ cnidcount++;
+ if (cnidcount > 10000) {
+ cnidcount = 0;
+ if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
+ dbd_log(LOGSTD, "Error checkpointing!");
+ return 0;
+ }
+ }
+
/* Get CNID from ad-file if volume is using AFPVOL_CACHE */
ad_cnid = 0;
if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
/* Now add this object to our rebuild dbd */
if (cnid) {
+ static uint count = 0;
rqst.cnid = rply.cnid;
ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
dbif_txn_close(dbd_rebuild, ret);
cnid, cwdbuf, ep->d_name);
longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
}
+ count++;
+ if (count == 10000) {
+ if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
+ dbd_log(LOGSTD, "Error checkpointing!");
+ return -1;
+ }
+ count = 0;
+ }
}
}
struct cnid_dbd_rqst rqst;
struct cnid_dbd_rply rply;
+ dbd->db_param.txn_frequency = 0;
+
/* jump over rootinfo key */
if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
return;
}
if (dbd_cnid > rebuild_cnid) {
+ dbif_idwalk(dbd, NULL, 1); /* Close cursor */
+ dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
+ dbif_txn_close(dbd, 2);
+ dbif_txn_close(dbd_rebuild, 2);
dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
dbif_dump(dbd_rebuild, 0);
dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
- dbif_txn_close(dbd, ret);
- dbif_idwalk(dbd, NULL, 1); /* Close cursor */
- dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
goto cleanup;
}
} /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
db_param.cachesize = 128 * 1024; /* 128 MB */
db_param.maxlocks = DEFAULT_MAXLOCKS;
db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
+ db_param.txn_frequency = 1000; /* close txn every 1000 objects */
+ db_param.logfile_autoremove = 1;
/* Make it accessible for all funcs */
dbd = dbd_ref;
if (setjmp(jmp) != 0) {
ret = 0; /* Got signal, jump from dbd_readdir */
- goto exit;
+ goto exit_cleanup;
}
/* scanvol */
goto exit;
}
+exit_cleanup:
if (! nocniddb) {
- /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
- other clients in between our pass 1 and 2 */
- if (flags & DBD_FLAGS_EXCL)
+ dbif_txn_close(dbd, 2);
+ dbif_txn_close(dbd_rebuild, 2);
+ if ((flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
+ /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
+ other clients in between our pass 1 and 2 */
delete_orphaned_cnids(dbd, dbd_rebuild, flags);
}
if (dbd_rebuild) {
dbd_log(LOGDEBUG, "Closing tmp db");
dbif_close(dbd_rebuild);
-#if 0
+
if (tmpdb_path) {
char cmd[8 + MAXPATHLEN];
snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path);
snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path);
system(cmd);
}
-#endif
}
return ret;
}
return -1;
}
+ dbd->db_param = *dbp;
+
if ((dbif_openlog(dbd)) != 0)
return -1;
}
/*
- ret = 1 -> commit txn
- ret = 0 -> abort txn -> exit!
+ ret = 2 -> commit txn regardless of db_param.txn_frequency
+ ret = 1 -> commit txn if db_param.txn_frequency
+ ret = 0 -> abort txn db_param.txn_frequency -> exit!
anything else -> exit!
+
+ db_param of the db environment might specify txn_frequency > 1 in which case
+ we only close a txn every txn_frequency time. the `dbd` command uses this for the
+ temp rebuild db, cnid_dbd keeps it at 0. For increasing cnid_dbd throughput this
+ should be tuned and testes as well.
*/
void dbif_txn_close(DBD *dbd, int ret)
{
LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!");
exit(EXIT_FAILURE);
}
- } else if (ret == 1) {
+ } else if (ret == 1 || ret == 2) {
+ static uint count;
+ if (ret != 2 && dbd->db_param.txn_frequency > 1) {
+ count++;
+ if ((count % dbd->db_param.txn_frequency) != 0)
+ return;
+ }
ret = dbif_txn_commit(dbd);
if ( ret < 0) {
LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!");