static void next_expiry(AvahiCache *c, AvahiCacheEntry *e, unsigned percent) { AvahiUsec usec, left, right; time_t now; assert(c); assert(e); assert(percent > 0 && percent <= 100); usec = (AvahiUsec) e->record->ttl * 10000; left = usec * percent; right = usec * (percent+2); /* 2% jitter */ now = time(NULL); if (now >= c->last_rand_timestamp + 10) { c->last_rand = rand(); c->last_rand_timestamp = now; } usec = left + (AvahiUsec) ((double) (right-left) * c->last_rand / (RAND_MAX+1.0)); e->expiry = e->timestamp; avahi_timeval_add(&e->expiry, usec); /* g_message("wake up in +%lu seconds", e->expiry.tv_sec - e->timestamp.tv_sec); */ update_time_event(c, e); }
static void expire_in_one_second(AvahiCache *c, AvahiCacheEntry *e, AvahiCacheEntryState state) { assert(c); assert(e); e->state = state; gettimeofday(&e->expiry, NULL); avahi_timeval_add(&e->expiry, 1000000); /* 1s */ update_time_event(c, e); }
static void add_to_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) { AvahiWideAreaCacheEntry *c; int is_new; assert(e); assert(r); if ((c = find_record_in_cache(e, r))) { is_new = 0; /* Update the existing entry */ avahi_record_unref(c->record); } else { AvahiWideAreaCacheEntry *t; is_new = 1; /* Enforce cache size */ if (e->cache_n_entries >= CACHE_ENTRIES_MAX) /* Eventually we should improve the caching algorithm here */ goto finish; c = avahi_new(AvahiWideAreaCacheEntry, 1); c->engine = e; c->time_event = NULL; AVAHI_LLIST_PREPEND(AvahiWideAreaCacheEntry, cache, e->cache, c); /* Add the new entry to the cache entry hash table */ t = avahi_hashmap_lookup(e->cache_by_key, r->key); AVAHI_LLIST_PREPEND(AvahiWideAreaCacheEntry, by_key, t, c); avahi_hashmap_replace(e->cache_by_key, avahi_key_ref(r->key), t); e->cache_n_entries ++; } c->record = avahi_record_ref(r); gettimeofday(&c->timestamp, NULL); c->expiry = c->timestamp; avahi_timeval_add(&c->expiry, r->ttl * 1000000); if (c->time_event) avahi_time_event_update(c->time_event, &c->expiry); else c->time_event = avahi_time_event_new(e->server->time_event_queue, &c->expiry, expiry_event, c); finish: if (is_new) run_callbacks(e, r); }
struct timeval *avahi_elapse_time(struct timeval *tv, unsigned msec, unsigned jitter) { assert(tv); gettimeofday(tv, NULL); if (msec) avahi_timeval_add(tv, (AvahiUsec) msec*1000); if (jitter) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int last_rand; static time_t timestamp = 0; time_t now; int r; now = time(NULL); pthread_mutex_lock(&mutex); if (now >= timestamp + 10) { timestamp = now; last_rand = rand(); } r = last_rand; pthread_mutex_unlock(&mutex); /* We use the same jitter for 10 seconds. That way our * time events elapse in bursts which has the advantage that * packet data can be aggregated better */ avahi_timeval_add(tv, (AvahiUsec) (jitter*1000.0*r/(RAND_MAX+1.0))); } return tv; }
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) { struct timeval a = { 5, 5 }, b; b = a; printf("%li.%li\n", a.tv_sec, a.tv_usec); avahi_timeval_add(&a, -50); printf("%li.%li\n", a.tv_sec, a.tv_usec); printf("%lli\n", (long long) avahi_timeval_diff(&a, &b)); return 0; }
int avahi_s_entry_group_commit(AvahiSEntryGroup *g) { struct timeval now; assert(g); assert(!g->dead); if (g->state != AVAHI_ENTRY_GROUP_UNCOMMITED && g->state != AVAHI_ENTRY_GROUP_COLLISION) return avahi_server_set_errno(g->server, AVAHI_ERR_BAD_STATE); if (avahi_s_entry_group_is_empty(g)) return avahi_server_set_errno(g->server, AVAHI_ERR_IS_EMPTY); g->n_register_try++; avahi_timeval_add(&g->register_time, 1000*(g->n_register_try >= AVAHI_RR_RATE_LIMIT_COUNT ? AVAHI_RR_HOLDOFF_MSEC_RATE_LIMIT : AVAHI_RR_HOLDOFF_MSEC)); gettimeofday(&now, NULL); if (avahi_timeval_compare(&g->register_time, &now) <= 0) { /* Holdoff time passed, so let's start probing */ entry_group_commit_real(g); } else { /* Holdoff time has not yet passed, so let's wait */ assert(!g->register_time_event); g->register_time_event = avahi_time_event_new(g->server->time_event_queue, &g->register_time, entry_group_register_time_event_callback, g); avahi_s_entry_group_change_state(g, AVAHI_ENTRY_GROUP_REGISTERING); } return AVAHI_OK; }