[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r3488 - GNUnet/src/applications/fs/fsui
From: |
grothoff |
Subject: |
[GNUnet-SVN] r3488 - GNUnet/src/applications/fs/fsui |
Date: |
Fri, 13 Oct 2006 21:12:45 -0700 (PDT) |
Author: grothoff
Date: 2006-10-13 21:12:42 -0700 (Fri, 13 Oct 2006)
New Revision: 3488
Modified:
GNUnet/src/applications/fs/fsui/fsui.c
GNUnet/src/applications/fs/fsui/fsui.h
GNUnet/src/applications/fs/fsui/upload.c
Log:
fsui hackery
Modified: GNUnet/src/applications/fs/fsui/fsui.c
===================================================================
--- GNUnet/src/applications/fs/fsui/fsui.c 2006-10-14 03:39:14 UTC (rev
3487)
+++ GNUnet/src/applications/fs/fsui/fsui.c 2006-10-14 04:12:42 UTC (rev
3488)
@@ -186,8 +186,8 @@
event.type = FSUI_upload_resumed;
event.data.UploadResumed.uc.pos = ulist;
event.data.UploadResumed.uc.cctx = NULL;
- event.data.UploadResumed.completed = ulist->main_completed;
- event.data.UploadResumed.total = ulist->main_total;
+ event.data.UploadResumed.completed = ulist->completed;
+ event.data.UploadResumed.total = ulist->total;
event.data.UploadResumed.anonymityLevel = ulist->anonymityLevel;
event.data.UploadResumed.eta = 0; /* FIXME: use start_time for estimate! */
event.data.UploadResumed.filename = ulist->filename;
@@ -450,11 +450,8 @@
upos = ctx->activeUploads;
ctx->activeUploads = upos->next;
FREE(upos->filename);
- FREENONNULL(upos->main_filename);
ECRS_freeMetaData(upos->meta);
ECRS_freeUri(upos->uri);
- if (upos->globalUri != NULL)
- ECRS_freeUri(upos->globalUri);
EXTRACTOR_removeAll(upos->extractors);
FREE(upos);
}
Modified: GNUnet/src/applications/fs/fsui/fsui.h
===================================================================
--- GNUnet/src/applications/fs/fsui/fsui.h 2006-10-14 03:39:14 UTC (rev
3487)
+++ GNUnet/src/applications/fs/fsui/fsui.h 2006-10-14 04:12:42 UTC (rev
3488)
@@ -333,14 +333,12 @@
/**
* Context for the upload thread.
- *
- * TODO: keep upload hierarchy!
*/
typedef struct FSUI_UploadList {
- unsigned long long main_completed;
+ unsigned long long completed;
- unsigned long long main_total;
+ unsigned long long total;
cron_t expiration;
@@ -352,6 +350,10 @@
struct FSUI_UploadList * next;
+ struct FSUI_UploadList * child;
+
+ struct FSUI_UploadList * parent;
+
DirTrack * dir;
struct PTHREAD * handle;
@@ -360,12 +362,10 @@
struct ECRS_URI * uri;
- struct ECRS_URI * globalUri;
+ char * extractor_config;
char * filename;
- char * main_filename;
-
void * cctx;
int isRecursive;
@@ -437,7 +437,7 @@
*/
FSUI_UnindexList * unindexOperations;
- FSUI_UploadList * activeUploads;
+ FSUI_UploadList activeUploads;
/**
* Root of the tree of downloads. On shutdown,
Modified: GNUnet/src/applications/fs/fsui/upload.c
===================================================================
--- GNUnet/src/applications/fs/fsui/upload.c 2006-10-14 03:39:14 UTC (rev
3487)
+++ GNUnet/src/applications/fs/fsui/upload.c 2006-10-14 04:12:42 UTC (rev
3488)
@@ -25,9 +25,10 @@
* @author Christian Grothoff
*
* TODO:
- * - make sure events are sent for resume/abort
+ * - make sure events are sent for resume/abort/error
* when respective FSUI calls happen!
* (initialize cctx!)
+ * - proper tree handling
*/
#include "platform.h"
@@ -39,14 +40,6 @@
#define DEBUG_UPLOAD NO
-/* LE <= 0.5.8/0.5.12 compatibility code */
-#ifndef EXTRACTOR_SPLIT
-#define EXTRACTOR_SPLIT 89
-#endif
-#ifndef EXTRACTOR_LOWERCASE
-#define EXTRACTOR_LOWERCASE 101
-#endif
-
/**
* Transform an ECRS progress callback into an FSUI event.
*/
@@ -60,6 +53,10 @@
now = get_time();
event.type = FSUI_upload_progress;
+ event.data.UploadProgress.uc.pos = utc;
+ event.data.UploadProgress.uc.cctx = utc->cctx;
+ event.data.UploadProgress.uc.ppos = utc->parent;
+ event.data.UploadProgress.uc.pcctx = utc->parent->cctx;
event.data.UploadProgress.completed = completedBytes;
event.data.UploadProgress.total = totalBytes;
event.data.UploadProgress.filename = utc->filename;
@@ -68,6 +65,13 @@
&event);
}
+static int testTerminate(void * cls) {
+ FSUI_UploadList * utc = cls;
+ if (utc->state != FSUI_ACTIVE)
+ return SYSERR;
+ return OK;
+}
+
/**
* Take the current directory entries from utc, create
* a directory, upload it and store the uri in *uri.
@@ -148,25 +152,48 @@
utc->expiration,
&progressCallback,
utc,
- NULL,
- NULL,
+ &testTerminate,
+ utc,
uri);
if (ret == OK) {
GE_ASSERT(ectx, NULL != *uri);
event.type = FSUI_upload_complete;
+ event.data.UploadCompleted.uc.pos = utc;
+ event.data.UploadCompleted.uc.cctx = utc->cctx;
+ event.data.UploadCompleted.uc.ppos = utc->parent;
+ event.data.UploadCompleted.uc.pcctx = utc->parent->cctx;
event.data.UploadCompleted.total = utc->main_total;
event.data.UploadCompleted.filename = dirName;
event.data.UploadCompleted.uri = *uri;
utc->ctx->ecb(utc->ctx->ecbClosure,
&event);
- utc->main_completed += len;
+ utc->completed = utc->total;
+ utc->uri = *uri;
+ } else if (utc->state == FSUI_ACTIVE) {
+ /* ECRS internal error - signal */
+ event.type = FSUI_upload_error;
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
+ event.data.UploadError.message = _("Error during upload (consult
logs)");
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
}
UNLINK(tempName);
}
FREE(tempName);
FREENONNULL(data);
+ } else {
+ event.type = FSUI_upload_error;
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
+ event.data.UploadError.message = _("Failed to create directory.");
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
}
-
if (ret != OK) {
ECRS_freeMetaData(*meta);
*meta = NULL;
@@ -174,13 +201,27 @@
return ret;
}
+static struct FSUI_UploadList *
+startUpload(struct FSUI_Context * ctx,
+ const char * filename,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ int doIndex,
+ char * config,
+ EXTRACTOR_ExtractorList * extractors,
+ int individualKeywords,
+ const struct ECRS_MetaData * md,
+ const struct ECRS_URI * globalURI,
+ const struct ECRS_URI * keyUri,
+ struct FSUI_UploadList * parent);
+
/**
* For each file in the directory, upload (recursively).
*/
static int dirEntryCallback(const char * filename,
const char * dirName,
void * ptr) {
- FSUI_UploadList * utc = ptr;
+ FSUI_UploadList * parent = ptr;
char * fn;
struct ECRS_URI * uri;
struct ECRS_URI * keywordUri;
@@ -195,8 +236,18 @@
strcpy(fn, dirName);
strcat(fn, "/");
strcat(fn, filename);
- utc->filename = fn;
-
+ startUpload(parent->ctx,
+ fn,
+ parent->anonymityLevel,
+ parent->priority,
+ parent->doIndex,
+ parent->extractor_config,
+ parent->extractors,
+ parent->individualKeywords,
+ parent->meta,
+ parent->globalUri,
+ parent->uri,
+ parent);
if (NO == disk_directory_test(ectx, fn)) {
ret = ECRS_uploadFile(ectx,
utc->ctx->cfg,
@@ -205,32 +256,36 @@
utc->anonymityLevel,
utc->priority,
utc->expiration,
- (ECRS_UploadProgressCallback) &progressCallback,
+ &progressCallback,
utc,
- NULL,
- NULL,
+ &testTerminate,
+ utc,
&uri);
if (ret == OK) {
GE_ASSERT(ectx, uri != NULL);
+ utc->completed = utc->total;
event.type = FSUI_upload_complete;
+ event.data.UploadCompleted.uc.pos = utc;
+ event.data.UploadCompleted.uc.cctx = utc->cctx;
+ event.data.UploadCompleted.uc.ppos = utc->parent;
+ event.data.UploadCompleted.uc.pcctx = utc->parent->cctx;
event.data.UploadCompleted.total = utc->main_total;
event.data.UploadCompleted.filename = utc->filename;
event.data.UploadCompleted.uri = uri;
- if (OK == disk_file_size(ectx,
- fn,
- &len,
- YES))
- utc->main_completed += len;
utc->ctx->ecb(utc->ctx->ecbClosure,
&event);
meta = ECRS_createMetaData();
ECRS_extractMetaData(ectx,
meta,
fn,
- utc->extractors);
- } else {
+ utc->extractors);
+ } else if (utc->state == FSUI_ACTIVE) {
event.type = FSUI_upload_error;
- event.data.UploadError.message = _("Upload failed.");
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
+ event.data.UploadError.message = _("Error during upload (consult logs)");
utc->ctx->ecb(utc->ctx->ecbClosure,
&event);
meta = NULL;
@@ -321,13 +376,6 @@
return OK;
}
-static int tt(void * cls) {
- FSUI_UploadList * utc = cls;
- if (utc->force_termination == YES)
- return SYSERR;
- return OK;
-}
-
/**
* Thread that does the upload.
*/
@@ -339,50 +387,67 @@
ECRS_FileInfo fi;
int ret;
char * inboundFN;
- int sendEvent = YES;
struct GE_Context * ectx;
ectx = utc->ctx->ectx;
- GE_ASSERT(ectx, utc->main_filename != NULL);
- inboundFN
- = ECRS_getFromMetaData(utc->meta,
- EXTRACTOR_FILENAME);
+ GE_ASSERT(ectx, utc->filename != NULL);
utc->start_time = get_time();
-
if (OK != disk_file_size(ectx,
- utc->main_filename,
- &utc->main_total,
+ utc->filename,
+ &utc->total,
YES)) {
- utc->main_total = 0;
- /* or signal error?? */
+ event.type = FSUI_upload_error;
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
+ event.data.UploadError.message = _("Error during upload (could not
determine file size)");
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
+ return NULL;
}
- utc->main_completed = 0;
+ utc->completed = 0;
ret = SYSERR;
uri = NULL;
+ inboundFN
+ = ECRS_getFromMetaData(utc->meta,
+ EXTRACTOR_FILENAME);
if (NO == disk_directory_test(ectx,
- utc->main_filename)) {
+ utc->filename)) {
utc->filename = utc->main_filename;
ret = ECRS_uploadFile(ectx,
utc->ctx->cfg,
- utc->main_filename,
+ utc->filename,
utc->doIndex,
utc->anonymityLevel,
utc->priority,
utc->expiration,
&progressCallback,
utc,
- &tt,
+ &testTerminate,
utc,
&uri);
if (ret == OK) {
event.type = FSUI_upload_complete;
- event.data.UploadCompleted.total = utc->main_total;
+ event.data.UploadCompleted.uc.pos = utc;
+ event.data.UploadCompleted.uc.cctx = utc->cctx;
+ event.data.UploadCompleted.uc.ppos = utc->parent;
+ event.data.UploadCompleted.uc.pcctx = utc->parent->cctx;
+ event.data.UploadCompleted.total = utc->total;
event.data.UploadCompleted.filename = utc->filename;
event.data.UploadCompleted.uri = uri;
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
} else {
event.type = FSUI_upload_error;
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
event.data.UploadError.message = _("Upload failed.");
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
}
if (utc->meta == NULL)
utc->meta = ECRS_createMetaData();
@@ -401,13 +466,12 @@
memset(¤t, 0, sizeof(DirTrack));
utc->dir = ¤t;
- utc->filename = utc->main_filename;
disk_directory_scan(ectx,
- utc->main_filename,
+ utc->filename,
&dirEntryCallback,
utc);
ret = uploadDirectory(utc,
- utc->main_filename,
+ utc->filename,
¤t,
&uri,
&utc->meta);
@@ -418,17 +482,16 @@
GROW(current.fis,
current.fiCount,
0);
-
- if (ret != OK) {
- event.type = FSUI_upload_error;
- event.data.UploadError.message = _("Upload failed.");
- } else { /* for success, uploadDirectory sends event already! */
- sendEvent = NO;
- }
utc->filename = NULL;
} else {
event.type = FSUI_upload_error;
+ event.data.UploadError.uc.pos = utc;
+ event.data.UploadError.uc.cctx = utc->cctx;
+ event.data.UploadError.uc.ppos = utc->parent;
+ event.data.UploadError.uc.pcctx = utc->parent->cctx;
event.data.UploadError.message = _("Cannot upload directory without using
recursion.");
+ utc->ctx->ecb(utc->ctx->ecbClosure,
+ &event);
}
if (ret == OK) { /* publish top-level advertisements */
fi.meta = utc->meta;
@@ -445,8 +508,9 @@
inboundFN);
}
#if DEBUG_UPLOAD
- GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
- "Adding URI to keyspace.\n");
+ GE_LOG(ectx,
+ GE_DEBUG | GE_REQUEST | GE_USER,
+ "Adding URI to keyspace.\n");
#endif
keywordUri = ECRS_metaDataToUri(utc->meta);
if (keywordUri != NULL) {
@@ -484,12 +548,6 @@
EXTRACTOR_SPLIT,
NULL);
fi.meta = utc->meta;
- /*
- CO_publishToCollection(ectx,
- utc->ctx->cfg,
- utc->ctx,
- &fi);
- */
if (sendEvent)
utc->ctx->ecb(utc->ctx->ecbClosure,
&event);
@@ -500,29 +558,20 @@
return NULL;
}
-/**
- * Start uploading a file. Note that an upload cannot be stopped once
- * started (not necessary anyway), but it can fail. The function also
- * automatically the uploaded file in the global keyword space under
- * the given keywords.
- *
- * @return OK on success (at least we started with it),
- * SYSERR if the file does not exist or gnunetd is not
- * running
- */
-struct FSUI_UploadList *
-FSUI_startUpload(struct FSUI_Context * ctx,
- const char * filename,
- unsigned int anonymityLevel,
- unsigned int priority,
- int doIndex,
- int doExtract,
- int individualKeywords,
- const struct ECRS_MetaData * md,
- const struct ECRS_URI * globalURI,
- const struct ECRS_URI * keyUri) {
+static struct FSUI_UploadList *
+startUpload(struct FSUI_Context * ctx,
+ const char * filename,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ int doIndex,
+ char * config,
+ EXTRACTOR_ExtractorList * extractors,
+ int individualKeywords,
+ const struct ECRS_MetaData * md,
+ const struct ECRS_URI * globalURI,
+ const struct ECRS_URI * keyUri,
+ struct FSUI_UploadList * parent) {
FSUI_UploadList * utc;
- char * config;
struct GE_Context * ectx;
ectx = ctx->ectx;
@@ -533,23 +582,11 @@
utc->expiration = get_time() + 120 * cronYEARS;
utc->ctx = ctx;
utc->isRecursive = NO;
- if (doExtract) {
- utc->extractors = EXTRACTOR_loadDefaultLibraries();
- if ( (0 == GC_get_configuration_value_string(ctx->cfg,
- "FS",
- "EXTRACTORS",
- NULL,
- &config)) &&
- (config != NULL) ) {
- utc->extractors = EXTRACTOR_loadConfigLibraries(utc->extractors,
- config);
- FREE(config);
- }
- } else
- utc->extractors = NULL;
- utc->globalUri = NULL;
- utc->filename = NULL;
- utc->main_filename = STRDUP(filename);
+ utc->parent = parent;
+ utc->globalUri = ECRS_dupUri(globalURI);
+ utc->filename = STRDUP(filename);
+ utc->extractor_config = config;
+ utc->extractors = extractors;
utc->uri = ECRS_dupUri(keyUri);
utc->meta = ECRS_dupMetaData(md);
utc->doIndex = doIndex;
@@ -562,69 +599,164 @@
GE_LOG_STRERROR(ectx,
GE_ERROR | GE_USER | GE_BULK,
"PTHREAD_CREATE");
- FREE(utc->main_filename);
+ FREE(utc->filename);
ECRS_freeMetaData(utc->meta);
ECRS_freeUri(utc->uri);
- EXTRACTOR_removeAll(utc->extractors);
+ ECRS_freeUri(utc->globalURI);
+ if (utc->parent == &utc->ctx->activeUploads) {
+ EXTRACTOR_removeAll(utc->extractors);
+ FREE(utc->extractor_config);
+ }
FREE(utc);
return NULL;
}
MUTEX_LOCK(ctx->lock);
- utc->next = ctx->activeUploads;
- ctx->activeUploads = utc;
+ utc->next = parent->child;
+ parent->child = utc;
MUTEX_UNLOCK(ctx->lock);
return utc;
}
+
/**
+ * Start uploading a file. Note that an upload cannot be stopped once
+ * started (not necessary anyway), but it can fail. The function also
+ * automatically the uploaded file in the global keyword space under
+ * the given keywords.
+ *
+ * @return OK on success (at least we started with it),
+ * SYSERR if the file does not exist or gnunetd is not
+ * running
+ */
+struct FSUI_UploadList *
+FSUI_startUpload(struct FSUI_Context * ctx,
+ const char * filename,
+ unsigned int anonymityLevel,
+ unsigned int priority,
+ int doIndex,
+ int doExtract,
+ int individualKeywords,
+ const struct ECRS_MetaData * md,
+ const struct ECRS_URI * globalURI,
+ const struct ECRS_URI * keyUri) {
+ char * config;
+ EXTRACTOR_ExtractorList * extractors;
+
+ if (doExtract) {
+ extractors = EXTRACTOR_loadDefaultLibraries();
+ if ( (0 == GC_get_configuration_value_string(ctx->cfg,
+ "FS",
+ "EXTRACTORS",
+ NULL,
+ &config)) &&
+ (config != NULL) ) {
+ extractors = EXTRACTOR_loadConfigLibraries(extractors,
+ config);
+ }
+ } else {
+ extractors = NULL;
+ extractor_config = NULL;
+ }
+ return startUpload(ctx,
+ filename,
+ anonymityLevel,
+ priority,
+ doIndex,
+ extractors,
+ extractor_config,
+ individualKeywords,
+ md,
+ globalURI,
+ keyUri,
+ &ctx->activeUploads);
+}
+
+/**
* Abort an upload. If the context is for a recursive
* upload, all sub-uploads will also be aborted.
*
* @return SYSERR on error
*/
+int FSUI_abortUpload(struct FSUI_Context * ctx,
+ struct FSUI_UploadList * ul) {
+ FSUI_UploadList * c;
+ struct GE_Context * ectx;
+
+ GE_ASSERT(ctx->ectx, ul != NULL);
+ c = ul->child;
+ while (c != NULL) {
+ FSUI_abortDownload(ctx, c);
+ c = c->next;
+ }
+ if ( (ul->state != FSUI_ACTIVE) &&
+ (ul->state != FSUI_PENDING) )
+ return NO;
+ ul->state = FSUI_ABORTED;
+ PTHREAD_STOP_SLEEP(ul->handle);
+ event.type = FSUI_upload_aborted;
+ event.data.DownloadAborted.dc.pos = dl;
+ event.data.DownloadAborted.dc.cctx = dl->cctx;
+ event.data.DownloadAborted.dc.ppos = dl->parent;
+ event.data.DownloadAborted.dc.pcctx = dl->parent->cctx;
+ ctx->ecb(ctx->ecbClosure,
+ &event);
+ return OK;
+}
+
+/**
+ * Stop an upload. If the context is for a recursive
+ * upload, all sub-uploads will also be stopped.
+ *
+ * @return SYSERR on error
+ */
int FSUI_stopUpload(struct FSUI_Context * ctx,
struct FSUI_UploadList * ul) {
void * unused;
FSUI_UploadList * prev;
struct GE_Context * ectx;
- ectx = ctx->ectx;
- if (ul == NULL) {
- GE_BREAK(ectx, 0);
- return SYSERR;
- }
- GE_LOG(ectx,
- GE_DEBUG | GE_REQUEST | GE_USER,
- "FSUI_stopUpload called.\n");
+ GE_ASSERT(ctx->ectx, ul != NULL);
+ while (ul->child != NULL)
+ FSUI_stopDownload(ctx,
+ ul->child);
MUTEX_LOCK(ctx->lock);
- prev = ctx->activeUploads;
+ prev = (ul->parent != NULL) ? ul->parent->child : ctx->activeDownloads.child;
while ( (prev != ul) &&
(prev != NULL) &&
(prev->next != ul) )
prev = prev->next;
if (prev == NULL) {
MUTEX_UNLOCK(ctx->lock);
- GE_LOG(ectx,
+ GE_LOG(ctx->ectx,
GE_DEBUG | GE_REQUEST | GE_USER,
- "FSUI_stopUpload failed to locate deletion operation.\n");
+ "FSUI_stopUpload failed to locate download.\n");
return SYSERR;
}
- if (prev == ul) {
- ctx->activeUploads = ul->next;
- } else {
- prev->next = ul->next;
+ if (prev == ul)
+ ul->parent->child = ul->next; /* first child of parent */
+ else
+ prev->next = ul->next; /* not first child */
+ MUTEX_UNLOCK(ctx->lock);
+ if ( (dl->state == FSUI_COMPLETED) ||
+ (dl->state == FSUI_ABORTED) ||
+ (dl->state == FSUI_ERROR) ) {
+ PTHREAD_JOIN(ul->handle,
+ &unused);
+ ul->state++; /* add _JOINED */
}
- MUTEX_UNLOCK(ctx->lock);
- ul->force_termination = YES;
- PTHREAD_STOP_SLEEP(ul->handle);
- PTHREAD_JOIN(ul->handle,
- &unused);
- FREE(ul->main_filename);
+ event.type = FSUI_upload_stopped;
+ event.data.UploadStopped.uc.pos = ul;
+ event.data.UploadStopped.uc.cctx = ul->cctx;
+ event.data.UploadStopped.uc.ppos = ul->parent;
+ event.data.UploadStopped.uc.pcctx = ul->parent->cctx;
+ ctx->ecb(ctx->ecbClosure,
+ &event);
+ FREE(ul->filename);
+ if (ul->extractor_config != NULL)
+ FREE(ul->extractor_config);
ECRS_freeMetaData(ul->meta);
ECRS_freeUri(ul->uri);
- if (ul->globalUri != NULL)
- ECRS_freeUri(ul->globalUri);
EXTRACTOR_removeAll(ul->extractors);
FREE(ul);
return OK;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r3488 - GNUnet/src/applications/fs/fsui,
grothoff <=