static uint32_t mc_action_get_exp_time(void) { struct mm_core *core = mm_core_selfptr(); mm_timeval_t real_time = mm_core_getrealtime(core); return real_time / 1000000; // useconds -> seconds. }
static bool mc_action_find_victims(struct mc_tpart *part, struct mm_stack *victims, uint32_t nrequired) { uint32_t nvictims = 0; mm_stack_prepare(victims); struct mm_core *core = mm_core_selfptr(); mm_timeval_t real_time = mm_core_getrealtime(core); uint32_t time = real_time / 1000000; // useconds -> seconds. bool end = false; while (nvictims < nrequired) { struct mc_entry *hand = part->clock_hand; if (unlikely(hand == part->entries_end)) { // Prevent infinite loop. if (end) break; else end = true; hand = part->entries; } uint8_t state = hand->state; if (state >= MC_ENTRY_USED_MIN && state <= MC_ENTRY_USED_MAX) { if (mc_action_is_eviction_victim(part, hand, time)) { uint32_t index = mc_table_index(part, hand->hash); struct mm_stack *bucket = &part->buckets[index]; mc_action_remove_entry(part, &bucket->head, hand); mm_stack_insert(victims, &hand->link); ++nvictims; } else { hand->state--; } } part->clock_hand = hand + 1; } return (nvictims > 0 && nvictims == nrequired); }
static void mc_command_flush(uint32_t exptime) { // TODO: really use the exptime. struct mm_core *core = mm_core_selfptr(); mm_timeval_t real_time = mm_core_getrealtime(core); mc_exptime = real_time / 1000000 + exptime; for (mm_core_t i = 0; i < mc_table.nparts; i++) { #if ENABLE_MEMCACHE_DELEGATE struct mc_tpart *part = &mc_table.parts[i]; mm_core_post(part->core, mc_command_flush_routine, i); #else struct mc_action action; action.part = &mc_table.parts[i]; mc_action_flush(&action); #endif } }