summaryrefslogtreecommitdiff
path: root/source4/lib/tdb/common/tdb.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2006-03-30 04:52:39 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:59:20 -0500
commit3387746c4517d6766146080980ac467b72b62316 (patch)
treebe82b9daf54552306123f38d88330460825dfcf4 /source4/lib/tdb/common/tdb.c
parent86971ff3b930a93de55aae00fe66f3d1d10dbcb4 (diff)
downloadsamba-3387746c4517d6766146080980ac467b72b62316.tar.gz
samba-3387746c4517d6766146080980ac467b72b62316.tar.bz2
samba-3387746c4517d6766146080980ac467b72b62316.zip
r14799: added a tdb_get_seqnum() call, and the TDB_SEQNUM flag. This allows
for an extremely lightweight test to see if a tdb has possibly changed. (This used to be commit f325ba605ccceca63712c0f2c98961e35e437b3d)
Diffstat (limited to 'source4/lib/tdb/common/tdb.c')
-rw-r--r--source4/lib/tdb/common/tdb.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/source4/lib/tdb/common/tdb.c b/source4/lib/tdb/common/tdb.c
index 4b0d4a31c5..b0411601eb 100644
--- a/source4/lib/tdb/common/tdb.c
+++ b/source4/lib/tdb/common/tdb.c
@@ -30,6 +30,33 @@
TDB_DATA tdb_null;
+/*
+ increment the tdb sequence number if the tdb has been opened using
+ the TDB_SEQNUM flag
+*/
+static void tdb_increment_seqnum(struct tdb_context *tdb)
+{
+ tdb_off_t seqnum=0;
+
+ if (!(tdb->flags & TDB_SEQNUM)) {
+ return;
+ }
+
+ if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1) != 0) {
+ return;
+ }
+
+ /* we ignore errors from this, as we have no sane way of
+ dealing with them.
+ */
+ tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+ seqnum++;
+ tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum);
+
+ tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1);
+}
+
+
/* Returns 0 on fail. On success, return offset of record, and fills
in rec */
static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash,
@@ -203,6 +230,11 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
return -1;
ret = tdb_do_delete(tdb, rec_ptr, &rec);
+
+ if (ret == 0) {
+ tdb_increment_seqnum(tdb);
+ }
+
if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0)
TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n"));
return ret;
@@ -295,6 +327,9 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
/* Need to tdb_unallocate() here */
goto fail;
}
+
+ tdb_increment_seqnum(tdb);
+
out:
SAFE_FREE(p);
tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
@@ -369,3 +404,22 @@ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
{
return tdb->log_fn;
}
+
+
+/*
+ get the tdb sequence number. Only makes sense if the writers opened
+ with TDB_SEQNUM set. Note that this sequence number will wrap quite
+ quickly, so it should only be used for a 'has something changed'
+ test, not for code that relies on the count of the number of changes
+ made. If you want a counter then use a tdb record.
+
+ The aim of this sequence number is to allow for a very lightweight
+ test of a possible tdb change.
+*/
+int tdb_get_seqnum(struct tdb_context *tdb)
+{
+ tdb_off_t seqnum=0;
+
+ tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum);
+ return seqnum;
+}