Commit f011b13c authored by Bernhard Link's avatar Bernhard Link

move handling of downloaded files from aptmethod.c to the code queuing the...

move handling of downloaded files from aptmethod.c to  the code queuing the files. (refactorisation in preparation of later changes)
parent 9c982d12
2009-02-27
* move handling of downloaded files from aptmethod.c to
the code queuing the files. (refactorisation in preparation of later
changes)
2009-02-24
* fix race condition causing external uncompressors sometimes
to catch a sigpipe if their output is closed before they receive
......
This diff is collapsed.
......@@ -11,38 +11,15 @@
struct aptmethodrun;
struct aptmethod;
struct tobedone {
/*@null@*/
struct tobedone *next;
/* must be saved to know where is should be moved to: */
/*@notnull@*/
char *uri;
/*@notnull@*/
char *filename;
/* if non-NULL, add to the database after found (needs md5sum != NULL) */
union {
/* if !indexfile */
char *filekey;
/* if indexfile, the place the final uncompressed checksum
* is to be saved to: */
/*@null@*/ struct checksums **checksums_p;
};
union {
/* if !indexfile */
/*@null@*/ struct checksums *checksums;
/* if !indexfile */
/*@null@*/ const struct checksums *compressedchecksums;
};
bool indexfile;
/* must be c_none if not a index file */
enum compression compression;
};
enum queue_action { qa_abort, qa_got, qa_error };
typedef retvalue queue_callback(enum queue_action, void *privdata, void *privdata2, const char *uri, const char *gotfilename, const char *wantedfilename, /*@null@*/const struct checksums *, const char *methodname);
retvalue aptmethod_initialize_run(/*@out@*/struct aptmethodrun **run);
retvalue aptmethod_newmethod(struct aptmethodrun *, const char *uri, const char *fallbackuri, const struct strlist *config, /*@out@*/struct aptmethod **);
retvalue aptmethod_queuefile(struct aptmethod *, const char *origfile, const char *destfile, const struct checksums *, const char *filekey, /*@out@*/struct tobedone **);
retvalue aptmethod_queueindexfile(struct aptmethod *method, const char *suite, const char *origfile, const char *destfile, /*@null@*/struct checksums **, enum compression, /*@null@*/const struct checksums *);
retvalue aptmethod_enqueue(struct aptmethod *, const char *origfile, /*@only@*/char *destfile, queue_callback *, void *, void *);
retvalue aptmethod_enqueueindex(struct aptmethod *, const char *suite, const char *origfile, const char *, const char *destfile, const char *, queue_callback *, void *, void *);
retvalue aptmethod_download(struct aptmethodrun *, struct database *);
retvalue aptmethod_shutdown(/*@only@*/struct aptmethodrun *);
......
......@@ -19,6 +19,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include "error.h"
#include "strlist.h"
......@@ -32,7 +33,9 @@
struct downloaditem {
/*@dependent@*//*@null@*/struct downloaditem *parent;
/*@null@*/struct downloaditem *left,*right;
struct tobedone *todo;
char *filekey;
struct checksums *checksums;
bool done;
};
/* Initialize a new download session */
......@@ -59,10 +62,12 @@ static void freeitem(/*@null@*//*@only@*/struct downloaditem *item) {
return;
freeitem(item->left);
freeitem(item->right);
free(item->filekey);
checksums_free(item->checksums);
free(item);
}
retvalue downloadcache_free(struct downloadcache *download) {
retvalue downloadcache_free(struct downloadcache *download) {
if( download == NULL )
return RET_NOTHING;
......@@ -72,7 +77,79 @@ retvalue downloadcache_free(struct downloadcache *download) {
return RET_OK;
}
/*@null@*//*@dependent@*/ static const struct downloaditem *searchforitem(struct downloadcache *list,
static retvalue downloaditem_callback(enum queue_action action, void *privdata, void *privdata2, const char *uri, const char *gotfilename, const char *wantedfilename, /*@null@*/const struct checksums *checksums, const char *method) {
struct downloaditem *d = privdata;
struct database *database = privdata2;
struct checksums *read_checksums = NULL;
retvalue r;
bool improves;
if( action != qa_got )
// TODO: instead store in downloaditem?
return RET_ERROR;
/* if the file is somewhere else, copy it: */
if( strcmp(gotfilename, wantedfilename) != 0 ) {
if( verbose > 1 )
fprintf(stderr,
"Linking file '%s' to '%s'...\n", gotfilename, wantedfilename);
r = checksums_linkorcopyfile(wantedfilename, gotfilename,
&read_checksums);
if( r == RET_NOTHING ) {
fprintf(stderr, "Cannot open '%s', obtained from '%s' method.\n",
gotfilename, method);
r = RET_ERROR_MISSING;
}
if( RET_WAS_ERROR(r) ) {
// TODO: instead store in downloaditem?
return r;
}
if( read_checksums != NULL )
checksums = read_checksums;
}
if( checksums == NULL || !checksums_iscomplete(checksums) ) {
assert(read_checksums == NULL);
r = checksums_read(wantedfilename, &read_checksums);
if( r == RET_NOTHING ) {
fprintf(stderr,
"Cannot open '%s', though '%s' method claims to have put it there!\n",
wantedfilename, method);
r = RET_ERROR_MISSING;
}
if( RET_WAS_ERROR(r) ) {
// TODO: instead store in downloaditem?
return r;
}
checksums = read_checksums;
}
assert( checksums != NULL );
if( !checksums_check(d->checksums, checksums, &improves) ) {
fprintf(stderr, "Wrong checksum during receive of '%s':\n",
uri);
checksums_printdifferences(stderr, d->checksums, checksums);
checksums_free(read_checksums);
(void)unlink(wantedfilename);
// TODO: instead store in downloaditem?
return RET_ERROR_WRONG_MD5;
}
if( improves ) {
r = checksums_combine(&d->checksums, checksums, NULL);
checksums_free(read_checksums);
if( RET_WAS_ERROR(r) )
return r;
} else
checksums_free(read_checksums);
r = files_add_checksums(database, d->filekey, d->checksums);
if( RET_WAS_ERROR(r) )
return r;
d->done = true;
return RET_OK;
}
/*@null@*//*@dependent@*/ static struct downloaditem *searchforitem(struct downloadcache *list,
const char *filekey,
/*@out@*/struct downloaditem **p,
/*@out@*/struct downloaditem ***h) {
......@@ -84,7 +161,7 @@ retvalue downloadcache_free(struct downloadcache *download) {
item = list->items;
while( item != NULL ) {
*p = item;
c = strcmp(filekey,item->todo->filekey);
c = strcmp(filekey, item->filekey);
if( c == 0 )
return item;
else if( c < 0 ) {
......@@ -103,7 +180,7 @@ retvalue downloadcache_free(struct downloadcache *download) {
* for the same destination with other md5sum created. */
retvalue downloadcache_add(struct downloadcache *cache, struct database *database, struct aptmethod *method, const char *orig, const char *filekey, const struct checksums *checksums) {
const struct downloaditem *i;
struct downloaditem *i;
struct downloaditem *item,**h,*parent;
char *fullfilename;
retvalue r;
......@@ -117,44 +194,50 @@ retvalue downloadcache_add(struct downloadcache *cache, struct database *databas
if( i != NULL ) {
bool improves;
assert( i->todo->filekey != NULL );
if( !checksums_check(i->todo->checksums, checksums, &improves) ) {
assert( i->filekey != NULL );
if( !checksums_check(i->checksums, checksums, &improves) ) {
fprintf(stderr,
"ERROR: Same file is requested with conflicting checksums:\n"
"'%s':\n", i->todo->uri);
"ERROR: Same file is requested with conflicting checksums:\n");
checksums_printdifferences(stderr,
i->todo->checksums, checksums);
i->checksums, checksums);
return RET_ERROR_WRONG_MD5;
}
if( improves ) {
r = checksums_combine(&i->todo->checksums,
r = checksums_combine(&i->checksums,
checksums, NULL);
if( RET_WAS_ERROR(r) )
return r;
}
return RET_NOTHING;
}
item = malloc(sizeof(struct downloaditem));
if( item == NULL )
item = calloc(1, sizeof(struct downloaditem));
if( FAILEDTOALLOC(item) )
return RET_ERROR_OOM;
item->done = false;
item->filekey = strdup(filekey);
item->checksums = checksums_dup(checksums);
if( FAILEDTOALLOC(item->filekey) || FAILEDTOALLOC(item->checksums) ) {
freeitem(item);
return RET_ERROR_OOM;
}
fullfilename = files_calcfullfilename(database, filekey);
if( fullfilename == NULL ) {
free(item);
if( FAILEDTOALLOC(fullfilename) ) {
freeitem(item);
return RET_ERROR_OOM;
}
(void)dirs_make_parent(fullfilename);
r = space_needed(cache->devices, fullfilename, checksums);
if( RET_WAS_ERROR(r) ) {
free(fullfilename);
free(item);
freeitem(item);
return r;
}
r = aptmethod_queuefile(method, orig,
fullfilename, checksums, filekey, &item->todo);
free(fullfilename);
r = aptmethod_enqueue(method, orig, fullfilename,
downloaditem_callback, item, database);
if( RET_WAS_ERROR(r) ) {
free(item);
freeitem(item);
return r;
}
item->left = item->right = NULL;
......
This diff is collapsed.
......@@ -260,7 +260,7 @@ retvalue uncompress_checkpid(pid_t pid, int status) {
}
/* call the notification, if asked for */
if( t->callback != NULL ) {
r = t->callback(t->privdata, t->compressedfilename, error, false);
r = t->callback(t->privdata, t->compressedfilename, error);
if( r == RET_NOTHING )
r = RET_OK;
} else if( error )
......@@ -424,14 +424,13 @@ static retvalue uncompress_queue_external(enum compression compression, const ch
return RET_OK;
}
retvalue uncompress_queue_file(const char *compressed, const char *destination, enum compression compression, finishaction *action, void *privdata, bool *done_p) {
retvalue uncompress_queue_file(const char *compressed, const char *destination, enum compression compression, finishaction *action, void *privdata) {
retvalue r;
(void)unlink(destination);
if( extern_uncompressors[compression] != NULL ) {
r = uncompress_queue_external(compression, compressed, destination, action, privdata);
if( r != RET_NOTHING ) {
*done_p = false;
return r;
}
if( !uncompression_builtin(compression) )
......@@ -445,10 +444,9 @@ retvalue uncompress_queue_file(const char *compressed, const char *destination,
r = builtin_uncompress(compressed, destination, compression);
if( RET_WAS_ERROR(r) ) {
(void)unlink(destination);
return action(privdata, compressed, true, true);
return r;
}
*done_p = true;
return action(privdata, compressed, false, true);
return action(privdata, compressed, false);
}
retvalue uncompress_file(const char *compressed, const char *destination, enum compression compression) {
......
......@@ -28,9 +28,9 @@ retvalue uncompress_checkpid(pid_t, int);
/* still waiting for a client to exit */
bool uncompress_running(void);
typedef retvalue finishaction(void *, const char *, bool /*failed*/, bool /*early*/);
typedef retvalue finishaction(void *, const char *, bool /*failed*/);
/* uncompress and call action when finished */
retvalue uncompress_queue_file(const char *, const char *, enum compression, finishaction *, void *, bool *);
retvalue uncompress_queue_file(const char *, const char *, enum compression, finishaction *, void *);
/**** functions for update.c (uncompressing an earlier downloaded file) ****/
......
......@@ -1863,10 +1863,10 @@ retvalue updates_update(struct database *database, struct update_distribution *d
}
if( verbose >= 0 )
printf("Getting packages...\n");
r = downloadcache_free(cache);
RET_ENDUPDATE(result,r);
r = aptmethod_download(run, database);
RET_UPDATE(result,r);
r = downloadcache_free(cache);
RET_ENDUPDATE(result,r);
if( verbose > 0 )
printf("Shutting down aptmethods...\n");
r = aptmethod_shutdown(run);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment