}
static int fcntl_lock(struct tdb_context *tdb,
- int rw, off_t off, off_t len, bool wait)
+ int rw, off_t off, off_t len, bool waitflag)
{
struct flock fl;
-
+
fl.l_type = rw;
fl.l_whence = SEEK_SET;
fl.l_start = off;
fl.l_len = len;
fl.l_pid = 0;
- if (wait)
+ if (waitflag)
return fcntl(tdb->fd, F_SETLKW, &fl);
else
return fcntl(tdb->fd, F_SETLK, &fl);
* EAGAIN is an expected return from non-blocking
* locks. */
if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
- TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
tdb->fd, offset, rw_type, flags, (int)len));
}
return -1;
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
- TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
+ TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
tdb->fd, offset, rw_type, (int)len));
}
return ret;
return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
+
+
/* record lock stops delete underneath */
int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
{
errno = ENOMEM;
goto fail;
}
-
tdb_io_init(tdb);
tdb->fd = -1;
#ifdef TDB_TRACE
{
char tracefile[strlen(name) + 32];
- sprintf(tracefile, "%s.trace.%u", name, getpid());
+ snprintf(tracefile, sizeof(tracefile),
+ "%s.trace.%li", name, (long)getpid());
tdb->tracefd = open(tracefile, O_WRONLY|O_CREAT|O_EXCL, 0600);
if (tdb->tracefd >= 0) {
tdb_enable_seqnum(tdb);
return tdb->log.log_private;
}
-/* reopen a tdb - this can be used after a fork to ensure that we have an independent
- seek pointer from our parent and to re-establish locks */
-int tdb_reopen(struct tdb_context *tdb)
+static int tdb_reopen_internal(struct tdb_context *tdb, bool active_lock)
{
struct stat st;
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno)));
goto fail;
}
- if ((tdb->flags & TDB_CLEAR_IF_FIRST) &&
- (tdb->methods->brlock(tdb, F_RDLCK, ACTIVE_LOCK, 1, TDB_LOCK_WAIT) == -1)) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
- goto fail;
- }
if (fstat(tdb->fd, &st) != 0) {
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno)));
goto fail;
}
tdb_mmap(tdb);
+ if (active_lock &&
+ (tdb->methods->brlock(tdb, F_RDLCK, ACTIVE_LOCK, 1, TDB_LOCK_WAIT) == -1)) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
+ goto fail;
+ }
+
return 0;
fail:
return -1;
}
+/* reopen a tdb - this can be used after a fork to ensure that we have an independent
+ seek pointer from our parent and to re-establish locks */
+int tdb_reopen(struct tdb_context *tdb)
+{
+ return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
+}
+
/* reopen all tdb's */
int tdb_reopen_all(int parent_longlived)
{
struct tdb_context *tdb;
for (tdb=tdbs; tdb; tdb = tdb->next) {
+ bool active_lock = (tdb->flags & TDB_CLEAR_IF_FIRST);
+
/*
* If the parent is longlived (ie. a
* parent daemon architecture), we know
*/
if (parent_longlived) {
/* Ensure no clear-if-first. */
- tdb->flags &= ~TDB_CLEAR_IF_FIRST;
+ active_lock = false;
}
- if (tdb_reopen(tdb) != 0)
+ if (tdb_reopen_internal(tdb, active_lock) != 0)
return -1;
}
/* find which hash bucket it is in */
hash = tdb->hash_fn(&key);
- if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
+ if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null;
- }
+
ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len,
rec.data_len);
ret.dsize = rec.data_len;
hash = tdb->hash_fn(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
- tdb_trace_1rec_ret(tdb, "tdb_parse_record", key,
- -TDB_ERR_NOEXIST);
+ tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
tdb->ecode = TDB_ERR_NOEXIST;
return 0;
}
}
static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
- TDB_DATA dbuf, int flag, uint32_t hash)
+ TDB_DATA dbuf, int flag, uint32_t hash)
{
struct tdb_record rec;
tdb_off_t rec_ptr;
}
/* store an element in the database, replacing any existing element
- with the same key
+ with the same key
return 0 on success, -1 on failure
*/
if (tdb->read_only || tdb->traverse_read) {
tdb->ecode = TDB_ERR_RDONLY;
- tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag,
- -TDB_ERR_RDONLY);
+ tdb_trace_2rec_flag_ret(tdb, "tdb_store", key, dbuf, flag, -1);
return -1;
}
return ret;
}
-
/* Append to an entry. Create if not exist. */
int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
{
tdb_off_t seqnum=0;
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
- tdb_trace_ret(tdb, "tdb_get_seqnum", seqnum);
return seqnum;
}
return -1;
}
-
struct traverse_state {
bool error;
struct tdb_context *dest_db;
/*
traverse function for repacking
*/
-static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
+static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
{
- struct traverse_state *state = (struct traverse_state *)private;
+ struct traverse_state *state = (struct traverse_state *)private_data;
if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) {
state->error = true;
return -1;
tdb_trace(tdb, "tdb_repack");
if (tdb_transaction_start(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to start transaction\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n"));
return -1;
}
tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0);
if (tmp_db == NULL) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to create tmp_db\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n"));
tdb_transaction_cancel(tdb);
return -1;
}
state.dest_db = tmp_db;
if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to traverse copying out\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Error during traversal\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (tdb_wipe_all(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to wipe database\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
state.dest_db = tdb;
if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to traverse copying back\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
}
if (state.error) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Error during second traversal\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n"));
tdb_transaction_cancel(tdb);
tdb_close(tmp_db);
return -1;
tdb_close(tmp_db);
if (tdb_transaction_commit(tdb) != 0) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_repack: Failed to commit\n"));
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n"));
return -1;
}
static void tdb_trace_start(struct tdb_context *tdb)
{
tdb_off_t seqnum=0;
- char msg[sizeof(tdb_off_t) * 4];
+ char msg[sizeof(tdb_off_t) * 4 + 1];
tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
- sprintf(msg, "%u ", seqnum);
+ snprintf(msg, sizeof(msg), "%u ", seqnum);
tdb_trace_write(tdb, msg);
}
static void tdb_trace_end_ret(struct tdb_context *tdb, int ret)
{
- char msg[sizeof(ret) * 4];
- sprintf(msg, " = %i\n", ret);
+ char msg[sizeof(ret) * 4 + 4];
+ snprintf(msg, sizeof(msg), " = %i\n", ret);
tdb_trace_write(tdb, msg);
}
return;
}
+ /* snprintf here is purely cargo-cult programming. */
p = msg;
- p += sprintf(p, " %zu:", rec.dsize);
+ p += snprintf(p, sizeof(msg), " %zu:", rec.dsize);
for (i = 0; i < rec.dsize; i++)
- p += sprintf(p, "%02x", rec.dptr[i]);
+ p += snprintf(p, 2, "%02x", rec.dptr[i]);
tdb_trace_write(tdb, msg);
}
void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op)
{
- char msg[sizeof(tdb_off_t) * 4];
+ char msg[sizeof(tdb_off_t) * 4 + 1];
- sprintf(msg, "%u ", seqnum);
+ snprintf(msg, sizeof(msg), "%u ", seqnum);
tdb_trace_write(tdb, msg);
tdb_trace_write(tdb, op);
tdb_trace_end(tdb);
{
char msg[128];
- sprintf(msg, "%s %u %#x %#x", op, hash_size, tdb_flags, open_flags);
+ snprintf(msg, sizeof(msg),
+ "%s %u 0x%x 0x%x", op, hash_size, tdb_flags, open_flags);
tdb_trace_start(tdb);
tdb_trace_write(tdb, msg);
tdb_trace_end(tdb);
TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
int ret)
{
- char msg[sizeof(ret) * 4];
+ char msg[1 + sizeof(ret) * 4];
- sprintf(msg, " %#x", flag);
+ snprintf(msg, sizeof(msg), " %#x", flag);
tdb_trace_start(tdb);
tdb_trace_write(tdb, op);
tdb_trace_record(tdb, rec1);