Index: ft_node_cache.c
===================================================================
RCS file: /cvsroot/gift/OpenFT/src/ft_node_cache.c,v
retrieving revision 1.17
diff -u -r1.17 ft_node_cache.c
--- ft_node_cache.c	2 Nov 2003 12:09:06 -0000	1.17
+++ ft_node_cache.c	16 May 2004 22:44:12 -0000
@@ -31,6 +31,22 @@
 
 /*****************************************************************************/
 
+struct cache_state {
+	FILE    *f;
+	BOOL     error;
+	BOOL     unconfirmed;
+	ft_class_t klass;
+};
+
+static ft_class_t class_priority[]=
+{
+	FT_NODE_INDEX,
+	FT_NODE_SEARCH,
+	FT_NODE_USER
+};
+
+#define PRIO_LEN (sizeof(class_priority) / sizeof(ft_class_t))
+
 static int import_cache (FILE *f, char *path)
 {
 	FTNode        *node;
@@ -137,11 +153,17 @@
 
 /*****************************************************************************/
 
-static int write_node_cache (FTNode *node, FILE *f)
+static int write_node (FTNode *node, struct cache_state *state)
 {
 	time_t     vitality;
 	time_t     uptime;
 	ft_class_t klass;
+	int        wrote;
+
+	/* make sure the class we're interested in is the most
+	 * significant class this node has */
+	if ((node->ninfo.klass & FT_NODE_CLASSPRI_MASK) >= (state->klass << 1))
+		return FALSE;
 
 	/* no reason to write out firewalled nodes or users which we would
 	 * deny a connection to anyway... */
@@ -159,6 +181,11 @@
 	else
 		vitality = node->last_session;
 
+	/* Don't store nodes we've never connected to, unless we're
+	   desperate */
+	if (state->unconfirmed ^ !vitality)
+		return FALSE;
+
 	/*
 	 * Calculate the current uptime by determining the last known recorded
 	 * uptime (set at session close or when reading from the nodes file) and
@@ -171,73 +198,65 @@
 	 * and parent relationships) */
 	klass = ft_node_class (node, FALSE);
 
-	fprintf (f, "%li %li %s %hu %hu %hu %u\n",
+	wrote = fprintf (state->f, "%li %li %s %hu %hu %hu %u\n",
 	         (long)vitality, (long)uptime, net_ip_str (node->ninfo.host),
 	         node->ninfo.port_openft, node->ninfo.port_http,
 	         (unsigned short)klass, (unsigned int)node->version);
 
-	return TRUE;
-}
-
-static BOOL write_node_index (FTNode *node, FILE *f)
-{
-	return write_node_cache (node, f);
-}
-
-static BOOL write_node_search (FTNode *node, FILE *f)
-{
-	if (node->ninfo.klass & FT_NODE_INDEX)
-		return FALSE;
-
-	return write_node_cache (node, f);
-}
+	if (!wrote)
+	{
+		if (!state->error)
+			FT->err (FT, "error writing nodes cache: %s", platform_error ());
 
-static BOOL write_node_user (FTNode *node, FILE *f)
-{
-	if (node->ninfo.klass & FT_NODE_SEARCH)
+		state->error = TRUE;
+		
 		return FALSE;
-
-	return write_node_cache (node, f);
+	}
+		
+	return TRUE;
 }
 
 static int rewrite_cache (char *path)
 {
-	FILE *f;
 	char *pathtmp;
 	int   nodes;
 	int   remaining;
+	int   i;
 
+	struct cache_state state;
+	
 	/* use a temp path so we dont clobber the original if something goes
 	 * haywire */
 	if (!(pathtmp = stringf ("%s.tmp", path)))
 		return 0;
 
-	if (!(f = fopen (pathtmp, "w")))
+	if (!(state.f = fopen (pathtmp, "w")))
 	{
 		FT->err (FT, "can't create %s: %s", pathtmp, GIFT_STRERROR());
 		return 0;
 	}
 
-	/* loop through all nodes and write them out to the nodes cache */
-	nodes  = ft_netorg_foreach (FT_NODE_INDEX, FT_NODE_STATEANY, 0,
-	                            FT_NETORG_FOREACH(write_node_index), f);
-	nodes += ft_netorg_foreach (FT_NODE_SEARCH, FT_NODE_STATEANY, 0,
-	                            FT_NETORG_FOREACH(write_node_search), f);
-
-	/* determine the remaining number of nodes we can write to the cache */
-	remaining = FT_CFG_NODES_CACHE_MAX - nodes;
+	nodes = 0;
+	state.error = FALSE;
 
-	/* fill in the rest with user nodes... */
-	if (remaining > 0)
+	for (i = 0; i < PRIO_LEN * 2; i++)
 	{
-		ft_netorg_foreach (FT_NODE_USER, FT_NODE_STATEANY, remaining,
-		                   FT_NETORG_FOREACH(write_node_user), f);
+		remaining = FT_CFG_NODES_CACHE_MAX - nodes;
+		if (remaining <= 0)
+			break;
+
+		state.klass = class_priority[i % PRIO_LEN];
+		state.unconfirmed = (i >= PRIO_LEN);
+		nodes += ft_netorg_foreach (state.klass, FT_NODE_STATEANY, remaining,
+	                            FT_NETORG_FOREACH(write_node), &state);
 	}
 
-	fclose (f);
+	if (fclose (state.f))
+		state.error = TRUE;
 
 	/* get rid of the temp path */
-	file_mv (pathtmp, path);
+	if (!state.error)
+		file_mv (pathtmp, path);
 
 	return nodes;
 }

