From 28fc5582c207d493a33406222da517a241a157ec Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 11 Jan 2009 12:17:18 -0500 Subject: Add caching behavior to nsssrv_cmd.c check cache first and dispatch to backends only if we have a cache miss. --- server/nss/nss_ldb.h | 10 +++--- server/nss/nsssrv.c | 2 ++ server/nss/nsssrv.h | 2 ++ server/nss/nsssrv_cmd.c | 88 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 82 insertions(+), 20 deletions(-) (limited to 'server') diff --git a/server/nss/nss_ldb.h b/server/nss/nss_ldb.h index b41c7a67..eee4344f 100644 --- a/server/nss/nss_ldb.h +++ b/server/nss/nss_ldb.h @@ -29,13 +29,15 @@ #define NSS_DEF_GR_GIDNUM "gidNumber" #define NSS_DEF_GR_MEMBER "member" +#define NSS_DEF_LAST_UPDATE "lastUpdate" + #define NSS_DEF_PW_ATTRS {NSS_DEF_PW_NAME, NSS_DEF_PW_UIDNUM, \ NSS_DEF_PW_GIDNUM, NSS_DEF_PW_FULLNAME, \ NSS_DEF_PW_HOMEDIR, NSS_DEF_PW_SHELL, \ - NULL} -#define NSS_DEF_GRNAM_ATTRS {NSS_DEF_GR_NAME, NSS_DEF_GR_GIDNUM, NULL} -#define NSS_DEF_GRPW_ATTRS {NSS_DEF_PW_NAME, NULL} + NSS_DEF_LAST_UPDATE, NULL} +#define NSS_DEF_GRNAM_ATTRS {NSS_DEF_GR_NAME, NSS_DEF_GR_GIDNUM, NSS_DEF_LAST_UPDATE, NULL} +#define NSS_DEF_GRPW_ATTRS {NSS_DEF_PW_NAME, NSS_DEF_LAST_UPDATE, NULL} #define NSS_DEF_INITGR_ATTR "memberof" -#define NSS_DEF_INITGR_ATTRS {NSS_DEF_GR_GIDNUM, NULL} +#define NSS_DEF_INITGR_ATTRS {NSS_DEF_GR_GIDNUM, NSS_DEF_LAST_UPDATE, NULL} diff --git a/server/nss/nsssrv.c b/server/nss/nsssrv.c index 5fc707f8..c787637a 100644 --- a/server/nss/nsssrv.c +++ b/server/nss/nsssrv.c @@ -439,6 +439,8 @@ int nss_process_init(TALLOC_CTX *mem_ctx, return ret; } + nctx->cache_timeout = 600; /* FIXME: read from conf */ + DEBUG(1, ("NSS Initialization complete\n")); return EOK; diff --git a/server/nss/nsssrv.h b/server/nss/nsssrv.h index 51b0f535..faefa7df 100644 --- a/server/nss/nsssrv.h +++ b/server/nss/nsssrv.h @@ -48,6 +48,8 @@ struct nss_ctx { struct service_sbus_ctx *ss_ctx; struct service_sbus_ctx *dp_ctx; struct btreemap *domain_map; + + int cache_timeout; }; struct cli_ctx { diff --git a/server/nss/nsssrv_cmd.c b/server/nss/nsssrv_cmd.c index 828bdb78..9347c329 100644 --- a/server/nss/nsssrv_cmd.c +++ b/server/nss/nsssrv_cmd.c @@ -24,11 +24,13 @@ #include "util/util.h" #include "nss/nsssrv.h" #include "nss/nsssrv_ldb.h" +#include struct nss_cmd_ctx { struct cli_ctx *cctx; const char *name; uint64_t id; + bool check_expiration; }; struct getent_ctx { @@ -185,26 +187,45 @@ done: return EOK; } +static void nss_cmd_getpwnam_callback(uint16_t err_maj, uint32_t err_min, + const char *err_msg, void *ptr); + static void nss_cmd_getpw_callback(void *ptr, int status, struct ldb_result *res) { struct nss_cmd_ctx *nctx = talloc_get_type(ptr, struct nss_cmd_ctx); struct cli_ctx *cctx = nctx->cctx; + int timeout; + uint64_t lastUpdate; uint8_t *body; size_t blen; int ret; - /* create response packet */ - ret = nss_packet_new(cctx->creq, 0, - nss_packet_get_cmd(cctx->creq->in), - &cctx->creq->out); - if (ret != EOK) { - NSS_CMD_FATAL_ERROR(cctx); + if (status != LDB_SUCCESS) { + ret = nss_cmd_send_error(nctx, status); + if (ret != EOK) { + NSS_CMD_FATAL_ERROR(cctx); + } + return; } - if (status != LDB_SUCCESS) { - nss_packet_set_error(cctx->creq->out, status); - goto done; + if (res->count == 0 && nctx->check_expiration) { + + /* dont loop forever :-) */ + nctx->check_expiration = false; + + ret = nss_dp_send_acct_req(cctx->nctx, nctx, + nss_cmd_getpwnam_callback, nctx, + SSS_NSS_SOCKET_TIMEOUT/2, "*", + NSS_DP_USER, nctx->name, 0); + if (ret != EOK) { + ret = nss_cmd_send_error(nctx, ret); + } + if (ret != EOK) { + NSS_CMD_FATAL_ERROR(cctx); + } + + return; } if (res->count != 1) { @@ -226,6 +247,38 @@ static void nss_cmd_getpw_callback(void *ptr, int status, goto done; } + if (nctx->check_expiration) { + timeout = nctx->cctx->nctx->cache_timeout; + + lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0], "lastUpdate", 0); + if (lastUpdate + timeout < time(NULL)) { + + /* dont loop forever :-) */ + nctx->check_expiration = false; + + ret = nss_dp_send_acct_req(cctx->nctx, nctx, + nss_cmd_getpwnam_callback, nctx, + SSS_NSS_SOCKET_TIMEOUT/2, "*", + NSS_DP_USER, nctx->name, 0); + if (ret != EOK) { + ret = nss_cmd_send_error(nctx, ret); + } + if (ret != EOK) { + NSS_CMD_FATAL_ERROR(cctx); + } + + return; + } + } + + /* create response packet */ + ret = nss_packet_new(cctx->creq, 0, + nss_packet_get_cmd(cctx->creq->in), + &cctx->creq->out); + if (ret != EOK) { + NSS_CMD_FATAL_ERROR(cctx); + } + ret = fill_pwent(cctx->creq->out, cctx->nctx->lctx, res->msgs, res->count); nss_packet_set_error(cctx->creq->out, ret); @@ -271,6 +324,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) return ENOMEM; } nctx->cctx = cctx; + nctx->check_expiration = true; /* get user name to query */ nss_packet_get_body(cctx->creq->in, &body, &blen); @@ -286,16 +340,18 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) /* FIXME: Just ask all backends for now, until Steve provides for name * parsing code */ - ret = nss_dp_send_acct_req(cctx->nctx, nctx, - nss_cmd_getpwnam_callback, nctx, - SSS_NSS_SOCKET_TIMEOUT/2, "*", - NSS_DP_USER, nctx->name, 0); + ret = nss_ldb_getpwnam(nctx, cctx->ev, cctx->nctx->lctx, + nctx->name, nss_cmd_getpw_callback, nctx); if (ret != EOK) { - talloc_free(nctx); - return ret; + DEBUG(1, ("Failed to make request to our cache!\n")); + + ret = nss_cmd_send_error(nctx, ret); + if (ret != EOK) { + return ret; + } } - return ret; + return EOK; } static int nss_cmd_getpwuid(struct cli_ctx *cctx) -- cgit