Exemplo n.º 1
0
/**
 * Callback for adns_resolve(), invoked when the resolution is complete.
 */
static void
uhc_host_resolved(const host_addr_t *addrs, size_t n, void *uu_udata)
{
	(void) uu_udata;
	g_assert(addrs);

	/*
	 * If resolution failed, try again if possible.
	 */

	if (0 == n) {
		if (GNET_PROPERTY(bootstrap_debug))
			g_warning("could not resolve UDP host cache \"%s\"",
				uhc_ctx.host);

		uhc_try_next();
		return;
	}

	if (n > 1) {
		size_t i;
		host_addr_t *hav;
		/* Current UHC was moved to tail by uhc_get_next() */
		struct uhc *uhc = hash_list_tail(uhc_list);

		/*
		 * UHC resolved to multiple endpoints. Could be roundrobbin or
		 * IPv4 and IPv6 addresss. Adding them as seperate entries: if the
		 * IPv6 is unreachable we have an opportunity to skip it.
		 * 		-- JA 24/7/2011
		 *
		 * Shuffle the address array before appending them to the UHC list.
		 *		--RAM, 2015-10-01
		 */

		hav = HCOPY_ARRAY(addrs, n);
		SHUFFLE_ARRAY_N(hav, n);

		for (i = 0; i < n; i++) {
			const char *host = host_addr_port_to_string(hav[i], uhc_ctx.port);
			g_debug("BOOT UDP host cache \"%s\" resolved to %s (#%zu)",
				uhc_ctx.host, host, i + 1);

			uhc_list_append(host);
		}

		hash_list_remove(uhc_list, uhc);	/* Replaced by IP address list */
		uhc_free(&uhc);

		/*
		 * We're going to continue and process the first address (in our
		 * shuffled array).  Make sure it is put at the end of the list
		 * and marked as being used, mimicing what uhc_get_next() would do.
		 *		--RAM, 2015-10-01
		 */

		{
			struct uhc key;

			key.host = host_addr_port_to_string(hav[0], uhc_ctx.port);
			uhc = hash_list_lookup(uhc_list, &key);
			g_assert(uhc != NULL);	/* We added the entry above! */
			uhc->stamp = tm_time();
			uhc->used++;
			hash_list_moveto_tail(uhc_list, uhc);
		}

		uhc_ctx.addr = hav[0];		/* Struct copy */
		HFREE_NULL(hav);
	} else {
		uhc_ctx.addr = addrs[0];
	}

	if (GNET_PROPERTY(bootstrap_debug))
		g_debug("BOOT UDP host cache \"%s\" resolved to %s",
			uhc_ctx.host, host_addr_to_string(uhc_ctx.addr));


	/*
	 * Now send the ping.
	 */

	uhc_send_ping();
}
Exemplo n.º 2
0
/**
 * Get a new index in the cache, and update LRU data structures.
 *
 * @param db	the database
 * @param num	page number in the DB for which we want a cache index
 *
 *
 * @return -1 on error, or the allocated cache index.
 */
static int
getidx(DBM *db, long num)
{
	struct lru_cache *cache = db->cache;
	long n;		/* Cache index */

	/*
	 * If we invalidated pages, reuse their indices.
	 * If we have not used all the pages yet, get the next one.
	 * Otherwise, use the least-recently requested page.
	 */

	if (slist_length(cache->available)) {
		void *v = slist_shift(cache->available);
		n = pointer_to_int(v);
		g_assert(n >= 0 && n < cache->pages);
		g_assert(!cache->dirty[n]);
		g_assert(-1 == cache->numpag[n]);
		hash_list_prepend(cache->used, int_to_pointer(n));
	} else if (cache->next < cache->pages) {
		n = cache->next++;
		cache->dirty[n] = FALSE;
		hash_list_prepend(cache->used, int_to_pointer(n));
	} else {
		void *last = hash_list_tail(cache->used);
		long oldnum;
		gboolean had_ioerr = booleanize(db->flags & DBM_IOERR_W);

		hash_list_moveto_head(cache->used, last);
		n = pointer_to_int(last);

		/*
		 * This page is no longer cached as its cache index is being reused
		 * Flush it to disk if dirty before discarding it.
		 */

		g_assert(n >= 0 && n < cache->pages);

		oldnum = cache->numpag[n];

		if (cache->dirty[n] && !writebuf(db, oldnum, n)) {
			hash_list_iter_t *iter;
			void *item;
			gboolean found = FALSE;

			/*
			 * Cannot flush dirty page now, probably because we ran out of
			 * disk space.  Look through the cache whether we can reuse a
			 * non-dirty page instead, which would let us keep the dirty
			 * page a little longer in the cache, in the hope it can then
			 * be properly flushed later.
			 */

			iter = hash_list_iterator_tail(cache->used);

			while (NULL != (item = hash_list_iter_previous(iter))) {
				long i = pointer_to_int(item);

				g_assert(i >= 0 && i < cache->pages);

				if (!cache->dirty[i]) {
					found = TRUE;	/* OK, reuse cache slot #i then */
					n = i;
					oldnum = cache->numpag[i];
					break;
				}
			}

			hash_list_iter_release(&iter);

			if (found) {
				g_assert(item != NULL);
				hash_list_moveto_head(cache->used, item);

				/*
				 * Clear error condition if we had none prior to the flush
				 * attempt, since we can do without it for now.
				 */

				if (!had_ioerr)
					db->flags &= ~DBM_IOERR_W;

				g_warning("sdbm: \"%s\": "
					"reusing cache slot used by clean page #%ld instead",
					sdbm_name(db), oldnum);
			} else {
				g_warning("sdbm: \"%s\": cannot discard dirty page #%ld",
					sdbm_name(db), oldnum);
				return -1;
			}
		}

		g_hash_table_remove(cache->pagnum, ulong_to_pointer(oldnum));
		cache->dirty[n] = FALSE;
	}

	/*
	 * Record the association between the cache index and the page number.
	 */

	g_assert(n >= 0 && n < cache->pages);

	cache->numpag[n] = num;
	g_hash_table_insert(cache->pagnum,
		ulong_to_pointer(num), int_to_pointer(n));

	return n;
}