aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_namespace.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-01-11 10:28:07 +0000
committerChristian Grothoff <christian@grothoff.org>2011-01-11 10:28:07 +0000
commit9dccfed7fc149542bb836da4243f105dec485114 (patch)
tree5d361d801a29e8410159fb9fe551536d271d28ee /src/fs/fs_namespace.c
parenta6192b717590e4850a28591383775dd56e403a94 (diff)
downloadgnunet-9dccfed7fc149542bb836da4243f105dec485114.tar.gz
gnunet-9dccfed7fc149542bb836da4243f105dec485114.zip
trying to fix SVN 1640
Diffstat (limited to 'src/fs/fs_namespace.c')
-rw-r--r--src/fs/fs_namespace.c127
1 files changed, 69 insertions, 58 deletions
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c
index 91502e1de..bc66bb21f 100644
--- a/src/fs/fs_namespace.c
+++ b/src/fs/fs_namespace.c
@@ -1032,9 +1032,9 @@ process_update_node (void *cls,
1032 1032
1033 1033
1034/** 1034/**
1035 * Closure for 'find_sccs'. 1035 * Closure for 'find_trees'.
1036 */ 1036 */
1037struct FindSccClosure 1037struct FindTreeClosure
1038{ 1038{
1039 /** 1039 /**
1040 * Namespace we are operating on. 1040 * Namespace we are operating on.
@@ -1042,14 +1042,14 @@ struct FindSccClosure
1042 struct GNUNET_FS_Namespace *namespace; 1042 struct GNUNET_FS_Namespace *namespace;
1043 1043
1044 /** 1044 /**
1045 * Array with 'head's of SCCs. 1045 * Array with 'head's of TREEs.
1046 */ 1046 */
1047 struct NamespaceUpdateNode **scc_array; 1047 struct NamespaceUpdateNode **tree_array;
1048 1048
1049 /** 1049 /**
1050 * Size of 'scc_array' 1050 * Size of 'tree_array'
1051 */ 1051 */
1052 unsigned int scc_array_size; 1052 unsigned int tree_array_size;
1053 1053
1054 /** 1054 /**
1055 * Current generational ID used. 1055 * Current generational ID used.
@@ -1057,7 +1057,7 @@ struct FindSccClosure
1057 unsigned int nug; 1057 unsigned int nug;
1058 1058
1059 /** 1059 /**
1060 * Identifier for the current SCC, or UINT_MAX for none yet. 1060 * Identifier for the current TREE, or UINT_MAX for none yet.
1061 */ 1061 */
1062 unsigned int id; 1062 unsigned int id;
1063}; 1063};
@@ -1065,15 +1065,18 @@ struct FindSccClosure
1065 1065
1066/** 1066/**
1067 * Find all nodes reachable from the current node (including the 1067 * Find all nodes reachable from the current node (including the
1068 * current node itself). If they are in no SCC, add them to the 1068 * current node itself). If they are in no tree, add them to the
1069 * current one. If they are the head of another SCC, merge the 1069 * current one. If they are the head of another tree, merge the
1070 * SCCs. If they are in the middle of another SCC, let them be. 1070 * trees. If they are in the middle of another tree, let them be.
1071 * We can tell that a node is already in an SCC by checking if 1071 * We can tell that a node is already in an tree by checking if
1072 * its 'nug' field is set to the current 'nug' value. It is the 1072 * its 'nug' field is set to the current 'nug' value. It is the
1073 * head of an SCC if it is in the 'scc_array' under its respective 1073 * head of an tree if it is in the 'tree_array' under its respective
1074 * 'scc_id'. 1074 * 'tree_id'.
1075 * 1075 *
1076 * @param cls closure (of type 'struct FindSccClosure') 1076 * In short, we're trying to find the smallest number of tree to
1077 * cover a directed graph.
1078 *
1079 * @param cls closure (of type 'struct FindTreeClosure')
1077 * @param key current key code 1080 * @param key current key code
1078 * @param value value in the hash map 1081 * @param value value in the hash map
1079 * @return GNUNET_YES if we should continue to 1082 * @return GNUNET_YES if we should continue to
@@ -1081,34 +1084,40 @@ struct FindSccClosure
1081 * GNUNET_NO if not. 1084 * GNUNET_NO if not.
1082 */ 1085 */
1083static int 1086static int
1084find_sccs (void *cls, 1087find_trees (void *cls,
1085 const GNUNET_HashCode * key, 1088 const GNUNET_HashCode * key,
1086 void *value) 1089 void *value)
1087{ 1090{
1088 struct FindSccClosure *fc = cls; 1091 struct FindTreeClosure *fc = cls;
1089 struct NamespaceUpdateNode *nsn = value; 1092 struct NamespaceUpdateNode *nsn = value;
1090 GNUNET_HashCode hc; 1093 GNUNET_HashCode hc;
1091 1094
1092 if (nsn->nug == fc->nug) 1095 if (nsn->nug == fc->nug)
1093 { 1096 {
1094 if (fc->scc_array[nsn->scc_id] != nsn) 1097 if (nsn->tree_id == UINT_MAX)
1095 return GNUNET_YES; /* part of another SCC, end trace */ 1098 return GNUNET_YES; /* circular */
1096 if (nsn->scc_id == fc->id) 1099 GNUNET_assert (nsn->tree_id < fc->tree_array_size);
1097 return GNUNET_YES; /* that's us */ 1100 if (fc->tree_array[nsn->tree_id] != nsn)
1098 fc->scc_array[nsn->scc_id] = NULL; 1101 return GNUNET_YES; /* part of "another" (directed) TREE,
1102 and not root of it, end trace */
1103 if (nsn->tree_id == fc->id)
1104 return GNUNET_YES; /* that's our own root (can this be?) */
1105 /* merge existing TREE, we have a root for both */
1106 fc->tree_array[nsn->tree_id] = NULL;
1099 if (fc->id == UINT_MAX) 1107 if (fc->id == UINT_MAX)
1100 fc->id = nsn->scc_id; /* take over ID */ 1108 fc->id = nsn->tree_id; /* take over ID */
1101 } 1109 }
1102 else 1110 else
1103 { 1111 {
1104 nsn->nug = fc->nug; 1112 nsn->nug = fc->nug;
1113 nsn->tree_id = UINT_MAX; /* mark as undef */
1105 /* trace */ 1114 /* trace */
1106 GNUNET_CRYPTO_hash (nsn->update, 1115 GNUNET_CRYPTO_hash (nsn->update,
1107 strlen (nsn->update), 1116 strlen (nsn->update),
1108 &hc); 1117 &hc);
1109 GNUNET_CONTAINER_multihashmap_get_multiple (fc->namespace->update_map, 1118 GNUNET_CONTAINER_multihashmap_get_multiple (fc->namespace->update_map,
1110 &hc, 1119 &hc,
1111 &find_sccs, 1120 &find_trees,
1112 fc); 1121 fc);
1113 } 1122 }
1114 return GNUNET_YES; 1123 return GNUNET_YES;
@@ -1123,15 +1132,17 @@ find_sccs (void *cls,
1123 * 1132 *
1124 * Calling this function with "next_id" NULL will cause the library to 1133 * Calling this function with "next_id" NULL will cause the library to
1125 * call "ip" with a root for each strongly connected component of the 1134 * call "ip" with a root for each strongly connected component of the
1126 * graph (a root being a node from which all other nodes in the Scc 1135 * graph (a root being a node from which all other nodes in the Tree
1127 * are reachable). 1136 * are reachable).
1128 * 1137 *
1129 * Calling this function with "next_id" being the name of a node will 1138 * Calling this function with "next_id" being the name of a node will
1130 * cause the library to call "ip" with all children of the node. Note 1139 * cause the library to call "ip" with all children of the node. Note
1131 * that cycles within an SCC are possible (including self-loops). 1140 * that cycles within the final tree are possible (including self-loops).
1141 * I know, odd definition of a tree, but the GUI will display an actual
1142 * tree (GtkTreeView), so that's what counts for the term here.
1132 * 1143 *
1133 * @param namespace namespace to inspect for updateable content 1144 * @param namespace namespace to inspect for updateable content
1134 * @param next_id ID to look for; use NULL to look for SCC roots 1145 * @param next_id ID to look for; use NULL to look for tree roots
1135 * @param ip function to call on each updateable identifier 1146 * @param ip function to call on each updateable identifier
1136 * @param ip_cls closure for ip 1147 * @param ip_cls closure for ip
1137 */ 1148 */
@@ -1146,7 +1157,7 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1146 GNUNET_HashCode hc; 1157 GNUNET_HashCode hc;
1147 struct NamespaceUpdateNode *nsn; 1158 struct NamespaceUpdateNode *nsn;
1148 struct ProcessUpdateClosure pc; 1159 struct ProcessUpdateClosure pc;
1149 struct FindSccClosure fc; 1160 struct FindTreeClosure fc;
1150 1161
1151 if (namespace->update_nodes == NULL) 1162 if (namespace->update_nodes == NULL)
1152 read_update_information_graph (namespace); 1163 read_update_information_graph (namespace);
@@ -1190,12 +1201,12 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1190 } 1201 }
1191#if DEBUG_NAMESPACE 1202#if DEBUG_NAMESPACE
1192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1193 "Calculating SCCs to find roots of update trees\n"); 1204 "Calculating TREEs to find roots of update trees\n");
1194#endif 1205#endif
1195 /* Find heads of SCCs in update graph */ 1206 /* Find heads of TREEs in update graph */
1196 nug = ++namespace->nug_gen; 1207 nug = ++namespace->nug_gen;
1197 fc.scc_array = NULL; 1208 fc.tree_array = NULL;
1198 fc.scc_array_size = 0; 1209 fc.tree_array_size = 0;
1199 1210
1200 for (i=0;i<namespace->update_node_count;i++) 1211 for (i=0;i<namespace->update_node_count;i++)
1201 { 1212 {
@@ -1204,11 +1215,11 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1204 { 1215 {
1205#if DEBUG_NAMESPACE 1216#if DEBUG_NAMESPACE
1206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1207 "SCC of node `%s' is %u\n", 1218 "TREE of node `%s' is %u\n",
1208 nsn->id, 1219 nsn->id,
1209 nsn->nug); 1220 nsn->nug);
1210#endif 1221#endif
1211 continue; /* already placed in SCC */ 1222 continue; /* already placed in TREE */
1212 } 1223 }
1213 GNUNET_CRYPTO_hash (nsn->update, 1224 GNUNET_CRYPTO_hash (nsn->update,
1214 strlen (nsn->update), 1225 strlen (nsn->update),
@@ -1219,66 +1230,66 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1219 fc.namespace = namespace; 1230 fc.namespace = namespace;
1220 GNUNET_CONTAINER_multihashmap_get_multiple (namespace->update_map, 1231 GNUNET_CONTAINER_multihashmap_get_multiple (namespace->update_map,
1221 &hc, 1232 &hc,
1222 &find_sccs, 1233 &find_trees,
1223 &fc); 1234 &fc);
1224 if (fc.id == UINT_MAX) 1235 if (fc.id == UINT_MAX)
1225 { 1236 {
1226 /* start new SCC */ 1237 /* start new TREE */
1227 for (fc.id=0;fc.id<fc.scc_array_size;fc.id++) 1238 for (fc.id=0;fc.id<fc.tree_array_size;fc.id++)
1228 { 1239 {
1229 if (fc.scc_array[fc.id] == NULL) 1240 if (fc.tree_array[fc.id] == NULL)
1230 { 1241 {
1231 fc.scc_array[fc.id] = nsn; 1242 fc.tree_array[fc.id] = nsn;
1232 nsn->scc_id = fc.id; 1243 nsn->tree_id = fc.id;
1233 break; 1244 break;
1234 } 1245 }
1235 } 1246 }
1236 if (fc.id == fc.scc_array_size) 1247 if (fc.id == fc.tree_array_size)
1237 { 1248 {
1238 GNUNET_array_append (fc.scc_array, 1249 GNUNET_array_append (fc.tree_array,
1239 fc.scc_array_size, 1250 fc.tree_array_size,
1240 nsn); 1251 nsn);
1241 nsn->scc_id = fc.id; 1252 nsn->tree_id = fc.id;
1242 } 1253 }
1243#if DEBUG_NAMESPACE 1254#if DEBUG_NAMESPACE
1244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1245 "Starting new SCC %u with node `%s'\n", 1256 "Starting new TREE %u with node `%s'\n",
1246 nsn->scc_id, 1257 nsn->tree_id,
1247 nsn->id); 1258 nsn->id);
1248#endif 1259#endif
1249 /* put all nodes with same identifier into this SCC */ 1260 /* put all nodes with same identifier into this TREE */
1250 GNUNET_CRYPTO_hash (nsn->id, 1261 GNUNET_CRYPTO_hash (nsn->id,
1251 strlen (nsn->id), 1262 strlen (nsn->id),
1252 &hc); 1263 &hc);
1253 fc.id = nsn->scc_id; 1264 fc.id = nsn->tree_id;
1254 fc.nug = nug; 1265 fc.nug = nug;
1255 fc.namespace = namespace; 1266 fc.namespace = namespace;
1256 GNUNET_CONTAINER_multihashmap_get_multiple (namespace->update_map, 1267 GNUNET_CONTAINER_multihashmap_get_multiple (namespace->update_map,
1257 &hc, 1268 &hc,
1258 &find_sccs, 1269 &find_trees,
1259 &fc); 1270 &fc);
1260 } 1271 }
1261 else 1272 else
1262 { 1273 {
1263 /* make head of SCC "id" */ 1274 /* make head of TREE "id" */
1264 fc.scc_array[fc.id] = nsn; 1275 fc.tree_array[fc.id] = nsn;
1265 nsn->scc_id = fc.id; 1276 nsn->tree_id = fc.id;
1266 } 1277 }
1267#if DEBUG_NAMESPACE 1278#if DEBUG_NAMESPACE
1268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1269 "SCC of node `%s' is %u\n", 1280 "TREE of node `%s' is %u\n",
1270 nsn->id, 1281 nsn->id,
1271 fc.id); 1282 fc.id);
1272#endif 1283#endif
1273 } 1284 }
1274 for (i=0;i<fc.scc_array_size;i++) 1285 for (i=0;i<fc.tree_array_size;i++)
1275 { 1286 {
1276 nsn = fc.scc_array[i]; 1287 nsn = fc.tree_array[i];
1277 if (NULL != nsn) 1288 if (NULL != nsn)
1278 { 1289 {
1279#if DEBUG_NAMESPACE 1290#if DEBUG_NAMESPACE
1280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1281 "Root of SCC %u is node `%s'\n", 1292 "Root of TREE %u is node `%s'\n",
1282 i, 1293 i,
1283 nsn->id); 1294 nsn->id);
1284#endif 1295#endif
@@ -1290,12 +1301,12 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *namespace,
1290 nsn->update); 1301 nsn->update);
1291 } 1302 }
1292 } 1303 }
1293 GNUNET_array_grow (fc.scc_array, 1304 GNUNET_array_grow (fc.tree_array,
1294 fc.scc_array_size, 1305 fc.tree_array_size,
1295 0); 1306 0);
1296#if DEBUG_NAMESPACE 1307#if DEBUG_NAMESPACE
1297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1298 "Done processing SCCs\n"); 1309 "Done processing TREEs\n");
1299#endif 1310#endif
1300} 1311}
1301 1312