#if ! defined(TMPL_TYPE) #error "TMPL_TYPE must be defined before #include" #endif #ifndef LOOKUP_FN #define LOOKUP_FN(type) APPEND(_nss_memcache_lookup_, type) #endif enum return_t LOOKUP_FN(TMPL_TYPE)(const char *key, size_t keylen, struct TMPL_TYPE *result, char *buffer, size_t buflen) { memcache_result_t *res = NULL; DENTER; DLOG("checking for missing backend"); NSMC(initialize_connection)(); // TODO close connection after lookups are done. THis will release sigpipe // handler in memcache-lite... LOCK(backend); if (mc == NULL) { UNLOCK(backend); dreturn(RETURN_FAILURE); } UNLOCK(backend); res = memcache_result_new(); DLOG("searching backend for match"); LOCK(backend); memcache_get(mc, key, res); UNLOCK(backend); if (res == NULL || !memcache_result_found(res)) { DLOG("no backend match"); memcache_result_free(res); NSMC(destroy_connection)(); dreturn(RETURN_FAILURE); } DLOG("match from backend of size %u", memcache_result_size(res)); if (memcache_result_size(res) == 0) { DLOG("negative cache hit: %s", key); memcache_result_free(res); NSMC(destroy_connection)(); dreturn(RETURN_SKIP); } else if (memcache_result_size(res) < sizeof(struct TMPL_TYPE)) { DLOG("matched data smaller than sizeof(struct TMPL_TYPE)."); DLOG("purging bad data."); LOCK(backend); memcache_del(mc, key, 0); UNLOCK(backend); DLOG("purge done."); memcache_result_free(res); NSMC(destroy_connection)(); dreturn(RETURN_FAILURE); } else if ((memcache_result_size(res) - sizeof(struct TMPL_TYPE)) > buflen) { DLOG("matched data too big for buffer - falling through"); DLOG("%u > %u", (memcache_result_size(res) - sizeof(struct TMPL_TYPE)), buflen); memcache_result_free(res); NSMC(destroy_connection)(); dreturn(RETURN_FAILURE); } // do pwbufp checking, etc earlier memcpy(result, memcache_result_data(res), sizeof(struct TMPL_TYPE)); memcpy(buffer, memcache_result_data(res) + sizeof(struct TMPL_TYPE), MIN(buflen, (memcache_result_size(res)-sizeof(struct TMPL_TYPE)))); memcache_result_free(res); NSMC(destroy_connection)(); dreturn(RETURN_SUCCESS); }