Implement property (requires/provides) to package mapping.
authorKristian H?gsberg <krh@redhat.com>
Tue Sep 11 19:25:32 2007 -0400 (2007-09-11)
changeset 18b2bf852ca8d1
parent 17 67029e580a0e
child 19 d2a716dd92bd
Implement property (requires/provides) to package mapping.
TODO
razor.c
     1.1 --- a/TODO	Fri Sep 07 14:17:39 2007 -0400
     1.2 +++ b/TODO	Tue Sep 11 19:25:32 2007 -0400
     1.3 @@ -52,3 +52,15 @@
     1.4    and we need to control the on-disk format for these tools.
     1.5  
     1.6  - 20740 requires, 2246 unique... hmm.
     1.7 +
     1.8 +- diff from one package set to another answers: "what changed in
     1.9 +  rawhide between since yesterday?"
    1.10 +
    1.11 +- rewrite qsort and bsearch that doesn't require global context var
    1.12 +  and can output a map describing the permutaion.
    1.13 +
    1.14 +- move package lists out of the property pool, remap properties and
    1.15 +  packages in the two pools by just iterating through the pools.
    1.16 +
    1.17 +- use hash table for package and property lists so we only store
    1.18 +  unique lists (like for string pool).
     2.1 --- a/razor.c	Fri Sep 07 14:17:39 2007 -0400
     2.2 +++ b/razor.c	Tue Sep 11 19:25:32 2007 -0400
     2.3 @@ -141,14 +141,7 @@
     2.4  struct razor_set *
     2.5  razor_set_create(void)
     2.6  {
     2.7 -	struct razor_set *set;
     2.8 -	char *p;
     2.9 -
    2.10 -	set = zalloc(sizeof(struct razor_set));
    2.11 -	p = array_add(&set->string_pool, 1);
    2.12 -	*p = '\0';
    2.13 -
    2.14 -	return set;
    2.15 +	return zalloc(sizeof(struct razor_set));
    2.16  }
    2.17  
    2.18  struct razor_set *
    2.19 @@ -331,7 +324,7 @@
    2.20  	unsigned long  *p;
    2.21  
    2.22  	p = array_add(properties, sizeof *p);
    2.23 -	*p = 0;
    2.24 +	*p = ~0ul;
    2.25  	p = array_add(&set->property_pool, properties->size);
    2.26  	memcpy(p, properties->data, properties->size);
    2.27  
    2.28 @@ -390,7 +383,7 @@
    2.29  	unsigned long token;
    2.30  
    2.31  	if (string == NULL)
    2.32 -		return 0;
    2.33 +		return razor_set_tokenize(set, "");
    2.34  
    2.35  	token = razor_set_lookup(set, string);
    2.36  	if (token != 0)
    2.37 @@ -408,11 +401,20 @@
    2.38  	struct razor_set *set;
    2.39  	struct import_property_context requires;
    2.40  	struct import_property_context provides;
    2.41 -	unsigned long package;
    2.42 +	struct array packages;
    2.43 +	struct import_package *package;
    2.44  	unsigned long *requires_map;
    2.45  	unsigned long *provides_map;
    2.46  };
    2.47  
    2.48 +struct import_package {
    2.49 +	unsigned long name;
    2.50 +	unsigned long version;
    2.51 +	unsigned long requires;
    2.52 +	unsigned long provides;
    2.53 +	unsigned long index;
    2.54 +};
    2.55 +
    2.56  struct import_property {
    2.57  	unsigned long name;
    2.58  	unsigned long version;
    2.59 @@ -425,13 +427,14 @@
    2.60  import_context_add_package(struct import_context *ctx,
    2.61  			   const char *name, const char *version)
    2.62  {
    2.63 -	struct razor_package *p;
    2.64 +	struct import_package *p;
    2.65  
    2.66 -	p = array_add(&ctx->set->packages, sizeof *p);
    2.67 +	p = array_add(&ctx->packages, sizeof *p);
    2.68  	p->name = razor_set_tokenize(ctx->set, name);
    2.69  	p->version = razor_set_tokenize(ctx->set, version);
    2.70 +	p->index = p - (struct import_package *) ctx->packages.data;
    2.71  
    2.72 -	ctx->package = p - (struct razor_package *) ctx->set->packages.data;
    2.73 +	ctx->package = p;
    2.74  	array_init(&ctx->requires.package);
    2.75  	array_init(&ctx->provides.package);
    2.76  }
    2.77 @@ -439,9 +442,9 @@
    2.78  void
    2.79  import_context_finish_package(struct import_context *ctx)
    2.80  {
    2.81 -	struct razor_package *p;
    2.82 +	struct import_package *p;
    2.83  
    2.84 -	p = (struct razor_package *) ctx->set->packages.data + ctx->package;
    2.85 +	p = ctx->package;
    2.86  	p->requires = add_to_property_pool(ctx->set, &ctx->requires.package);
    2.87  	p->provides = add_to_property_pool(ctx->set, &ctx->provides.package);
    2.88  
    2.89 @@ -460,7 +463,7 @@
    2.90  	p = array_add(&pctx->all, sizeof *p);
    2.91  	p->name = razor_set_tokenize(ctx->set, name);
    2.92  	p->version = razor_set_tokenize(ctx->set, version);
    2.93 -	p->package = ctx->package;
    2.94 +	p->package = ctx->package->index;
    2.95  	p->index = p - (struct import_property *) pctx->all.data;
    2.96  
    2.97  	r = array_add(&pctx->package, sizeof *r);
    2.98 @@ -609,7 +612,7 @@
    2.99  static int
   2.100  compare_packages(const void *p1, const void *p2)
   2.101  {
   2.102 -	const struct razor_package *pkg1 = p1, *pkg2 = p2;
   2.103 +	const struct import_package *pkg1 = p1, *pkg2 = p2;
   2.104  	char *pool = qsort_set->string_pool.data;
   2.105  
   2.106  	return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
   2.107 @@ -630,12 +633,14 @@
   2.108  }
   2.109  
   2.110  static unsigned long *
   2.111 -uniqueify_properties(struct array *in, struct array *out)
   2.112 +uniqueify_properties(struct razor_set *set,
   2.113 +		     struct array *in, struct array *out)
   2.114  {
   2.115  	struct import_property *ip, *end;
   2.116 -	struct razor_property *rp;
   2.117 -	unsigned long *map;
   2.118 -	int i, count;
   2.119 +	struct razor_property *rp, *rp_end;
   2.120 +	struct array *pkgs, *p;
   2.121 +	unsigned long *map, *r;
   2.122 +	int i, count, unique;
   2.123  
   2.124  	count = in->size / sizeof(struct import_property);
   2.125  	qsort(in->data, count,
   2.126 @@ -658,40 +663,107 @@
   2.127  	for (i = 0; i < count; i++)
   2.128  		map[ip[i].index] = ip[i].unique_index;
   2.129  
   2.130 +	unique = out->size / sizeof(*rp);
   2.131 +	pkgs = zalloc(unique * sizeof *pkgs);
   2.132 +	for (ip = in->data; ip < end; ip++) {
   2.133 +		r = array_add(&pkgs[ip->unique_index], sizeof *r);
   2.134 +		*r = ip->package;
   2.135 +	}
   2.136 +
   2.137 +	rp_end = out->data + out->size;
   2.138 +	for (rp = out->data, p = pkgs; rp < rp_end; rp++, p++)
   2.139 +		rp->packages = add_to_property_pool(set, p);
   2.140 +
   2.141 +	free(pkgs);
   2.142 +
   2.143  	return map;
   2.144  }
   2.145  
   2.146  static void
   2.147 -sort_packages(struct import_context *ctx)
   2.148 +remap_package_links(struct import_context *ctx)
   2.149  {
   2.150 -	struct razor_package *p, *end;
   2.151 +	struct import_package *p, *end;
   2.152  	unsigned long *pool, *r;
   2.153  
   2.154  	pool = ctx->set->property_pool.data;
   2.155 -	end = ctx->set->packages.data + ctx->set->packages.size;
   2.156 -	for (p = ctx->set->packages.data; p < end; p++) {
   2.157 -		for (r = &pool[p->requires]; *r; r++)
   2.158 +	end = ctx->packages.data + ctx->packages.size;
   2.159 +	for (p = ctx->packages.data; p < end; p++) {
   2.160 +		for (r = &pool[p->requires]; ~*r; r++)
   2.161  			*r = ctx->requires_map[*r];
   2.162 -		for (r = &pool[p->provides]; *r; r++)
   2.163 +		for (r = &pool[p->provides]; ~*r; r++)
   2.164  			*r = ctx->provides_map[*r];
   2.165  	}
   2.166 +}
   2.167  
   2.168 -	qsort(ctx->set->packages.data,
   2.169 -	      ctx->set->packages.size / sizeof(struct razor_package),
   2.170 -	      sizeof(struct razor_package), compare_packages);
   2.171 +static void
   2.172 +remap_property_links(struct import_context *ctx)
   2.173 +{
   2.174 +	struct razor_property *p, *end;
   2.175 +	struct import_package *ip;
   2.176 +	unsigned long *map, *pool, *r;
   2.177 +	int i, count;
   2.178 +
   2.179 +	pool = ctx->set->property_pool.data;
   2.180 +	count = ctx->packages.size / sizeof(struct import_package);
   2.181 +	map = malloc(count * sizeof *map);
   2.182 +	ip = ctx->packages.data;
   2.183 +	for (i = 0; i < count; i++)
   2.184 +		map[ip[i].index] = i;
   2.185 +
   2.186 +	/* FIXME: This will break if we implement package list sharing
   2.187 +	 * for all properties, since we'll remap those lists more than
   2.188 +	 * once. We should just have a separate pool for property
   2.189 +	 * lists and a separate pool for package lists and remap it as
   2.190 +	 * a flat pool.  Right now, as property lists and package
   2.191 +	 * lists are mixed, we can't do that. */
   2.192 +
   2.193 +	end = ctx->set->requires.data + ctx->set->requires.size;
   2.194 +	for (p = ctx->set->requires.data; p < end; p++)
   2.195 +		for (r = &pool[p->packages]; ~*r; r++)
   2.196 +			*r = map[*r];
   2.197 +
   2.198 +	end = ctx->set->provides.data + ctx->set->provides.size;
   2.199 +	for (p = ctx->set->provides.data; p < end; p++)
   2.200 +		for (r = &pool[p->packages]; ~*r; r++)
   2.201 +			*r = map[*r];
   2.202 +
   2.203 +	free(map);
   2.204  }
   2.205  
   2.206  static struct razor_set *
   2.207  razor_finish_import(struct import_context *ctx)
   2.208  {
   2.209 +	struct import_package *ip;
   2.210 +	struct razor_package *rp;
   2.211 +	int i, count;
   2.212 +
   2.213  	qsort_set = ctx->set;
   2.214  
   2.215  	ctx->requires_map =
   2.216 -		uniqueify_properties(&ctx->requires.all, &ctx->set->requires);
   2.217 +		uniqueify_properties(ctx->set, 
   2.218 +				     &ctx->requires.all,
   2.219 +				     &ctx->set->requires);
   2.220  	ctx->provides_map =
   2.221 -		uniqueify_properties(&ctx->provides.all, &ctx->set->provides);
   2.222 +		uniqueify_properties(ctx->set,
   2.223 +				     &ctx->provides.all,
   2.224 +				     &ctx->set->provides);
   2.225  
   2.226 -	sort_packages(ctx);
   2.227 +	remap_package_links(ctx);
   2.228 +
   2.229 +	count = ctx->packages.size / sizeof(struct import_package);
   2.230 +	qsort(ctx->packages.data, count,
   2.231 +	      sizeof(struct import_package), compare_packages);
   2.232 +
   2.233 +	ip = ctx->packages.data;
   2.234 +	for (i = 0; i < count; i++, ip++, rp++) {
   2.235 +		rp = array_add(&ctx->set->packages, sizeof *rp);
   2.236 +		rp->name = ip->name;
   2.237 +		rp->version = ip->version;
   2.238 +		rp->requires = ip->requires;
   2.239 +		rp->provides = ip->provides;
   2.240 +	}
   2.241 +
   2.242 +	remap_property_links(ctx);
   2.243  
   2.244  	free(ctx->requires.all.data);
   2.245  	free(ctx->provides.all.data);
   2.246 @@ -862,6 +934,36 @@
   2.247  		       sizeof(struct razor_package), compare_package_name);
   2.248  }
   2.249  
   2.250 +static int
   2.251 +compare_property_name(const void *key, const void *data)
   2.252 +{
   2.253 +	const struct razor_property *p = data;
   2.254 +	char *pool;
   2.255 +
   2.256 +	pool = bsearch_set->string_pool.data;
   2.257 +
   2.258 +	return strcmp(key, &pool[p->name]);
   2.259 +}
   2.260 +
   2.261 +struct razor_property *
   2.262 +razor_set_get_property(struct razor_set *set,
   2.263 +		       struct array *properties,
   2.264 +		       const char *property)
   2.265 +{
   2.266 +	struct razor_property *p, *start;
   2.267 +
   2.268 +	bsearch_set = set;
   2.269 +	p = bsearch(property, properties->data,
   2.270 +		    properties->size / sizeof(struct razor_property),
   2.271 +		    sizeof(struct razor_property), compare_property_name);
   2.272 +
   2.273 +	start = properties->data;
   2.274 +	while (p > start && (p - 1)->name == p->name)
   2.275 +		p--;
   2.276 +
   2.277 +	return p;
   2.278 +}
   2.279 +
   2.280  static void
   2.281  razor_set_list_all_properties(struct razor_set *set, struct array *properties)
   2.282  {
   2.283 @@ -888,7 +990,7 @@
   2.284  			package->requires;
   2.285  		requires = set->requires.data;
   2.286  		pool = set->string_pool.data;
   2.287 -		while (*r) {
   2.288 +		while (~*r) {
   2.289  			p = &requires[*r++];
   2.290  			printf("%s %s\n", &pool[p->name], &pool[p->version]);
   2.291  		}
   2.292 @@ -910,7 +1012,7 @@
   2.293  			package->provides;
   2.294  		provides = set->provides.data;
   2.295  		pool = set->string_pool.data;
   2.296 -		while (*r) {
   2.297 +		while (~*r) {
   2.298  			p = &provides[*r++];
   2.299  			printf("%s %s\n", &pool[p->name], &pool[p->version]);
   2.300  		}
   2.301 @@ -919,6 +1021,35 @@
   2.302  }
   2.303  
   2.304  void
   2.305 +razor_set_list_property_packages(struct razor_set *set,
   2.306 +				 struct array *properties,
   2.307 +				 const char *name)
   2.308 +{
   2.309 +	struct razor_property *property, *end;
   2.310 +	struct razor_package *p, *packages;
   2.311 +	unsigned long *r;
   2.312 +	char *pool;
   2.313 +
   2.314 +	if (name == NULL)
   2.315 +		return;
   2.316 +
   2.317 +	property = razor_set_get_property(set, properties, name);
   2.318 +	packages = set->packages.data;
   2.319 +	pool = set->string_pool.data;
   2.320 +	end = properties->data + properties->size;
   2.321 +	while (property < end && strcmp(name, &pool[property->name]) == 0) {
   2.322 +		r = (unsigned long *)
   2.323 +			set->property_pool.data + property->packages;
   2.324 +		while (~*r) {
   2.325 +			p = &packages[*r++];
   2.326 +			printf("%s %s\n",
   2.327 +			       &pool[p->name], &pool[p->version]);
   2.328 +		}
   2.329 +		property++;
   2.330 +	}
   2.331 +}
   2.332 +
   2.333 +void
   2.334  razor_set_info(struct razor_set *set)
   2.335  {
   2.336  	unsigned int offset, size;
   2.337 @@ -926,7 +1057,7 @@
   2.338  
   2.339  	for (i = 0; i < set->header->sections[i].type; i++) {
   2.340  		offset = set->header->sections[i].offset;
   2.341 -		size = set->header->sections[i + 1].offset - offset;
   2.342 +		size = set->header->sections[i].size;
   2.343  
   2.344  		switch (set->header->sections[i].type) {
   2.345  		case RAZOR_STRINGS:
   2.346 @@ -941,6 +1072,9 @@
   2.347  		case RAZOR_PROVIDES:
   2.348  			printf("provides section:\t%dkb\n", size / 1024);
   2.349  			break;
   2.350 +		case RAZOR_PROPERTIES:
   2.351 +			printf("properties section:\t%dkb\n", size / 1024);
   2.352 +			break;
   2.353  		}
   2.354  	}
   2.355  }
   2.356 @@ -1019,6 +1153,14 @@
   2.357  		set = razor_set_open(repo_filename);
   2.358  		razor_set_list_provides(set, argv[2]);
   2.359  		razor_set_destroy(set);
   2.360 +	} else if (strcmp(argv[1], "what-requires") == 0) {
   2.361 +		set = razor_set_open(repo_filename);
   2.362 +		razor_set_list_property_packages(set, &set->requires, argv[2]);
   2.363 +		razor_set_destroy(set);
   2.364 +	} else if (strcmp(argv[1], "what-provides") == 0) {
   2.365 +		set = razor_set_open(repo_filename);
   2.366 +		razor_set_list_property_packages(set, &set->provides, argv[2]);
   2.367 +		razor_set_destroy(set);
   2.368  	} else if (strcmp(argv[1], "info") == 0) {
   2.369  		set = razor_set_open(repo_filename);
   2.370  		razor_set_info(set);
   2.371 @@ -1029,6 +1171,7 @@
   2.372  			return 1;
   2.373  		razor_set_write(set, rawhide_repo_filename);
   2.374  		razor_set_destroy(set);
   2.375 +		printf("wrote %s\n", rawhide_repo_filename);
   2.376  	} else {
   2.377  		usage();
   2.378  	}