📄 download.c
字号:
GNUNET_ECRS_uri_get_file_size (dl->fi.uri); event.data.DownloadStarted.filename = dl->filename; event.data.DownloadStarted.fi.uri = dl->fi.uri; event.data.DownloadStarted.fi.meta = dl->fi.meta; event.data.DownloadStarted.anonymityLevel = dl->anonymityLevel; GNUNET_URITRACK_add_state (ctx->ectx, ctx->cfg, uri, GNUNET_URITRACK_DOWNLOAD_STARTED); dl->cctx = dl->ctx->ecb (dl->ctx->ecbClosure, &event); dl->next = parent->child; parent->child = dl; if (psearch != NULL) { GNUNET_array_grow (psearch->my_downloads, psearch->my_downloads_size, psearch->my_downloads_size + 1); psearch->my_downloads[psearch->my_downloads_size - 1] = dl; } return dl;}/** * Start to download a file. * * @return GNUNET_OK on success, GNUNET_SYSERR if the target file is * already used for another download at the moment (or * if the disk does not have enough space). */struct GNUNET_FSUI_DownloadList *GNUNET_FSUI_download_start (struct GNUNET_FSUI_Context *ctx, unsigned int anonymityLevel, int doRecursive, const struct GNUNET_ECRS_URI *uri, const struct GNUNET_MetaData *meta, const char *filename, struct GNUNET_FSUI_SearchList *psearch, struct GNUNET_FSUI_DownloadList *pdownload){ struct GNUNET_FSUI_DownloadList *ret; GNUNET_mutex_lock (ctx->lock); if (pdownload == NULL) pdownload = &ctx->activeDownloads; ret = startDownload (ctx, anonymityLevel, doRecursive, uri, meta, filename, psearch, pdownload); GNUNET_mutex_unlock (ctx->lock); return ret;}/** * Starts or stops download threads in accordance with thread pool * size and active downloads. Call only while holding FSUI lock (or * during start/stop). Called from cron job in fsui.c. * * @return GNUNET_YES if change done that may require re-trying */intGNUNET_FSUI_updateDownloadThread (GNUNET_FSUI_DownloadList * list){ struct GNUNET_GE_Context *ectx; GNUNET_FSUI_DownloadList *dpos; GNUNET_FSUI_Event event; GNUNET_CronTime now; int ret; if (list == NULL) return GNUNET_NO; ectx = list->ctx->ectx;#if DEBUG_DTM GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Download thread manager investigates pending download of file `%s' (%u/%u downloads)\n", list->filename, list->ctx->activeDownloadThreads, list->ctx->threadPoolSize);#endif ret = GNUNET_NO; now = GNUNET_get_time(); /* should this one be started? */ if ((list->ctx->threadPoolSize > list->ctx->activeDownloadThreads) && (list->state == GNUNET_FSUI_PENDING) && ( (list->block_resume == 0) || (list->block_resume == list->ctx->min_block_resume) || (list->ctx->threadPoolSize > list->ctx->activeDownloadThreads + 1) ) && ((list->total > list->completed) || (list->total == 0))) { if (list->block_resume == list->ctx->min_block_resume) list->ctx->min_block_resume = -1; list->block_resume = 0;#if DEBUG_DTM GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Download thread manager starts download of file `%s'\n", list->filename);#endif list->state = GNUNET_FSUI_ACTIVE; list->startTime = now - list->runTime; list->handle = GNUNET_ECRS_file_download_partial_start (list->ctx->ectx, list->ctx->cfg, NULL, list->fi.uri, list->filename, 0, GNUNET_ECRS_uri_get_file_size (list->fi.uri), list->anonymityLevel, GNUNET_NO, &downloadProgressCallback, list); list->progressBits = 1; list->lastProgressTime = now; if (list->handle != NULL) list->ctx->activeDownloadThreads++; else list->state = GNUNET_FSUI_ERROR_JOINED; } if (list->state == GNUNET_FSUI_ACTIVE) update_progress_bits(now, list); /* should this one be stopped? */ if ( (list->state == GNUNET_FSUI_ACTIVE) && ( (list->ctx->threadPoolSize < list->ctx->activeDownloadThreads) || ( (list->ctx->threadPoolSize == list->ctx->activeDownloadThreads) && (0 == (list->progressBits & GNUNET_FSUI_DL_KILL_TIME_MASK)) ) ) ) { if ( (list->ctx->threadPoolSize == list->ctx->activeDownloadThreads) && (0 == (list->progressBits & GNUNET_FSUI_DL_KILL_TIME_MASK)) ) list->block_resume = now; else list->block_resume = 0;#if DEBUG_DTM GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Download thread manager aborts active download of file `%s' (%u/%u downloads)\n", list->filename, list->ctx->activeDownloadThreads, list->ctx->threadPoolSize);#endif list->state = GNUNET_FSUI_SUSPENDING; GNUNET_GE_ASSERT (ectx, list->handle != NULL); GNUNET_ECRS_file_download_partial_stop (list->handle); list->handle = NULL; list->ctx->activeDownloadThreads--; list->state = GNUNET_FSUI_PENDING; ret = GNUNET_YES; } /* Trigger any recursive sub-downloads */ if (((list->state == GNUNET_FSUI_COMPLETED) || (list->state == GNUNET_FSUI_COMPLETED_JOINED)) && (list->is_directory == GNUNET_YES)) { /* in case there is no sub-download, still create the (possibly empty) directory! */ GNUNET_disk_directory_create (list->ctx->ectx, list->filename); if ((list->is_recursive == GNUNET_YES) && (GNUNET_ECRS_uri_get_file_size (list->fi.uri) > 0)) { download_recursive (list); list->is_recursive = GNUNET_NO; } } /* has this one "died naturally"? */ if ((list->state == GNUNET_FSUI_COMPLETED) || (list->state == GNUNET_FSUI_ABORTED) || (list->state == GNUNET_FSUI_ERROR)) {#if DEBUG_DTM GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Download thread manager collects inactive download of file `%s'\n", list->filename);#endif GNUNET_ECRS_file_download_partial_stop (list->handle); list->handle = NULL; list->ctx->activeDownloadThreads--; if (list->state == GNUNET_FSUI_COMPLETED) { /* generate event */ event.type = GNUNET_FSUI_download_completed; event.data.DownloadCompleted.dc.pos = list; event.data.DownloadCompleted.dc.cctx = list->cctx; event.data.DownloadCompleted.dc.ppos = list->parent == &list->ctx->activeDownloads ? NULL : list->parent; event.data.DownloadCompleted.dc.pcctx = list->parent->cctx; event.data.DownloadCompleted.dc.spos = list->search; event.data.DownloadCompleted.dc.sctx = list->search == NULL ? NULL : list->search->cctx; event.data.DownloadCompleted.total = list->total; event.data.DownloadCompleted.filename = list->filename; event.data.DownloadCompleted.uri = list->fi.uri; list->ctx->ecb (list->ctx->ecbClosure, &event); } list->state++; /* adds _JOINED */ ret = GNUNET_YES; } dpos = list->child; while (dpos != NULL) { if (GNUNET_YES == GNUNET_FSUI_updateDownloadThread (dpos)) ret = GNUNET_YES; dpos = dpos->next; } if ( (list->block_resume != 0) && (list->state == GNUNET_FSUI_PENDING) && (list->block_resume < list->ctx->next_min_block_resume) ) list->ctx->next_min_block_resume = list->block_resume; return ret;}/** * Abort a download (and all child-downloads). This will also * delete all of the files associated with the download * (except if the download has already completed, in which * case GNUNET_NO will be returned). If this is a recursive * download and some files have been completed, these files * will not be removed (only incomplete downloads will be * removed). * * @return GNUNET_SYSERR if no such download is pending, * GNUNET_NO if the download has already finished */intGNUNET_FSUI_download_abort (struct GNUNET_FSUI_DownloadList *dl){ struct GNUNET_FSUI_Context *ctx; struct GNUNET_FSUI_DownloadList *c; GNUNET_FSUI_Event event; if (dl == NULL) return GNUNET_SYSERR; ctx = dl->ctx; c = dl->child; while (c != NULL) { GNUNET_FSUI_download_abort (c); c = c->next; } GNUNET_mutex_lock (ctx->lock); if ((dl->state != GNUNET_FSUI_ACTIVE) && (dl->state != GNUNET_FSUI_PENDING)) { GNUNET_mutex_unlock (ctx->lock); return GNUNET_NO; } if (dl->state == GNUNET_FSUI_ACTIVE) { dl->state = GNUNET_FSUI_ABORTED_JOINED; GNUNET_ECRS_file_download_partial_stop (dl->handle); dl->handle = NULL; dl->ctx->activeDownloadThreads--; dl->runTime = GNUNET_get_time() - dl->startTime; event.type = GNUNET_FSUI_download_aborted; event.data.DownloadAborted.dc.pos = dl; event.data.DownloadAborted.dc.cctx = dl->cctx; event.data.DownloadAborted.dc.ppos = dl->parent == &dl->ctx->activeDownloads ? NULL : dl->parent; event.data.DownloadAborted.dc.pcctx = dl->parent->cctx; event.data.DownloadAborted.dc.spos = dl->search; event.data.DownloadAborted.dc.sctx = dl->search == NULL ? NULL : dl->search->cctx; GNUNET_URITRACK_add_state (dl->ctx->ectx, dl->ctx->cfg, dl->fi.uri, GNUNET_URITRACK_DOWNLOAD_ABORTED); dl->ctx->ecb (dl->ctx->ecbClosure, &event); } else { dl->state = GNUNET_FSUI_ABORTED_JOINED; } if (0 != UNLINK (dl->filename)) { if (errno == EISDIR) { if ( (0 != RMDIR(dl->filename)) && (errno != ENOTEMPTY) ) GNUNET_GE_LOG_STRERROR_FILE (dl->ctx->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "rmdir", dl->filename); } else if (errno != ENOENT) GNUNET_GE_LOG_STRERROR_FILE (dl->ctx->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "unlink", dl->filename); } GNUNET_mutex_unlock (ctx->lock); return GNUNET_OK;}/** * Stops a download (and all downloads that are * child downloads of this download). * * @return GNUNET_SYSERR if no such download is pending */intGNUNET_FSUI_download_stop (struct GNUNET_FSUI_DownloadList *dl){ struct GNUNET_FSUI_DownloadList *prev; struct GNUNET_FSUI_Context *ctx; GNUNET_FSUI_Event event; int i; if (dl == NULL) return GNUNET_SYSERR; ctx = dl->ctx; while (dl->child != NULL) GNUNET_FSUI_download_stop (dl->child); GNUNET_mutex_lock (ctx->lock); prev = (dl->parent != NULL) ? dl->parent->child : ctx->activeDownloads.child; while ((prev != dl) && (prev != NULL) && (prev->next != dl)) prev = prev->next; if (prev == NULL) { GNUNET_mutex_unlock (ctx->lock); GNUNET_GE_LOG (ctx->ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "GNUNET_FSUI_download_stop failed to locate download.\n"); return GNUNET_SYSERR; } if (prev == dl) dl->parent->child = dl->next; /* first child of parent */ else prev->next = dl->next; /* not first child */ GNUNET_mutex_unlock (ctx->lock); if ((dl->state == GNUNET_FSUI_ACTIVE) || (dl->state == GNUNET_FSUI_COMPLETED) || (dl->state == GNUNET_FSUI_ABORTED) || (dl->state == GNUNET_FSUI_ERROR)) { GNUNET_GE_ASSERT (ctx->ectx, dl->handle != NULL); GNUNET_ECRS_file_download_partial_stop (dl->handle); dl->handle = NULL; dl->runTime = GNUNET_get_time() - dl->startTime; GNUNET_mutex_lock (ctx->lock); dl->ctx->activeDownloadThreads--; GNUNET_mutex_unlock (ctx->lock); dl->handle = NULL; if (dl->state == GNUNET_FSUI_ACTIVE) dl->state = GNUNET_FSUI_PENDING; else dl->state++; /* add _JOINED */ } else { GNUNET_GE_ASSERT (ctx->ectx, dl->handle == NULL); } event.type = GNUNET_FSUI_download_stopped; event.data.DownloadStopped.dc.pos = dl; event.data.DownloadStopped.dc.cctx = dl->cctx; event.data.DownloadStopped.dc.ppos = dl->parent == &ctx->activeDownloads ? NULL : dl->parent; event.data.DownloadStopped.dc.pcctx = dl->parent->cctx; event.data.DownloadStopped.dc.spos = dl->search; event.data.DownloadStopped.dc.sctx = dl->search == NULL ? NULL : dl->search->cctx; ctx->ecb (ctx->ecbClosure, &event); if (dl->search != NULL) { for (i = 0; i < dl->search->my_downloads_size; i++) { if (dl->search->my_downloads[i] == dl) { dl->search->my_downloads[i] = dl->search->my_downloads[dl->search->my_downloads_size - 1]; GNUNET_array_grow (dl->search->my_downloads, dl->search->my_downloads_size, dl->search->my_downloads_size - 1); } } } for (i = dl->completedDownloadsCount - 1; i >= 0; i--) GNUNET_ECRS_uri_destroy (dl->completedDownloads[i]); GNUNET_array_grow (dl->completedDownloads, dl->completedDownloadsCount, 0); GNUNET_ECRS_uri_destroy (dl->fi.uri); if (dl->fi.meta != NULL) GNUNET_meta_data_destroy (dl->fi.meta); GNUNET_free (dl->filename); GNUNET_free (dl); return GNUNET_OK;}/* end of download.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -