+ unsigned int i;
+ unsigned int nug;
+ struct GNUNET_HashCode hc;
+ struct NamespaceUpdateNode *nsn;
+ struct ProcessUpdateClosure pc;
+ struct FindTreeClosure fc;
+ struct GNUNET_FS_UpdateInformationGraph *uig;
+
+ uig = read_update_information_graph (h, ns);
+ if (NULL == uig->update_nodes)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "No updateable nodes found for ID `%s'\n", next_id);
+ free_update_information_graph (uig);
+ return; /* no nodes */
+ }
+ uig->update_map =
+ GNUNET_CONTAINER_multihashmap_create (2 +
+ 3 * uig->update_node_count /
+ 4,
+ GNUNET_NO);
+ for (i = 0; i < uig->update_node_count; i++)
+ {
+ nsn = uig->update_nodes[i];
+ GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc);
+ GNUNET_CONTAINER_multihashmap_put (uig->update_map, &hc, nsn,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ }
+ if (NULL != next_id)
+ {
+ GNUNET_CRYPTO_hash (next_id, strlen (next_id), &hc);
+ pc.ip = ip;
+ pc.ip_cls = ip_cls;
+ GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc,
+ &process_update_node, &pc);
+ free_update_information_graph (uig);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Calculating TREEs to find roots of update trees\n");
+ /* Find heads of TREEs in update graph */
+ nug = ++uig->nug_gen;
+ fc.tree_array = NULL;
+ fc.tree_array_size = 0;
+
+ for (i = 0; i < uig->update_node_count; i++)
+ {
+ nsn = uig->update_nodes[i];
+ if (nsn->nug == nug)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id,
+ nsn->nug);
+ continue; /* already placed in TREE */
+ }
+ GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc);
+ nsn->nug = nug;
+ nsn->tree_id = UINT_MAX;
+ fc.id = UINT_MAX;
+ fc.nug = nug;
+ fc.uig = uig;
+ GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc,
+ &find_trees, &fc);
+ if (UINT_MAX == fc.id)
+ {
+ /* start new TREE */
+ for (fc.id = 0; fc.id < fc.tree_array_size; fc.id++)
+ {
+ if (NULL == fc.tree_array[fc.id])
+ {
+ fc.tree_array[fc.id] = nsn;
+ nsn->tree_id = fc.id;
+ break;
+ }
+ }
+ if (fc.id == fc.tree_array_size)
+ {
+ GNUNET_array_append (fc.tree_array, fc.tree_array_size, nsn);
+ nsn->tree_id = fc.id;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting new TREE %u with node `%s'\n", nsn->tree_id,
+ nsn->id);
+ /* put all nodes with same identifier into this TREE */
+ GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc);
+ fc.id = nsn->tree_id;
+ fc.nug = nug;
+ fc.uig = uig;
+ GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc,
+ &find_trees, &fc);
+ }
+ else
+ {
+ /* make head of TREE "id" */
+ fc.tree_array[fc.id] = nsn;
+ nsn->tree_id = fc.id;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TREE of node `%s' is %u\n", nsn->id,
+ fc.id);
+ }
+ for (i = 0; i < fc.tree_array_size; i++)
+ {
+ nsn = fc.tree_array[i];
+ if (NULL != nsn)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Root of TREE %u is node `%s'\n", i,
+ nsn->id);
+ ip (ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update);
+ }
+ }
+ GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n");
+ free_update_information_graph (uig);