razor.c
changeset 11 5361c3a3dc77
parent 9 c4338a14dd9f
child 12 71a410830f3d
     1.1 --- a/razor.c	Thu Sep 06 17:01:01 2007 -0400
     1.2 +++ b/razor.c	Fri Sep 07 00:08:43 2007 -0400
     1.3 @@ -24,7 +24,7 @@
     1.4  	if (array->alloc > 0)
     1.5  		alloc = array->alloc;
     1.6  	else
     1.7 -		alloc = 1024;
     1.8 +		alloc = 16;
     1.9  
    1.10  	while (alloc < array->size + size)
    1.11  		alloc *= 2;
    1.12 @@ -98,10 +98,13 @@
    1.13  #define RAZOR_PACKAGES 3
    1.14  #define RAZOR_REQUIRES 4
    1.15  #define RAZOR_PROVIDES 5
    1.16 +#define RAZOR_PROPERTIES 6
    1.17  
    1.18  struct razor_package {
    1.19  	unsigned long name;
    1.20  	unsigned long version;
    1.21 +	unsigned long requires;
    1.22 +	unsigned long provides;
    1.23  };
    1.24  
    1.25  struct razor_property {
    1.26 @@ -113,6 +116,7 @@
    1.27  struct razor_set {
    1.28  	struct array buckets;
    1.29  	struct array string_pool;
    1.30 +	struct array property_pool;
    1.31   	struct array packages;
    1.32   	struct array requires;
    1.33   	struct array provides;
    1.34 @@ -180,6 +184,11 @@
    1.35  			set->provides.size = size;
    1.36  			set->provides.size = size;
    1.37  			break;
    1.38 +		case RAZOR_PROPERTIES:
    1.39 +			set->property_pool.data = (void *) set->header + offset;
    1.40 +			set->property_pool.size = size;
    1.41 +			set->property_pool.size = size;
    1.42 +			break;
    1.43  		}
    1.44  	}
    1.45  	close(fd);
    1.46 @@ -204,6 +213,7 @@
    1.47  		free(set->packages.data);
    1.48  		free(set->requires.data);
    1.49  		free(set->provides.data);
    1.50 +		free(set->property_pool.data);
    1.51  	}
    1.52  
    1.53  	free(set);
    1.54 @@ -215,12 +225,14 @@
    1.55  	char data[4096];
    1.56  	struct razor_set_header *header = (struct razor_set_header *) data;
    1.57  	int fd, pool_size, packages_size, requires_size, provides_size;
    1.58 +	int properties_size;
    1.59  
    1.60  	/* Align these to pages sizes */
    1.61  	pool_size = (set->string_pool.size + 4095) & ~4095;
    1.62  	packages_size = (set->packages.size + 4095) & ~4095;
    1.63  	requires_size = (set->requires.size + 4095) & ~4095;
    1.64  	provides_size = (set->provides.size + 4095) & ~4095;
    1.65 +	properties_size = (set->property_pool.size + 4095) & ~4095;
    1.66  
    1.67  	memset(data, 0, sizeof data);
    1.68  	header->magic = RAZOR_MAGIC;
    1.69 @@ -245,10 +257,14 @@
    1.70  	header->sections[4].offset =
    1.71  		header->sections[3].offset + requires_size;
    1.72  
    1.73 -	header->sections[5].type = 0;
    1.74 +	header->sections[5].type = RAZOR_PROPERTIES;
    1.75  	header->sections[5].offset =
    1.76  		header->sections[4].offset + provides_size;
    1.77  
    1.78 +	header->sections[6].type = 0;
    1.79 +	header->sections[6].offset =
    1.80 +		header->sections[5].offset + properties_size;
    1.81 +
    1.82  	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    1.83  	if (fd < 0)
    1.84  		return -1;
    1.85 @@ -259,6 +275,7 @@
    1.86  	write_to_fd(fd, set->packages.data, packages_size);
    1.87  	write_to_fd(fd, set->requires.data, requires_size);
    1.88  	write_to_fd(fd, set->provides.data, provides_size);
    1.89 +	write_to_fd(fd, set->property_pool.data, properties_size);
    1.90  
    1.91  	return 0;
    1.92  }
    1.93 @@ -312,6 +329,19 @@
    1.94  	return p - (char *) set->string_pool.data;
    1.95  }
    1.96  
    1.97 +static unsigned long
    1.98 +add_to_property_pool(struct razor_set *set, struct array *properties)
    1.99 +{
   1.100 +	unsigned long  *p;
   1.101 +
   1.102 +	p = array_add(properties, sizeof *p);
   1.103 +	*p = 0;
   1.104 +	p = array_add(&set->property_pool, properties->size);
   1.105 +	memcpy(p, properties->data, properties->size);
   1.106 +
   1.107 +	return p - (unsigned long *) set->property_pool.data;
   1.108 +}
   1.109 +
   1.110  static void
   1.111  do_insert(struct razor_set *set, unsigned long value)
   1.112  {
   1.113 @@ -412,11 +442,26 @@
   1.114  	return razor_set_insert(set, string);
   1.115  }
   1.116  
   1.117 +struct property_context {
   1.118 +	struct array all;
   1.119 +	struct array package;
   1.120 +};
   1.121 +
   1.122  struct import_context {
   1.123  	struct razor_set *set;
   1.124 -	struct array requires;
   1.125 -	struct array provides;
   1.126 +	struct property_context requires;
   1.127 +	struct property_context provides;
   1.128  	unsigned long package;
   1.129 +	unsigned long *requires_map;
   1.130 +	unsigned long *provides_map;
   1.131 +};
   1.132 +
   1.133 +struct import_property {
   1.134 +	unsigned long name;
   1.135 +	unsigned long version;
   1.136 +	unsigned long package;
   1.137 +	unsigned long index;
   1.138 +	unsigned long unique_index;
   1.139  };
   1.140  
   1.141  static void
   1.142 @@ -439,6 +484,8 @@
   1.143  	}
   1.144  
   1.145  	ctx->package = razor_set_add_package(ctx->set, name, version);
   1.146 +	memset(&ctx->requires.package, 0, sizeof ctx->requires.package);
   1.147 +	memset(&ctx->provides.package, 0, sizeof ctx->provides.package);
   1.148  
   1.149  	return;
   1.150  }
   1.151 @@ -446,9 +493,9 @@
   1.152  static void
   1.153  parse_property(struct import_context *ctx, const char **atts, void *data)
   1.154  {
   1.155 -	unsigned long name = 0, version = 0;
   1.156 -	struct razor_property *p;
   1.157 -	struct array *array = data;
   1.158 +	unsigned long name = 0, version = 0, *r;
   1.159 +	struct import_property *p;
   1.160 +	struct property_context *pctx = data;
   1.161  	int i;
   1.162  
   1.163  	for (i = 0; atts[i]; i += 2) {
   1.164 @@ -463,10 +510,14 @@
   1.165  		return;
   1.166  	}
   1.167  
   1.168 -	p = array_add(array, sizeof *p);
   1.169 +	p = array_add(&pctx->all, sizeof *p);
   1.170  	p->name = name;
   1.171  	p->version = version;
   1.172 -	p->packages = ctx->package;
   1.173 +	p->package = ctx->package;
   1.174 +	p->index = p - (struct import_property *) pctx->all.data;
   1.175 +
   1.176 +	r = array_add(&pctx->package, sizeof *r);
   1.177 +	*r = p->index;
   1.178  }
   1.179  
   1.180  static void
   1.181 @@ -486,9 +537,19 @@
   1.182  end_element (void *data, const char *name)
   1.183  {
   1.184  	struct import_context *ctx = data;
   1.185 +	struct razor_package *package;
   1.186  
   1.187 -	if (strcmp(name, "package") == 0)
   1.188 +	if (strcmp(name, "package") == 0) {
   1.189 +		package = (struct razor_package *) ctx->set->packages.data +
   1.190 +			ctx->package;
   1.191 +		package->requires =
   1.192 +			add_to_property_pool(ctx->set, &ctx->requires.package);
   1.193 +		package->provides =
   1.194 +			add_to_property_pool(ctx->set, &ctx->provides.package);
   1.195 +		free(ctx->requires.package.data);
   1.196 +		free(ctx->provides.package.data);
   1.197  		ctx->package = 0;
   1.198 +	}
   1.199  }
   1.200  
   1.201  static char *
   1.202 @@ -577,52 +638,86 @@
   1.203  static int
   1.204  compare_properties(const void *p1, const void *p2)
   1.205  {
   1.206 -	const struct razor_property *prop1 = p1, *prop2 = p2;
   1.207 +	const struct import_property *prop1 = p1, *prop2 = p2;
   1.208  	char *pool = qsort_set->string_pool.data;
   1.209  
   1.210  	return strcmp(&pool[prop1->name], &pool[prop2->name]);
   1.211  }
   1.212  
   1.213 -static void
   1.214 +static unsigned long *
   1.215  uniqueify_properties(struct array *in, struct array *out)
   1.216  {
   1.217 -	struct razor_property *p, *q, *end;
   1.218 +	struct import_property *ip, *end;
   1.219 +	struct razor_property *rp;
   1.220 +	unsigned long *map;
   1.221 +	int i, count;
   1.222  
   1.223 -	qsort(in->data, in->size / sizeof(struct razor_property),
   1.224 -	      sizeof(struct razor_property), compare_properties);
   1.225 +	count = in->size / sizeof(struct import_property);
   1.226 +	qsort(in->data, count,
   1.227 +	      sizeof(struct import_property), compare_properties);
   1.228  
   1.229 -	q = NULL;
   1.230 +	rp = NULL;
   1.231  	end = in->data + in->size;
   1.232 -	for (p = in->data; p < end && p->name; p++) {
   1.233 -		if (q == NULL ||
   1.234 -		    p->name != q->name || p->version != q->version) {
   1.235 -			q = array_add(out, sizeof *q);
   1.236 -			q->name = p->name;
   1.237 -			q->version = p->version;
   1.238 +	for (ip = in->data; ip < end; ip++) {
   1.239 +		if (rp == NULL ||
   1.240 +		    ip->name != rp->name || ip->version != rp->version) {
   1.241 +			rp = array_add(out, sizeof *rp);
   1.242 +			rp->name = ip->name;
   1.243 +			rp->version = ip->version;
   1.244 +		}
   1.245 +		ip->unique_index = rp - (struct razor_property *) out->data;
   1.246 +	}
   1.247  
   1.248 -		}
   1.249 +	map = malloc(count * sizeof (unsigned long));
   1.250 +	ip = in->data;
   1.251 +	for (i = 0; i < count; i++)
   1.252 +		map[ip[i].index] = ip[i].unique_index;
   1.253 +
   1.254 +	return map;
   1.255 +}
   1.256 +
   1.257 +static void
   1.258 +sort_packages(struct import_context *ctx)
   1.259 +{
   1.260 +	struct razor_package *p, *end;
   1.261 +	unsigned long *pool, *r;
   1.262 +
   1.263 +	pool = ctx->set->property_pool.data;
   1.264 +	end = ctx->set->packages.data + ctx->set->packages.size;
   1.265 +	for (p = ctx->set->packages.data; p < end; p++) {
   1.266 +		for (r = &pool[p->requires]; *r; r++)
   1.267 +			*r = ctx->requires_map[*r];
   1.268 +		for (r = &pool[p->provides]; *r; r++)
   1.269 +			*r = ctx->provides_map[*r];
   1.270  	}
   1.271 +
   1.272 +	qsort(ctx->set->packages.data,
   1.273 +	      ctx->set->packages.size / sizeof(struct razor_package),
   1.274 +	      sizeof(struct razor_package), compare_packages);
   1.275  }
   1.276  
   1.277  static void
   1.278  razor_set_finish_import(struct import_context *ctx)
   1.279  {
   1.280  	qsort_set = ctx->set;
   1.281 -	qsort(ctx->set->packages.data,
   1.282 -	      ctx->set->packages.size / sizeof(struct razor_package),
   1.283 -	      sizeof(struct razor_package), compare_packages);
   1.284  
   1.285 -	uniqueify_properties(&ctx->requires, &ctx->set->requires);
   1.286 -	uniqueify_properties(&ctx->provides, &ctx->set->provides);
   1.287 +	ctx->requires_map =
   1.288 +		uniqueify_properties(&ctx->requires.all, &ctx->set->requires);
   1.289 +	ctx->provides_map =
   1.290 +		uniqueify_properties(&ctx->provides.all, &ctx->set->provides);
   1.291  
   1.292 -	free(ctx->requires.data);
   1.293 -	free(ctx->provides.data);
   1.294 +	sort_packages(ctx);
   1.295 +
   1.296 +	free(ctx->requires.all.data);
   1.297 +	free(ctx->provides.all.data);
   1.298 +	free(ctx->requires_map);
   1.299 +	free(ctx->provides_map);
   1.300  
   1.301  	fprintf(stderr, "parsed %d requires, %d unique\n",
   1.302 -		ctx->requires.size / sizeof(struct razor_property),
   1.303 +		ctx->requires.all.size / sizeof(struct import_property),
   1.304  		ctx->set->requires.size / sizeof(struct razor_property));
   1.305  	fprintf(stderr, "parsed %d provides, %d unique\n",
   1.306 -		ctx->provides.size / sizeof(struct razor_property),
   1.307 +		ctx->provides.all.size / sizeof(struct import_property),
   1.308  		ctx->set->provides.size / sizeof(struct razor_property));
   1.309  }
   1.310  
   1.311 @@ -639,28 +734,75 @@
   1.312  		printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.313  }
   1.314  
   1.315 -void
   1.316 -razor_set_list_requires(struct razor_set *set)
   1.317 +struct razor_package *
   1.318 +razor_set_get_package(struct razor_set *set, const char *package)
   1.319 +{
   1.320 +	unsigned long name;
   1.321 +	struct razor_package *p, *end;
   1.322 +
   1.323 +	name = razor_set_lookup(set, package);
   1.324 +	end = set->packages.data + set->packages.size;
   1.325 +	for (p = set->packages.data; p < end && p->name; p++)
   1.326 +		if (p->name == name)
   1.327 +			return p;
   1.328 +
   1.329 +	return NULL;
   1.330 +}
   1.331 +
   1.332 +static void
   1.333 +razor_set_list_all_properties(struct razor_set *set, struct array *properties)
   1.334  {
   1.335  	struct razor_property *p, *end;
   1.336  	char *pool;
   1.337  
   1.338  	pool = set->string_pool.data;
   1.339 -	end = set->requires.data + set->requires.size;
   1.340 -	for (p = set->requires.data; p < end && p->name; p++)
   1.341 +	end = properties->data + properties->size;
   1.342 +	for (p = properties->data; p < end && p->name; p++)
   1.343  		printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.344  }
   1.345  
   1.346  void
   1.347 -razor_set_list_provides(struct razor_set *set)
   1.348 +razor_set_list_requires(struct razor_set *set, const char *name)
   1.349  {
   1.350 -	struct razor_property *p, *end;
   1.351 +	struct razor_property *p, *requires;
   1.352 +	struct razor_package *package;
   1.353 +	unsigned long *r;
   1.354  	char *pool;
   1.355  
   1.356 -	pool = set->string_pool.data;
   1.357 -	end = set->provides.data + set->provides.size;
   1.358 -	for (p = set->provides.data; p < end && p->name; p++)
   1.359 -		printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.360 +	if (name) {
   1.361 +		package = razor_set_get_package(set, name);
   1.362 +		r = (unsigned long *) set->property_pool.data +
   1.363 +			package->requires;
   1.364 +		requires = set->requires.data;
   1.365 +		pool = set->string_pool.data;
   1.366 +		while (*r) {
   1.367 +			p = &requires[*r++];
   1.368 +			printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.369 +		}
   1.370 +	} else
   1.371 +		razor_set_list_all_properties(set, &set->requires);
   1.372 +}
   1.373 +
   1.374 +void
   1.375 +razor_set_list_provides(struct razor_set *set, const char *name)
   1.376 +{
   1.377 +	struct razor_property *p, *provides;
   1.378 +	struct razor_package *package;
   1.379 +	unsigned long *r;
   1.380 +	char *pool;
   1.381 +
   1.382 +	if (name) {
   1.383 +		package = razor_set_get_package(set, name);
   1.384 +		r = (unsigned long *) set->property_pool.data +
   1.385 +			package->provides;
   1.386 +		provides = set->provides.data;
   1.387 +		pool = set->string_pool.data;
   1.388 +		while (*r) {
   1.389 +			p = &provides[*r++];
   1.390 +			printf("%s %s\n", &pool[p->name], &pool[p->version]);
   1.391 +		}
   1.392 +	} else 
   1.393 +		razor_set_list_all_properties(set, &set->provides);
   1.394  }
   1.395  
   1.396  void
   1.397 @@ -764,11 +906,11 @@
   1.398  		razor_set_destroy(set);
   1.399  	} else if (strcmp(argv[1], "list-requires") == 0) {
   1.400  		set = razor_set_open(repo_filename);
   1.401 -		razor_set_list_requires(set);
   1.402 +		razor_set_list_requires(set, argv[2]);
   1.403  		razor_set_destroy(set);
   1.404  	} else if (strcmp(argv[1], "list-provides") == 0) {
   1.405  		set = razor_set_open(repo_filename);
   1.406 -		razor_set_list_provides(set);
   1.407 +		razor_set_list_provides(set, argv[2]);
   1.408  		razor_set_destroy(set);
   1.409  	} else if (strcmp(argv[1], "info") == 0) {
   1.410  		set = razor_set_open(repo_filename);