downloadcache.c 4.14 KB
Newer Older
Bernhard Link's avatar
Bernhard Link committed
1
/*  This file is part of "reprepro"
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *  Copyright (C) 2004 Bernhard R. Link
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <config.h>

#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include "error.h"
#include "strlist.h"
#include "names.h"
#include "dirs.h"
#include "files.h"
#include "downloadcache.h"


struct downloaditem {
32
	struct downloaditem *parent,*left,*right;
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
	struct tobedone *todo;
};

struct downloadcache {
	struct downloaditem *items;
};

/* Initialize a new download session */
retvalue downloadcache_initialize(struct downloadcache **download) {
	struct downloadcache *cache;

	cache = malloc(sizeof(struct downloadcache));
	if( cache == NULL )
		return RET_ERROR_OOM;
	cache->items = NULL;
	*download = cache;
	return RET_OK;
}

/* free all memory */
53 54 55 56 57 58 59
static void freeitem(struct downloaditem *item) {
	if( item == NULL )
		return;
	freeitem(item->left);
	freeitem(item->right);
	free(item);
}
60 61
retvalue downloadcache_free(struct downloadcache *download) {

62 63
	if( download == NULL )
		return RET_NOTHING;
64

65
	freeitem(download->items);
66 67 68 69
	free(download);
	return RET_OK;
}

70 71 72 73 74 75
const struct downloaditem *searchforitem(struct downloadcache *list,
					const char *filekey,
					struct downloaditem **p,
					struct downloaditem ***h) {
	struct downloaditem *item;
	int c;
76

77 78 79 80 81
	item = list->items;
	while( item ) {
		*p = item;
		c = strcmp(filekey,item->todo->filekey);
		if( c == 0 )
82
			return item;
83 84 85 86 87 88 89
		else if( c < 0 ) {
			*h = &item->left;
			item = item->left;
		} else {
			*h = &item->right;
			item = item->right;
		}
90 91 92 93 94 95 96 97 98 99
	}
	return NULL;
}

/* queue a new file to be downloaded: 
 * results in RET_ERROR_WRONG_MD5, if someone else already asked
 * for the same destination with other md5sum created. */
retvalue downloadcache_add(struct downloadcache *cache,filesdb filesdb,struct aptmethod *method,const char *orig,const char *filekey,const char *md5sum) {

	const struct downloaditem *i;
100
	struct downloaditem *item,**h,*parent;
101 102 103 104
	char *fullfilename;
	retvalue r;

	assert(filesdb && cache && method);
105
	r = files_expect(filesdb,filekey,md5sum);
106 107 108
	if( r != RET_NOTHING )
		return r;

109
	i = searchforitem(cache,filekey,&parent,&h);
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
	if( i != NULL ) {
		if( strcmp(md5sum,i->todo->md5sum) == 0 )
			return RET_NOTHING;
		// TODO: print error;
		return RET_ERROR_WRONG_MD5;
	}
	item = malloc(sizeof(struct downloaditem));
	if( item == NULL )
		return RET_ERROR_OOM;

	fullfilename = calc_dirconcat(filesdb->mirrordir,filekey);
	if( fullfilename == NULL ) {
		free(item);
		return RET_ERROR_OOM;
	}
	(void)dirs_make_parent(fullfilename);
	r = aptmethod_queuefile(method,orig,fullfilename,md5sum,filekey,&item->todo);
	free(fullfilename);
	if( RET_WAS_ERROR(r) ) {
		free(item);
		return r;
	}
132 133 134 135 136 137 138 139 140 141
	item->left = item->right = NULL;

	if( cache->items == NULL ) {
		cache->items = item;
		item->parent = NULL;
		return RET_OK;
	}
	item->parent = parent;
	*h = item;

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	return RET_OK;
}

/* some as above, only for more files... */
retvalue downloadcache_addfiles(struct downloadcache *cache,filesdb filesdb,
		struct aptmethod *method,
		const struct strlist *origfiles,
		const struct strlist *filekeys,
		const struct strlist *md5sums) {
	retvalue result,r;
	int i;

	assert(origfiles && filekeys && md5sums
		&& origfiles->count == filekeys->count
		&& md5sums->count == filekeys->count);

	result = RET_NOTHING;
	
	for( i = 0 ; i < filekeys->count ; i++ ) {
		r = downloadcache_add(cache,filesdb,method,
			origfiles->values[i],
			filekeys->values[i],
			md5sums->values[i]);
		RET_UPDATE(result,r);
	}
	return result;
}