2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina Pavel Březina <pbrezina@redhat.com>
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina Copyright (C) 2016 Red Hat
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina This program is free software; you can redistribute it and/or modify
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina it under the terms of the GNU General Public License as published by
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina the Free Software Foundation; either version 3 of the License, or
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina (at your option) any later version.
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina This program is distributed in the hope that it will be useful,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina GNU General Public License for more details.
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina You should have received a copy of the GNU General Public License
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina#include "responder/common/cache_req/cache_req_private.h"
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina#include "responder/common/cache_req/cache_req_plugin.h"
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic errno_t cache_req_search_ncache(struct cache_req *cr)
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "This request type does not support negative cache\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Checking negative cache for [%s]\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina ret = cr->plugin->ncache_check_fn(cr->ncache, cr->domain, cr->data);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "[%s] does not exist (negative cache)\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Unable to check negative cache [%d]: %s\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "[%s] is not present in negative cache\n",
800b1a27543fa83bc6cd73d8e2789f3cdbaf584aJakub Hrozekvoid cache_req_search_ncache_add_to_domain(struct cache_req *cr,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "This request type does not support negative cache\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Adding [%s] to negative cache\n",
800b1a27543fa83bc6cd73d8e2789f3cdbaf584aJakub Hrozek ret = cr->plugin->ncache_add_fn(cr->ncache, domain, cr->data);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Cannot set negative cache for [%s] [%d]: %s\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* not fatal */
800b1a27543fa83bc6cd73d8e2789f3cdbaf584aJakub Hrozekstatic void cache_req_search_ncache_add(struct cache_req *cr)
800b1a27543fa83bc6cd73d8e2789f3cdbaf584aJakub Hrozek return cache_req_search_ncache_add_to_domain(cr, cr->domain);
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidênciostatic errno_t cache_req_search_ncache_filter(TALLOC_CTX *mem_ctx,
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio if (cr->plugin->ncache_filter_fn == NULL) {
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "This request type does not support filtering "
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "result by negative cache\n");
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "Filtering out results by negative cache\n");
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio msgs = talloc_zero_array(tmp_ctx, struct ldb_message *, (*_result)->count);
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio for (size_t i = 0; i < (*_result)->count; i++) {
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio name = sss_get_name_from_msg(cr->domain, (*_result)->msgs[i]);
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "sss_get_name_from_msg() returned NULL, which should never "
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "happen in this scenario!\n");
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio ret = cr->plugin->ncache_filter_fn(cr->ncache, cr->domain, name);
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "[%s] filtered out! (negative cache)\n",
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio "Unable to check negative cache [%d]: %s\n",
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio msgs[msg_count] = talloc_steal(msgs, (*_result)->msgs[i]);
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio filtered_result = cache_req_create_ldb_result_from_msg_list(tmp_ctx, msgs,
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio *_result = talloc_steal(mem_ctx, filtered_result);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic errno_t cache_req_search_cache(TALLOC_CTX *mem_ctx,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Bug: No cache lookup function specified\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Looking up [%s] in cache\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina ret = cr->plugin->lookup_fn(mem_ctx, cr, cr->data, cr->domain, &result);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina if (ret == EOK && (result == NULL || result->count == 0)) {
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina if (cr->plugin->only_one_result && result->count > 1) {
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Multiple objects were found when "
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "only one was expected!\n");
2af80640f18966d65cf82106059ce3c060df93bfamitkuma "ID [%s] was filtered out\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Object [%s] was not found in cache\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Unable to lookup [%s] in cache [%d]: %s\n",
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinacache_req_expiration_status(struct cache_req *cr,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina if (result == NULL || result->count == 0 || cr->plugin->bypass_cache) {
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina expire = ldb_msg_find_attr_as_uint64(result->msgs[0],
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina ret = sss_cmd_check_cache(result->msgs[0], cr->midpoint, expire);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* input data */
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* output data */
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic errno_t cache_req_search_dp(struct tevent_req *req,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic void cache_req_search_oob_done(struct tevent_req *subreq);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic void cache_req_search_done(struct tevent_req *subreq);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina req = tevent_req_create(mem_ctx, &state, struct cache_req_search_state);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
817e3ec31bbdb5447f4ffcd3302c558283b90943Pavel Březina CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr, "Looking up %s\n", cr->debugobj);
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina /* If bypass_cache is enabled we always contact data provider before
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina * searching the cache. Thus we set expiration status to missing,
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina * which will trigger data provider request later.
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina * If disabled, we want to search the cache here to see if the
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina * object is already cached and valid or if data provider needs
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina * to be contacted.
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina ret = cache_req_search_cache(state, cr, &state->result);
f63607bfcc01ad426efa20ed8ec65f429c9b2bd6Pavel Březina status = cache_req_expiration_status(cr, state->result);
606015a4f71d8ee809347188667d268f73110483Pavel Březina /* If bypass_dp is true but we found the object in this domain,
606015a4f71d8ee809347188667d268f73110483Pavel Březina * we will contact the data provider anyway to refresh it so
606015a4f71d8ee809347188667d268f73110483Pavel Březina * we can return it without searching the rest of the domains.
606015a4f71d8ee809347188667d268f73110483Pavel Březina "Object found, but needs to be refreshed.\n");
4c09cd008967c5c0ec358dc658ffc6fc1cef2697Fabiano Fidêncio ret = cache_req_search_ncache_filter(state, cr, &state->result);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic errno_t cache_req_search_dp(struct tevent_req *req,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina state = tevent_req_data(req, struct cache_req_search_state);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* Out of band update. The calling function will return the cached
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina * entry immediately. We need to use rctx so the request is not
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina * removed when state is freed. */
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Performing midpoint cache update of [%s]\n",
0dacb781f094b97e40694aeff288853a8a4e9d63Pavel Březina subreq = state->cr->plugin->dp_send_fn(state->rctx, state->cr,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band "
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "data provider request\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* This is non-fatal, so we'll continue here */
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina tevent_req_set_callback(subreq, cache_req_search_oob_done, req);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Looking up [%s] in data provider\n",
4df7aec645f87342f3a5146062abcb15f71f4fd9Pavel Březina subreq = state->cr->plugin->dp_send_fn(state->cr, state->cr,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Out of memory sending data provider request\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina tevent_req_set_callback(subreq, cache_req_search_done, req);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, state->cr,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic void cache_req_search_oob_done(struct tevent_req *subreq)
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, "Out of band request finished\n");
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinastatic void cache_req_search_done(struct tevent_req *subreq)
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina state = tevent_req_data(req, struct cache_req_search_state);
4df7aec645f87342f3a5146062abcb15f71f4fd9Pavel Březina state->dp_success = state->cr->plugin->dp_recv_fn(subreq, state->cr);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina /* Get result from cache again. */
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio ret = cache_req_search_cache(state, state->cr, &state->result);
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio /* Only store entry in negative cache if DP request succeeded
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio * because only then we know that the entry does not exist. */
4ef0b19a5e8a327443d027e57487c8a1e4f654ceFabiano Fidêncio /* ret == EOK */
c8193b1602cf44740b59f5dfcdc5330508c0c365Fabiano Fidêncio ret = cache_req_search_ncache_filter(state, state->cr, &state->result);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina "Returning updated object [%s]\n", state->cr->debugobj);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březinaerrno_t cache_req_search_recv(TALLOC_CTX *mem_ctx,
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina state = tevent_req_data(req, struct cache_req_search_state);
2749964664a69bbb99d09409c1110095cbfcc664Pavel Březina *_result = talloc_steal(mem_ctx, state->result);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozekstatic void cache_req_locate_domain_done(struct tevent_req *subreq);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozekstruct tevent_req *cache_req_locate_domain_send(TALLOC_CTX *mem_ctx,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek req = tevent_req_create(mem_ctx, &state, struct cache_req_locate_domain_state);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek should_run = cr->plugin->dp_get_domain_check_fn(cr->rctx,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek if (should_run == false) {
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek /* The request was tried too recently, don't issue a new one
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek * as its results are still valid
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek subreq = cr->plugin->dp_get_domain_send_fn(state,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek tevent_req_set_callback(subreq, cache_req_locate_domain_done, req);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozekstatic void cache_req_locate_domain_done(struct tevent_req *subreq)
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek req = tevent_req_callback_data(subreq, struct tevent_req);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek state = tevent_req_data(req, struct cache_req_locate_domain_state);
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek ret = state->cr->plugin->dp_get_domain_recv_fn(state,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozekerrno_t cache_req_locate_domain_recv(TALLOC_CTX *mem_ctx,
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek struct cache_req_locate_domain_state *state = NULL;
0a0b34f5fbe8f4a8c533a7d65f0f2961ee264054Jakub Hrozek state = tevent_req_data(req, struct cache_req_locate_domain_state);