/** * Pickup a cache randomly from the known set. If there's no URL used that * has not been used recently, NULL will be returned. The timestamp for * the picked URL is updated automatically. * * Try to avoid using default bootstrapping URLs if we have more than the * minimum set of caches in stock... * * @return a GWebCache URL or NULL on failure. */ static const char * gwc_pick(void) { int count = hset_count(gwc_known_url); int idx, i; const char *url = NULL; time_t now = tm_time(); if (0 == count) return NULL; g_assert(count > 0); g_assert(count <= MAX_GWC_URLS); g_assert(count == MAX_GWC_URLS || gwc_url_slot < count); idx = random_value(count - 1); for (i = 0; i < count; i++) { time_t stamp = gwc_url[idx].stamp; if (0 == stamp || delta_time(now, stamp) > 3900) { url = gwc_url[idx].url; gwc_url[idx].stamp = now; break; } } if (GNET_PROPERTY(bootstrap_debug) && url) g_message("GWC picked webcache \"%s\"", url); return url; }
/** * Clear all results from search. */ void search_gui_clear_search(search_t *search) { g_assert(search); g_assert(search->dups); search_gui_clear_tree(search); search_gui_clear_queue(search); g_assert(0 == hset_count(search->dups)); g_assert(0 == htable_count(search->parents)); }
/** * Initialize web cache. */ void gwc_init(void) { uint i; gwc_known_url = hset_create(HASH_KEY_STRING, 0); gwc_failed_url = hset_create(HASH_KEY_STRING, 0); gwc_retrieve(); if (0 == hset_count(gwc_known_url)) { for (i = 0; i < N_ITEMS(boot_url) && boot_url[i]; i++) gwc_add(boot_url[i]); } }
/** * Removes the URL from the set of known URL, but do not free its memory * and keeps it in the set of failed URLs for the session. */ static void gwc_forget_url(const char *url) { struct gwc url_tmp[MAX_GWC_URLS]; /* Temporary copy */ int count = hset_count(gwc_known_url); int i; int j = 0; g_assert(count > 0); g_assert(count <= MAX_GWC_URLS); g_assert(count == MAX_GWC_URLS || gwc_url_slot < count); g_assert(gwc_url_slot >= 0); STATIC_ASSERT(sizeof(url_tmp) == sizeof(gwc_url)); if (GNET_PROPERTY(bootstrap_debug)) g_warning("forgetting GWC URL \"%s\"", url); /* * It is possible that the URL we're trying to forget was * already removed from the cache if it was at a slot overridden * in the round-robin buffer, should we have got new GWC URL since * it was selected. */ if (hset_contains(gwc_known_url, url)) hset_remove(gwc_known_url, url); else { if (GNET_PROPERTY(bootstrap_debug)) g_warning("URL was already gone from GWC"); return; } hset_insert(gwc_failed_url, url); /* * Because we have a round-robin buffer, removing something in the * middle of the buffer is not straightforward. The `gwc_url_slot' * variable points to the last filled value in the buffer. * * We're going to build a copy in url_tmp[], filled from 0 to "count - 1", * and we'll move back that copy into the regular gwc_url[] cache. * The reason is that since there will be less entries in the cache * than the maximum amount, the round-robin buffer must be linearily * filled from 0 and upwards. */ memset(url_tmp, 0, sizeof(url_tmp)); if (count == MAX_GWC_URLS) { /* Buffer was full */ for (i = gwc_url_slot;;) { if (gwc_url[i].url != url) /* Atoms: we can compare addresses */ url_tmp[j++] = gwc_url[i]; i++; if (i == MAX_GWC_URLS) i = 0; if (i == gwc_url_slot) /* Back to where we started */ break; } } else { /* Buffer was partially filled */ for (i = 0; i <= gwc_url_slot; i++) { if (gwc_url[i].url != url) /* Atoms: we can compare addresses */ url_tmp[j++] = gwc_url[i]; } } count--; /* New amount of data in cache */ gwc_url_slot = j - 1; /* Last position we filled */ gwc_url_slot = MAX(0, gwc_url_slot); /* If we removed ALL entries */ g_assert(gwc_url_slot == MAX(0, count - 1)); memcpy(gwc_url, url_tmp, sizeof(gwc_url)); g_assert(gwc_url_slot >= 0 && gwc_url_slot < MAX_GWC_URLS); gwc_file_dirty = TRUE; }