/**
- * Schedule the download of the specified
- * block in the tree.
+ * Schedule the download of the specified block in the tree.
*
* @param dc overall download this block belongs to
* @param chk content-hash-key of the block
}
+/**
+ * Check if all child-downloads have completed and
+ * if so, signal completion (and possibly recurse to
+ * parent).
+ */
+static void
+check_completed (struct GNUNET_FS_DownloadContext *dc)
+{
+ struct GNUNET_FS_ProgressInfo pi;
+ struct GNUNET_FS_DownloadContext *pos;
+
+ pos = dc->child_head;
+ while (pos != NULL)
+ {
+ if ( (pos->emsg == NULL) &&
+ (pos->completed < pos->length) )
+ return; /* not done yet */
+ if ( (pos->child_head != NULL) &&
+ (pos->has_finished != GNUNET_YES) )
+ return; /* not transitively done yet */
+ pos = pos->next;
+ }
+ dc->has_finished = GNUNET_YES;
+ /* signal completion */
+ pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED;
+ make_download_status (&pi, dc);
+ dc->client_info = dc->h->upcb (dc->h->upcb_cls,
+ &pi);
+ if (dc->parent != NULL)
+ check_completed (dc->parent);
+}
+
+
/**
* Iterator over entries in the pending requests in the 'active' map for the
* reply that we just got.
dc);
}
-
pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS;
make_download_status (&pi, dc);
pi.value.download.specifics.progress.data = pt;
make_download_status (&pi, dc);
dc->client_info = dc->h->upcb (dc->h->upcb_cls,
&pi);
+ if (dc->parent != NULL)
+ check_completed (dc->parent);
}
GNUNET_assert (sm->depth == dc->treedepth);
}
dc->length = length;
dc->anonymity = anonymity;
dc->options = options;
- dc->active = GNUNET_CONTAINER_multihashmap_create (2 * (length / DBLOCK_SIZE));
+ dc->active = GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE));
dc->treedepth = GNUNET_FS_compute_depth (GNUNET_ntohll(dc->uri->data.chk.file_length));
#if DEBUG_DOWNLOAD
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,