const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key) { const char *myname = "dict_cache_lookup"; const char *cache_val; DICT *db = cp->db; /* * Search for the cache entry. Don't return an entry that is scheduled * for delete-behind. */ if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) && DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) { if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s (pretend not found - scheduled for deletion)", myname, cache_key); DICT_ERR_VAL_RETURN(cp, DICT_ERR_NONE, (char *) 0); } else { cache_val = dict_get(db, cache_key); if (cache_val == 0 && db->error != 0) msg_rate_delay(&cp->get_log_stamp, cp->log_delay, msg_warn, "%s: cache lookup for '%s' failed due to error", cp->name, cache_key); if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s value=%s", myname, cache_key, cache_val ? cache_val : db->error ? "error" : "(not found)"); DICT_ERR_VAL_RETURN(cp, db->error, cache_val); } }
void dict_cache_update(DICT_CACHE *cp, const char *cache_key, const char *cache_val) { const char *myname = "dict_cache_update"; /* * Store the cache entry and cancel the delete-behind operation. */ if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) && DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) { if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: cancel delete-behind for key=%s", myname, cache_key); DC_CANCEL_DELETE_BEHIND(cp); } if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s value=%s", myname, cache_key, cache_val); dict_put(cp->db, cache_key, cache_val); }
const char *dict_cache_lookup(DICT_CACHE *cp, const char *cache_key) { const char *myname = "dict_cache_lookup"; const char *cache_val; /* * Search for the cache entry. Don't return an entry that is scheduled * for delete-behind. */ if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) && DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) { if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s (pretend not found - scheduled for deletion)", myname, cache_key); return (0); } else { cache_val = dict_get(cp->db, cache_key); if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s value=%s", myname, cache_key, cache_val ? cache_val : "(not found)"); return (cache_val); } }
int dict_cache_update(DICT_CACHE *cp, const char *cache_key, const char *cache_val) { const char *myname = "dict_cache_update"; DICT *db = cp->db; int put_res; /* * Store the cache entry and cancel the delete-behind operation. */ if (DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp) && DC_MATCH_SAVED_CURRENT_KEY(cp, cache_key)) { if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: cancel delete-behind for key=%s", myname, cache_key); DC_CANCEL_DELETE_BEHIND(cp); } if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s value=%s", myname, cache_key, cache_val); put_res = dict_put(db, cache_key, cache_val); if (put_res != 0) msg_rate_delay(&cp->upd_log_stamp, cp->log_delay, msg_warn, "%s: could not update entry for %s", cp->name, cache_key); DICT_ERR_VAL_RETURN(cp, db->error, put_res); }
int dict_cache_sequence(DICT_CACHE *cp, int first_next, const char **cache_key, const char **cache_val) { const char *myname = "dict_cache_sequence"; int seq_res; const char *raw_cache_key; const char *raw_cache_val; char *previous_curr_key; char *previous_curr_val; DICT *db = cp->db; /* * Find the first or next database entry. Hide the record with the cache * cleanup completion time stamp. */ seq_res = dict_seq(db, first_next, &raw_cache_key, &raw_cache_val); if (seq_res == 0 && strcmp(raw_cache_key, DC_LAST_CACHE_CLEANUP_COMPLETED) == 0) seq_res = dict_seq(db, DICT_SEQ_FUN_NEXT, &raw_cache_key, &raw_cache_val); if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: key=%s value=%s", myname, seq_res == 0 ? raw_cache_key : db->error ? "(error)" : "(not found)", seq_res == 0 ? raw_cache_val : db->error ? "(error)" : "(not found)"); if (db->error) msg_rate_delay(&cp->seq_log_stamp, cp->log_delay, msg_warn, "%s: sequence error", cp->name); /* * Save the current cache_key and cache_val before they are clobbered by * our own delete operation below. This also prevents surprises when the * application accesses the database after this function returns. * * We also use the saved cache_key to protect the current entry against * application delete requests. */ previous_curr_key = cp->saved_curr_key; previous_curr_val = cp->saved_curr_val; if (seq_res == 0) { cp->saved_curr_key = mystrdup(raw_cache_key); cp->saved_curr_val = mystrdup(raw_cache_val); } else { cp->saved_curr_key = 0; cp->saved_curr_val = 0; } /* * Delete behind. */ if (db->error == 0 && DC_IS_SCHEDULED_FOR_DELETE_BEHIND(cp)) { DC_CANCEL_DELETE_BEHIND(cp); if (cp->user_flags & DICT_CACHE_FLAG_VERBOSE) msg_info("%s: delete-behind key=%s value=%s", myname, previous_curr_key, previous_curr_val); if (dict_del(db, previous_curr_key) != 0) msg_rate_delay(&cp->del_log_stamp, cp->log_delay, msg_warn, "%s: could not delete entry for %s", cp->name, previous_curr_key); } /* * Clean up previous iteration key and value. */ if (previous_curr_key) myfree(previous_curr_key); if (previous_curr_val) myfree(previous_curr_val); /* * Return the result. */ *cache_key = (cp)->saved_curr_key; *cache_val = (cp)->saved_curr_val; DICT_ERR_VAL_RETURN(cp, db->error, seq_res); }