>From 2c4107d1059c346161967a965c0c5df319cceaf1 Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Tue, 11 Sep 2012 18:44:52 +0200
Subject: [PATCH 2/2] sss_cache tool invalidates records in memory cache.

---
 src/responder/nss/nsssrv.c            | 55 ++++++++++++++++++++++++++++++++++-
 src/responder/nss/nsssrv_mmap_cache.c | 50 +++++++++++++++++++++++++++++++
 src/responder/nss/nsssrv_mmap_cache.h |  3 ++
 src/tools/sss_cache.c                 |  9 ++++++
 4 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 64267e8..258063c 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -51,10 +51,13 @@
 #define SHELL_REALLOC_INCREMENT 5
 #define SHELL_REALLOC_MAX       50
 
+static int nss_hup(DBusMessage *message,
+                   struct sbus_connection *conn);
+
 struct sbus_method monitor_nss_methods[] = {
     { MON_CLI_METHOD_PING, monitor_common_pong },
     { MON_CLI_METHOD_RES_INIT, monitor_common_res_init },
-    { MON_CLI_METHOD_ROTATE, responder_logrotate },
+    { MON_CLI_METHOD_ROTATE, nss_hup },
     { NULL, NULL }
 };
 
@@ -66,6 +69,56 @@ struct sbus_interface monitor_nss_interface = {
     NULL
 };
 
+static int nss_hup(DBusMessage *message,
+                   struct sbus_connection *conn)
+{
+    errno_t ret;
+    int memcache_timeout;
+    size_t memcache_size;
+    struct resp_ctx *rctx = talloc_get_type(sbus_conn_get_private_data(conn),
+                                            struct resp_ctx);
+    struct nss_ctx *nctx = (struct nss_ctx*)rctx->pvt_ctx;
+
+    /* Rotate logs */
+    ret = monitor_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
+    if (ret != EOK) return ret;
+
+    /* FIXME: It would be good not to invalidate cache every time we
+     * rotate logs. */
+    ret = confdb_get_int(rctx->cdb,
+                         CONFDB_NSS_CONF_ENTRY,
+                         CONFDB_MEMCACHE_TIMEOUT,
+                         300, &memcache_timeout);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Unable to get memory cache entry timeout.\n"));
+        return ret;
+    }
+
+    /* TODO: read cache sizes from configuration */
+    memcache_size = 50000;
+
+    ret = sss_mmap_cache_reinit(nctx, memcache_size,
+                                (time_t)memcache_timeout,
+                                &nctx->pwd_mc_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("passwd mmap cache invalidation failed\n"));
+        return ret;
+    }
+
+    ret = sss_mmap_cache_reinit(nctx, memcache_size,
+                                (time_t)memcache_timeout,
+                                &nctx->grp_mc_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("group mmap cache invalidation failed\n"));
+        return ret;
+    }
+
+    return monitor_common_pong(message, conn);
+}
+
 static errno_t nss_get_etc_shells(TALLOC_CTX *mem_ctx, char ***_shells)
 {
     int i = 0;
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 07498a9..1316e77 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -58,6 +58,8 @@ struct sss_mc_ctx {
     uint32_t seed;          /* pseudo-random seed to avoid collision attacks */
     time_t valid_time_slot; /* maximum time the entry is valid in seconds */
 
+    int n_elem;             /* max number of entries stored in mmap cache */
+
     void *mmap_base;        /* base address of mmap */
     size_t mmap_size;       /* total size of mmap */
 
@@ -725,3 +727,51 @@ done:
     return ret;
 }
 
+errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
+                              time_t timeout, struct sss_mc_ctx **mc_ctx)
+{
+    errno_t ret;
+    TALLOC_CTX* local_ctx;
+    char *name;
+    enum sss_mc_type type;
+
+    if (mc_ctx == NULL || (*mc_ctx) == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Unable to re-init unitialized memory cache.\n"));
+        return EINVAL;
+    }
+
+    local_ctx = talloc_new(mem_ctx);
+    if (local_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n"));
+        return ENOMEM;
+    }
+
+    name = talloc_strdup(local_ctx, (*mc_ctx)->name);
+    if (name == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    type = (*mc_ctx)->type;
+    ret = talloc_free(*mc_ctx);
+    if (ret != 0) {
+        /* This can happen only if destructor is associated with this
+         * context */
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Destructor asociated with memory"
+                                    " context failed.\n"));
+        goto done;
+    }
+
+    ret = sss_mmap_cache_init(mem_ctx, name, type, n_elem, timeout, mc_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to re-initialize mmap cache.\n"));
+        goto done;
+    }
+
+done:
+    talloc_free(local_ctx);
+    return ret;
+}
+
diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
index 81241b2..8be490c 100644
--- a/src/responder/nss/nsssrv_mmap_cache.h
+++ b/src/responder/nss/nsssrv_mmap_cache.h
@@ -48,4 +48,7 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx *mcc,
                                 gid_t gid, size_t memnum,
                                 char *membuf, size_t memsize);
 
+errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
+                              time_t timeout, struct sss_mc_ctx **mc_ctx);
+
 #endif /* _NSSSRV_MMAP_CACHE_H_ */
diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c
index 950ff1c..63f31ad 100644
--- a/src/tools/sss_cache.c
+++ b/src/tools/sss_cache.c
@@ -141,6 +141,15 @@ int main(int argc, const char *argv[])
             ERROR("No cache object matched the specified search\n");
             ret = ENOENT;
             goto done;
+        } else {
+            /*Local cache changed -> signal monitor to invalidate fastcache */
+            DEBUG(SSSDBG_TRACE_FUNC, ("Sending SIGHUP to monitor.\n"));
+            ret = signal_sssd(SIGHUP);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      ("Failed to send SIGHUP to monitor.\n"));
+                goto done;
+            }
         }
     }
 
-- 
1.7.11.2

