lib: Avoid looking at fcntl'ed gencache.tdb
authorVolker Lendecke <vl@samba.org>
Thu, 3 Mar 2016 16:41:34 +0000 (17:41 +0100)
committerRalph Boehme <slow@samba.org>
Mon, 7 Mar 2016 16:58:16 +0000 (17:58 +0100)
gencache_notrans.tdb is much cheaper to look at than gencache.tdb because it's
mutexed and thus avoids expensive fcntl locks. This patch aggressively uses the
shared _notrans tdb for both positive and negative entries. It's a replacement
for the memcache copy in every process that was removed a few patches ago.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/lib/gencache.c

index 67a4638f500e8a495b4531350a1c0f707442627d..e506b3be5f1f19264d5eb003d8be9801f6684647 100644 (file)
@@ -450,6 +450,7 @@ static bool gencache_pull_timeout(uint8_t *val, time_t *pres, char **payload)
 struct gencache_parse_state {
        void (*parser)(time_t timeout, DATA_BLOB blob, void *private_data);
        void *private_data;
+       bool copy_to_notrans;
 };
 
 static int gencache_parse_fn(TDB_DATA key, TDB_DATA data, void *private_data)
@@ -472,6 +473,10 @@ static int gencache_parse_fn(TDB_DATA key, TDB_DATA data, void *private_data)
                payload, data.dsize - PTR_DIFF(payload, data.dptr));
        state->parser(t, blob, state->private_data);
 
+       if (state->copy_to_notrans) {
+               tdb_store(cache_notrans->tdb, key, data, 0);
+       }
+
        return 0;
 }
 
@@ -496,13 +501,35 @@ bool gencache_parse(const char *keystr,
 
        state.parser = parser;
        state.private_data = private_data;
+       state.copy_to_notrans = false;
+
+       ret = tdb_chainlock(cache_notrans->tdb, key);
+       if (ret != 0) {
+               return false;
+       }
 
        ret = tdb_parse_record(cache_notrans->tdb, key,
                               gencache_parse_fn, &state);
        if (ret == 0) {
+               tdb_chainunlock(cache_notrans->tdb, key);
                return true;
        }
+
+       state.copy_to_notrans = true;
+
        ret = tdb_parse_record(cache->tdb, key, gencache_parse_fn, &state);
+
+       if ((ret == -1) && (tdb_error(cache->tdb) == TDB_ERR_NOEXIST)) {
+               /*
+                * The record does not exist. Set a delete-marker in
+                * gencache_notrans, so that we don't have to look at
+                * the fcntl-based cache again.
+                */
+               gencache_set(keystr, "", 0);
+       }
+
+       tdb_chainunlock(cache_notrans->tdb, key);
+
        return (ret == 0);
 }