razor.c
author Kristian H?gsberg <krh@redhat.com>
Mon Jun 09 12:47:37 2008 -0400 (2008-06-09)
changeset 230 c1e2aed8dd07
parent 220 1fcb5c23034a
child 237 715b18dc94f3
permissions -rw-r--r--
Rewrite depsolver to use a series of passes over all packages.

The big change is that we follow one step of the depedency chain for
each package to resolve in each iteration, and repeat until there are
no more possible moves. In contrast the old depsolver would try to
follow the dependency chain completely for one package at a time.

This new approach is simpler and faster, and at the same time more
roboust. Instead of knowing how one newly installed package may
affect other packages (obsoleting, pulling in new packages etc), the
new algorithm just looks at the total list of requires, provides,
obsoletes and conflicts after installing new packages.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #define _GNU_SOURCE
    21 
    22 #include <stdlib.h>
    23 #include <stddef.h>
    24 #include <stdint.h>
    25 #include <stdio.h>
    26 #include <string.h>
    27 #include <sys/types.h>
    28 #include <sys/stat.h>
    29 #include <sys/mman.h>
    30 #include <unistd.h>
    31 #include <fcntl.h>
    32 #include <errno.h>
    33 #include <ctype.h>
    34 #include <fnmatch.h>
    35 
    36 #include "razor.h"
    37 #include "razor-internal.h"
    38 #include "types.h"
    39 
    40 struct razor_set_section {
    41 	uint32_t type;
    42 	uint32_t offset;
    43 	uint32_t size;
    44 };
    45 
    46 struct razor_set_header {
    47 	uint32_t magic;
    48 	uint32_t version;
    49 	struct razor_set_section sections[0];
    50 };
    51 
    52 #define RAZOR_MAGIC 0x7a7a7a7a
    53 #define RAZOR_VERSION 1
    54 
    55 #define RAZOR_STRING_POOL	0
    56 #define RAZOR_PACKAGES		1
    57 #define RAZOR_PROPERTIES	2
    58 #define RAZOR_FILES		3
    59 #define RAZOR_PACKAGE_POOL	4
    60 #define RAZOR_PROPERTY_POOL	5
    61 #define RAZOR_FILE_POOL		6
    62 
    63 struct razor_package {
    64 	uint name  : 24;
    65 	uint flags : 8;
    66 	uint32_t version;
    67 	uint32_t arch;
    68 	struct list_head properties;
    69 	struct list_head files;
    70 };
    71 
    72 struct razor_property {
    73 	uint name  : 24;
    74 	uint flags : 6;
    75 	enum razor_property_type type : 2;
    76 	enum razor_version_relation relation : 32;
    77 	uint32_t version;
    78 	struct list_head packages;
    79 };
    80 
    81 struct razor_entry {
    82 	uint name  : 24;
    83 	uint flags : 8;
    84 	uint32_t start;
    85 	struct list_head packages;
    86 };
    87 
    88 #define RAZOR_ENTRY_LAST	0x80
    89 
    90 struct razor_set {
    91 	struct array string_pool;
    92  	struct array packages;
    93  	struct array properties;
    94  	struct array files;
    95 	struct array package_pool;
    96  	struct array property_pool;
    97  	struct array file_pool;
    98 	struct razor_set_header *header;
    99 };
   100 
   101 struct import_entry {
   102 	uint32_t package;
   103 	char *name;
   104 };
   105 
   106 struct import_directory {
   107 	uint32_t name, count;
   108 	struct array files;
   109 	struct array packages;
   110 	struct import_directory *last;
   111 };
   112 
   113 struct razor_importer {
   114 	struct razor_set *set;
   115 	struct hashtable table;
   116 	struct razor_package *package;
   117 	struct array properties;
   118 	struct array files;
   119 	struct array file_requires;
   120 };
   121 
   122 static void *
   123 zalloc(size_t size)
   124 {
   125 	void *p;
   126 
   127 	p = malloc(size);
   128 	memset(p, 0, size);
   129 
   130 	return p;
   131 }
   132 
   133 struct razor_set_section razor_sections[] = {
   134 	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
   135 	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
   136 	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
   137 	{ RAZOR_FILES,		offsetof(struct razor_set, files) },
   138 	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
   139 	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
   140 	{ RAZOR_FILE_POOL,	offsetof(struct razor_set, file_pool) },
   141 };
   142 
   143 struct razor_set *
   144 razor_set_create(void)
   145 {
   146 	struct razor_set *set;
   147 	struct razor_entry *e;
   148 	char *empty;
   149 
   150 	set = zalloc(sizeof *set);
   151 
   152 	e = array_add(&set->files, sizeof *e);
   153 	empty = array_add(&set->string_pool, 1);
   154 	*empty = '\0';
   155 	e->name = 0;
   156 	e->flags = RAZOR_ENTRY_LAST;
   157 	e->start = 0;
   158 	list_set_empty(&e->packages);
   159 
   160 	return set;
   161 }
   162 
   163 struct razor_set *
   164 razor_set_open(const char *filename)
   165 {
   166 	struct razor_set *set;
   167 	struct razor_set_section *s;
   168 	struct stat stat;
   169 	struct array *array;
   170 	int fd;
   171 
   172 	set = zalloc(sizeof *set);
   173 	fd = open(filename, O_RDONLY);
   174 	if (fstat(fd, &stat) < 0)
   175 		return NULL;
   176 	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   177 	if (set->header == MAP_FAILED) {
   178 		free(set);
   179 		return NULL;
   180 	}
   181 
   182 	for (s = set->header->sections; ~s->type; s++) {
   183 		if (s->type >= ARRAY_SIZE(razor_sections))
   184 			continue;
   185 		if (s->type != razor_sections[s->type].type)
   186 			continue;
   187 		array = (void *) set + razor_sections[s->type].offset;
   188 		array->data = (void *) set->header + s->offset;
   189 		array->size = s->size;
   190 		array->alloc = s->size;
   191 	}
   192 	close(fd);
   193 
   194 	return set;
   195 }
   196 
   197 void
   198 razor_set_destroy(struct razor_set *set)
   199 {
   200 	unsigned int size;
   201 	struct array *a;
   202 	int i;
   203 
   204 	if (set->header) {
   205 		for (i = 0; set->header->sections[i].type; i++)
   206 			;
   207 		size = set->header->sections[i].type;
   208 		munmap(set->header, size);
   209 	} else {
   210 		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   211 			a = (void *) set + razor_sections[i].offset;
   212 			free(a->data);
   213 		}
   214 	}
   215 
   216 	free(set);
   217 }
   218 
   219 int
   220 razor_set_write_to_fd(struct razor_set *set, int fd)
   221 {
   222 	char data[4096];
   223 	struct razor_set_header *header = (struct razor_set_header *) data;
   224 	struct array *a;
   225 	uint32_t offset;
   226 	int i;
   227 
   228 	memset(data, 0, sizeof data);
   229 	header->magic = RAZOR_MAGIC;
   230 	header->version = RAZOR_VERSION;
   231 	offset = sizeof data;
   232 
   233 	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   234 		if (razor_sections[i].type != i)
   235 			continue;
   236 		a = (void *) set + razor_sections[i].offset;
   237 		header->sections[i].type = i;
   238 		header->sections[i].offset = offset;
   239 		header->sections[i].size = a->size;
   240 		offset += ALIGN(a->size, 4096);
   241 	}
   242 
   243 	header->sections[i].type = ~0;
   244 	header->sections[i].offset = 0;
   245 	header->sections[i].size = 0;
   246 
   247 	razor_write(fd, data, sizeof data);
   248 	memset(data, 0, sizeof data);
   249 	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   250 		if (razor_sections[i].type != i)
   251 			continue;
   252 		a = (void *) set + razor_sections[i].offset;
   253 		razor_write(fd, a->data, a->size);
   254 		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
   255 	}
   256 
   257 	return 0;
   258 }
   259 
   260 int
   261 razor_set_write(struct razor_set *set, const char *filename)
   262 {
   263 	int fd, status;
   264 
   265 	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
   266 	if (fd < 0)
   267 		return -1;
   268 
   269 	status = razor_set_write_to_fd(set, fd);
   270 	if (status) {
   271 	    close(fd);
   272 	    return status;
   273 	}
   274 
   275 	return close(fd);
   276 }
   277 
   278 void
   279 razor_build_evr(char *evr_buf, int size, const char *epoch,
   280 		const char *version, const char *release)
   281 {
   282 	int len;
   283 
   284 	if (!version || !*version) {
   285 		*evr_buf = '\0';
   286 		return;
   287 	}
   288 
   289 	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
   290 		len = snprintf(evr_buf, size, "%s:", epoch);
   291 		evr_buf += len;
   292 		size -= len;
   293 	}
   294 	len = snprintf(evr_buf, size, "%s", version);
   295 	evr_buf += len;
   296 	size -= len;
   297 	if (release && *release)
   298 		snprintf(evr_buf, size, "-%s", release);
   299 }
   300 
   301 void
   302 razor_importer_begin_package(struct razor_importer *importer,
   303 			     const char *name,
   304 			     const char *version,
   305 			     const char *arch)
   306 {
   307 	struct razor_package *p;
   308 
   309 	p = array_add(&importer->set->packages, sizeof *p);
   310 	p->name = hashtable_tokenize(&importer->table, name);
   311 	p->flags = 0;
   312 	p->version = hashtable_tokenize(&importer->table, version);
   313 	p->arch = hashtable_tokenize(&importer->table, arch);
   314 
   315 	importer->package = p;
   316 	array_init(&importer->properties);
   317 }
   318 
   319 void
   320 razor_importer_finish_package(struct razor_importer *importer)
   321 {
   322 	list_set_array(&importer->package->properties,
   323 		       &importer->set->property_pool,
   324 		       &importer->properties,
   325 		       1);
   326 
   327 	array_release(&importer->properties);
   328 }
   329 
   330 void
   331 razor_importer_add_property(struct razor_importer *importer,
   332 			    const char *name,
   333 			    enum razor_version_relation relation,
   334 			    const char *version,
   335 			    enum razor_property_type type)
   336 {
   337 	struct razor_property *p;
   338 	uint32_t *r;
   339 
   340 	p = array_add(&importer->set->properties, sizeof *p);
   341 	p->name = hashtable_tokenize(&importer->table, name);
   342 	p->flags = 0;
   343 	p->type = type;
   344 	p->relation = relation;
   345 	p->version = hashtable_tokenize(&importer->table, version);
   346 	list_set_ptr(&p->packages, importer->package -
   347 		     (struct razor_package *) importer->set->packages.data);
   348 
   349 	r = array_add(&importer->properties, sizeof *r);
   350 	*r = p - (struct razor_property *) importer->set->properties.data;
   351 
   352 	if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
   353 		r = array_add(&importer->file_requires, sizeof *r);
   354 		*r = p->name;
   355 	}
   356 }
   357 
   358 void
   359 razor_importer_add_file(struct razor_importer *importer, const char *name)
   360 {
   361 	struct import_entry *e;
   362 
   363 	e = array_add(&importer->files, sizeof *e);
   364 
   365 	e->package = importer->package -
   366 		(struct razor_package *) importer->set->packages.data;
   367 	e->name = strdup(name);
   368 }
   369 
   370 struct razor_importer *
   371 razor_importer_new(void)
   372 {
   373 	struct razor_importer *importer;
   374 
   375 	importer = zalloc(sizeof *importer);
   376 	importer->set = razor_set_create();
   377 	hashtable_init(&importer->table, &importer->set->string_pool);
   378 
   379 	return importer;
   380 }
   381 
   382 /* Destroy an importer without creating the set. */
   383 void
   384 razor_importer_destroy(struct razor_importer *importer)
   385 {
   386 	/* FIXME: write this */
   387 }
   388 
   389 static int
   390 versioncmp(const char *s1, const char *s2)
   391 {
   392 	const char *p1, *p2;
   393 	long n1, n2;
   394 	int res;
   395 
   396 	n1 = strtol(s1, (char **) &p1, 10);
   397 	n2 = strtol(s2, (char **) &p2, 10);
   398 
   399 	/* Epoch; if one but not the other has an epoch set, default
   400 	 * the epoch-less version to 0. */
   401 	res = (*p1 == ':') - (*p2 == ':');
   402 	if (res < 0) {
   403 		n1 = 0;
   404 		p1 = s1;
   405 		p2++;
   406 	} else if (res > 0) {
   407 		p1++;
   408 		n2 = 0;
   409 		p2 = s2;
   410 	}
   411 
   412 	if (n1 != n2)
   413 		return n1 - n2;
   414 	while (*p1 && *p2) {
   415 		if (*p1 != *p2)
   416 			return *p1 - *p2;
   417 		p1++;
   418 		p2++;
   419 		if (isdigit(*p1) && isdigit(*p2))
   420 			return versioncmp(p1, p2);
   421 	}
   422 
   423 	return *p1 - *p2;
   424 }
   425 
   426 static int
   427 compare_packages(const void *p1, const void *p2, void *data)
   428 {
   429 	const struct razor_package *pkg1 = p1, *pkg2 = p2;
   430 	struct razor_set *set = data;
   431 	char *pool = set->string_pool.data;
   432 
   433 	/* FIXME: what if the flags are different? */
   434 	if (pkg1->name == pkg2->name)
   435 		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
   436 	else
   437 		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
   438 }
   439 
   440 static int
   441 compare_properties(const void *p1, const void *p2, void *data)
   442 {
   443 	const struct razor_property *prop1 = p1, *prop2 = p2;
   444 	struct razor_set *set = data;
   445 	char *pool = set->string_pool.data;
   446 
   447 	if (prop1->name != prop2->name) 
   448 		return strcmp(&pool[prop1->name], &pool[prop2->name]);
   449 	else if (prop1->type != prop2->type)
   450 		return prop1->type - prop2->type;
   451 	else if (prop1->relation != prop2->relation)
   452 		return prop1->relation - prop2->relation;
   453 	else
   454 		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
   455 }
   456 
   457 static uint32_t *
   458 uniqueify_properties(struct razor_set *set)
   459 {
   460 	struct razor_property *rp, *up, *rp_end;
   461 	struct array *pkgs, *p;
   462 	struct list_head *r;
   463 	uint32_t *map, *rmap;
   464 	int i, count, unique;
   465 
   466 	count = set->properties.size / sizeof(struct razor_property);
   467 	map = razor_qsort_with_data(set->properties.data,
   468 				    count,
   469 				    sizeof(struct razor_property),
   470 				    compare_properties,
   471 				    set);
   472 
   473 	rp_end = set->properties.data + set->properties.size;
   474 	rmap = malloc(count * sizeof *map);
   475 	pkgs = zalloc(count * sizeof *pkgs);
   476 	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
   477 		if (rp->name != up->name || rp->type != up->type ||
   478 		    rp->relation != up->relation || rp->version != up->version) {
   479 			up++;
   480 			up->name = rp->name;
   481 			up->flags = 0;
   482 			up->type = rp->type;
   483 			up->relation = rp->relation;
   484 			up->version = rp->version;
   485 		}
   486 
   487 		unique = up - (struct razor_property *) set->properties.data;
   488 		rmap[map[i]] = unique;
   489 		r = array_add(&pkgs[unique], sizeof *r);
   490 		*r = rp->packages;
   491 	}
   492 	free(map);
   493 
   494 	if (up != rp)
   495 		up++;
   496 	set->properties.size = (void *) up - set->properties.data;
   497 	rp_end = up;
   498 	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
   499 		list_set_array(&rp->packages, &set->package_pool, p, 0);
   500 		array_release(p);
   501 	}
   502 
   503 	free(pkgs);
   504 
   505 	return rmap;
   506 }
   507 
   508 static int
   509 compare_filenames(const void *p1, const void *p2, void *data)
   510 {
   511 	const struct import_entry *e1 = p1;
   512 	const struct import_entry *e2 = p2;
   513 	const char *n1 = e1->name;
   514 	const char *n2 = e2->name;
   515 
   516 	/* Need to make sure that the contents of a directory
   517 	 * are sorted immediately after it. So "foo/bar" has to
   518 	 * sort before "foo.conf"
   519 	 *
   520 	 * FIXME: this is about 60% slower than strcmp
   521 	 */
   522 	while (*n1 && *n2) {
   523 		if (*n1 < *n2)
   524 			return *n2 == '/' ? 1 : -1;
   525 		else if (*n1 > *n2)
   526 			return *n1 == '/' ? -1 : 1;
   527 		n1++;
   528 		n2++;
   529 	}
   530 	if (*n1)
   531 		return 1;
   532 	else if (*n2)
   533 		return -1;
   534 	else
   535 		return 0;
   536 }
   537 
   538 static void
   539 count_entries(struct import_directory *d)
   540 {
   541 	struct import_directory *p, *end;
   542 
   543 	p = d->files.data;
   544 	end = d->files.data + d->files.size;
   545 	d->count = 0;
   546 	while (p < end) {
   547 		count_entries(p);
   548 		d->count += p->count + 1;
   549 		p++;
   550 	}		
   551 }
   552 
   553 static void
   554 serialize_files(struct razor_set *set,
   555 		struct import_directory *d, struct array *array)
   556 {
   557 	struct import_directory *p, *end;
   558 	struct razor_entry *e = NULL;
   559 	uint32_t s;
   560 
   561 	p = d->files.data;
   562 	end = d->files.data + d->files.size;
   563 	s = array->size / sizeof *e + d->files.size / sizeof *p;
   564 	while (p < end) {
   565 		e = array_add(array, sizeof *e);
   566 		e->name = p->name;
   567 		e->flags = 0;
   568 		e->start = p->count > 0 ? s : 0;
   569 		s += p->count;
   570 
   571 		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
   572 		array_release(&p->packages);
   573 		p++;
   574 	}		
   575 	if (e != NULL)
   576 		e->flags |= RAZOR_ENTRY_LAST;
   577 
   578 	p = d->files.data;
   579 	end = d->files.data + d->files.size;
   580 	while (p < end) {
   581 		serialize_files(set, p, array);
   582 		p++;
   583 	}
   584 }
   585 
   586 static void
   587 remap_property_package_links(struct array *properties, uint32_t *rmap)
   588 {
   589 	struct razor_property *p, *end;
   590 
   591 	end = properties->data + properties->size;
   592 	for (p = properties->data; p < end; p++)
   593 		list_remap_head(&p->packages, rmap);
   594 }
   595 
   596 static void
   597 build_file_tree(struct razor_importer *importer)
   598 {
   599 	int count, i, length;
   600 	struct import_entry *filenames;
   601 	char *f, *end;
   602 	uint32_t name, *r;
   603 	char dirname[256];
   604 	struct import_directory *d, root;
   605 	struct razor_entry *e;
   606 
   607 	count = importer->files.size / sizeof (struct import_entry);
   608 	razor_qsort_with_data(importer->files.data,
   609 			      count,
   610 			      sizeof (struct import_entry),
   611 			      compare_filenames,
   612 			      NULL);
   613 
   614 	root.name = hashtable_tokenize(&importer->table, "");
   615 	array_init(&root.files);
   616 	array_init(&root.packages);
   617 	root.last = NULL;
   618 
   619 	filenames = importer->files.data;
   620 	for (i = 0; i < count; i++) {
   621 		f = filenames[i].name;
   622 		if (*f != '/')
   623 			continue;
   624 		f++;
   625 
   626 		d = &root;
   627 		while (*f) {
   628 			end = strchr(f, '/');
   629 			if (end == NULL)
   630 				end = f + strlen(f);
   631 			length = end - f;
   632 			memcpy(dirname, f, length);
   633 			dirname[length] ='\0';
   634 			name = hashtable_tokenize(&importer->table, dirname);
   635 			if (d->last == NULL || d->last->name != name) {
   636 				d->last = array_add(&d->files, sizeof *d);
   637 				d->last->name = name;
   638 				d->last->last = NULL;
   639 				array_init(&d->last->files);
   640 				array_init(&d->last->packages);
   641 			}
   642 			d = d->last;				
   643 			f = end + 1;
   644 			if (*end == '\0')
   645 				break;
   646 		}
   647 
   648 		r = array_add(&d->packages, sizeof *r);
   649 		*r = filenames[i].package;
   650 		free(filenames[i].name);
   651 	}
   652 
   653 	count_entries(&root);
   654 	e = importer->set->files.data;
   655 	e->name = root.name;
   656 	e->flags = RAZOR_ENTRY_LAST;
   657 	e->start = importer->files.size ? 1 : 0;
   658 	list_set_empty(&e->packages);
   659 
   660 	serialize_files(importer->set, &root, &importer->set->files);
   661 
   662 	array_release(&importer->files);
   663 }
   664 
   665 static struct razor_entry *
   666 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
   667 
   668 static void
   669 list_to_array(struct list *list, struct array *array)
   670 {
   671 	uint32_t *item;
   672 
   673 	while (list) {
   674 		 item = array_add(array, sizeof *item);
   675 		 *item = list->data;
   676 		 list = list_next(list);
   677 	}
   678 }
   679 
   680 static int
   681 compare_file_requires(const void *p1, const void *p2, void *data)
   682 {
   683 	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
   684 	const char *pool = data;
   685 
   686 	return strcmp(&pool[*f1], &pool[*f2]);
   687 }
   688 
   689 static void
   690 find_file_provides(struct razor_importer *importer)
   691 {
   692 	struct razor_property *prop;
   693 	struct razor_entry *top, *entry;
   694 	struct razor_package *packages;
   695 	struct array pkgprops;
   696 	struct list *pkg;
   697 	uint32_t *req, *req_start, *req_end;
   698 	uint32_t *map, *newprop;
   699 	char *pool;
   700 
   701 	pool = importer->set->string_pool.data;
   702 	packages = importer->set->packages.data;
   703 	top = importer->set->files.data;
   704 
   705 	req = req_start = importer->file_requires.data;
   706 	req_end = importer->file_requires.data + importer->file_requires.size;
   707 	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
   708 				    compare_file_requires, pool);
   709 	free(map);
   710 
   711 	for (req = req_start; req < req_end; req++) {
   712 		if (req > req_start && req[0] == req[-1])
   713 			continue;
   714 		entry = find_entry(importer->set, top, &pool[*req]);
   715 		if (!entry)
   716 			continue;
   717 
   718 		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
   719 			prop = array_add(&importer->set->properties, sizeof *prop);
   720 			prop->name = *req;
   721 			prop->type = RAZOR_PROPERTY_PROVIDES;
   722 			prop->relation = RAZOR_VERSION_EQUAL;
   723 			prop->version = hashtable_tokenize(&importer->table, "");
   724 			list_set_ptr(&prop->packages, pkg->data);
   725 
   726 			/* Update property list of pkg */
   727 			array_init(&pkgprops);
   728 			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
   729 			newprop = array_add(&pkgprops, sizeof *newprop);
   730 			*newprop = prop - (struct razor_property *)importer->set->properties.data;
   731 			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
   732 			array_release(&pkgprops);
   733 		}
   734 	}
   735 
   736 	array_release(&importer->file_requires);
   737 }
   738 
   739 static void
   740 build_package_file_lists(struct razor_set *set, uint32_t *rmap)
   741 {
   742 	struct razor_package *p, *packages;
   743 	struct array *pkgs;
   744 	struct razor_entry *e, *end;
   745 	struct list *r;
   746 	uint32_t *q;
   747 	int i, count;
   748 
   749 	count = set->packages.size / sizeof *p;
   750 	pkgs = zalloc(count * sizeof *pkgs);
   751 
   752 	end = set->files.data + set->files.size;
   753 	for (e = set->files.data; e < end; e++) {
   754 		list_remap_head(&e->packages, rmap);
   755 		r = list_first(&e->packages, &set->package_pool);
   756 		while (r) {
   757 			q = array_add(&pkgs[r->data], sizeof *q);
   758 			*q = e - (struct razor_entry *) set->files.data;
   759 			r = list_next(r);
   760 		}
   761 	}
   762 
   763 	packages = set->packages.data;
   764 	for (i = 0; i < count; i++) {
   765 		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
   766 		array_release(&pkgs[i]);
   767 	}
   768 	free(pkgs);
   769 }
   770 
   771 struct razor_set *
   772 razor_importer_finish(struct razor_importer *importer)
   773 {
   774 	struct razor_set *set;
   775 	uint32_t *map, *rmap;
   776 	int i, count;
   777 
   778 	build_file_tree(importer);
   779 	find_file_provides(importer);
   780 
   781 	map = uniqueify_properties(importer->set);
   782 	list_remap_pool(&importer->set->property_pool, map);
   783 	free(map);
   784 
   785 	count = importer->set->packages.size / sizeof(struct razor_package);
   786 	map = razor_qsort_with_data(importer->set->packages.data,
   787 				    count,
   788 				    sizeof(struct razor_package),
   789 				    compare_packages,
   790 				    importer->set);
   791 
   792 	rmap = malloc(count * sizeof *rmap);
   793 	for (i = 0; i < count; i++)
   794 		rmap[map[i]] = i;
   795 	free(map);
   796 
   797 	list_remap_pool(&importer->set->package_pool, rmap);
   798 	build_package_file_lists(importer->set, rmap);
   799 	remap_property_package_links(&importer->set->properties, rmap);
   800 	free(rmap);
   801 
   802 	set = importer->set;
   803 	hashtable_release(&importer->table);
   804 	free(importer);
   805 
   806 	return set;
   807 }
   808 
   809 struct razor_package_iterator {
   810 	struct razor_set *set;
   811 	struct razor_package *package, *end;
   812 	struct list *index;
   813 	int free_index;
   814 };
   815 
   816 static struct razor_package_iterator *
   817 razor_package_iterator_create_with_index(struct razor_set *set,
   818 					 struct list *index)
   819 {
   820 	struct razor_package_iterator *pi;
   821 
   822 	pi = zalloc(sizeof *pi);
   823 	pi->set = set;
   824 	pi->index = index;
   825 
   826 	return pi;
   827 }
   828 
   829 struct razor_package_iterator *
   830 razor_package_iterator_create(struct razor_set *set)
   831 {
   832 	struct razor_package_iterator *pi;
   833 
   834 	pi = zalloc(sizeof *pi);
   835 	pi->set = set;
   836 	pi->end = set->packages.data + set->packages.size;
   837 	pi->package = set->packages.data;
   838 
   839 	return pi;
   840 }
   841 
   842 static void
   843 razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
   844 					 struct razor_set *set,
   845 					 struct razor_property *property)
   846 {
   847 	memset(pi, 0, sizeof *pi);
   848 	pi->set = set;
   849 	pi->index = list_first(&property->packages, &set->package_pool);
   850 }
   851 
   852 struct razor_package_iterator *
   853 razor_package_iterator_create_for_property(struct razor_set *set,
   854 					   struct razor_property *property)
   855 {
   856 	struct list *index;
   857 
   858 	index = list_first(&property->packages, &set->package_pool);
   859 	return razor_package_iterator_create_with_index(set, index);
   860 }
   861 
   862 int
   863 razor_package_iterator_next(struct razor_package_iterator *pi,
   864 			    struct razor_package **package,
   865 			    const char **name,
   866 			    const char **version,
   867 			    const char **arch)
   868 {
   869 	char *pool;
   870 	int valid;
   871 	struct razor_package *p, *packages;
   872 
   873 	if (pi->package) {
   874 		p = pi->package++;
   875 		valid = p < pi->end;
   876 	} else if (pi->index) {
   877 		packages = pi->set->packages.data;
   878 		p = &packages[pi->index->data];
   879 		pi->index = list_next(pi->index);
   880 		valid = 1;
   881 	} else
   882 		valid = 0;
   883 
   884 	if (valid) {
   885 		pool = pi->set->string_pool.data;
   886 		*package = p;
   887 		*name = &pool[p->name];
   888 		*version = &pool[p->version];
   889 		*arch = &pool[p->arch];
   890 	} else {
   891 		*package = NULL;
   892 	}
   893 
   894 	return valid;
   895 }
   896 
   897 void
   898 razor_package_iterator_destroy(struct razor_package_iterator *pi)
   899 {
   900 	if (pi->free_index)
   901 		free(pi->index);
   902 
   903 	free(pi);
   904 }
   905 
   906 struct razor_package *
   907 razor_set_get_package(struct razor_set *set, const char *package)
   908 {
   909 	struct razor_package_iterator *pi;
   910 	struct razor_package *p;
   911 	const char *name, *version, *arch;
   912 
   913 	pi = razor_package_iterator_create(set);
   914 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
   915 		if (strcmp(package, name) == 0)
   916 			break;
   917 	}
   918 	razor_package_iterator_destroy(pi);
   919 
   920 	return p;
   921 }
   922 
   923 struct razor_property_iterator {
   924 	struct razor_set *set;
   925 	struct razor_property *property, *end;
   926 	struct list *index;
   927 };
   928 
   929 struct razor_property_iterator *
   930 razor_property_iterator_create(struct razor_set *set,
   931 			       struct razor_package *package)
   932 {
   933 	struct razor_property_iterator *pi;
   934 
   935 	pi = zalloc(sizeof *pi);
   936 	pi->set = set;
   937 
   938 	if (package) {
   939 		pi->index = list_first(&package->properties,
   940 				       &set->property_pool);
   941 	} else {
   942 		pi->property = set->properties.data;
   943 		pi->end = set->properties.data + set->properties.size;
   944 	}
   945 
   946 	return pi;
   947 }
   948 
   949 int
   950 razor_property_iterator_next(struct razor_property_iterator *pi,
   951 			     struct razor_property **property,
   952 			     const char **name,
   953 			     enum razor_version_relation *relation,
   954 			     const char **version,
   955 			     enum razor_property_type *type)
   956 {
   957 	char *pool;
   958 	int valid;
   959 	struct razor_property *p, *properties;
   960 
   961 	if (pi->property) {
   962 		p = pi->property++;
   963 		valid = p < pi->end;
   964 	} else if (pi->index) {
   965 		properties = pi->set->properties.data;
   966 		p = &properties[pi->index->data];
   967 		pi->index = list_next(pi->index);
   968 		valid = 1;
   969 	} else
   970 		valid = 0;
   971 
   972 	if (valid) {
   973 		pool = pi->set->string_pool.data;
   974 		*property = p;
   975 		*name = &pool[p->name];
   976 		*relation = p->relation;
   977 		*version = &pool[p->version];
   978 		*type = p->type;
   979 	} else {
   980 		*property = NULL;
   981 	}
   982 
   983 	return valid;
   984 }
   985 
   986 void
   987 razor_property_iterator_destroy(struct razor_property_iterator *pi)
   988 {
   989 	free(pi);
   990 }
   991 
   992 static struct razor_entry *
   993 find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
   994 {
   995 	struct razor_entry *e;
   996 	const char *n, *pool = set->string_pool.data;
   997 	int len;
   998 
   999 	e = (struct razor_entry *) set->files.data + dir->start;
  1000 	do {
  1001 		n = pool + e->name;
  1002 		if (strcmp(pattern + 1, n) == 0)
  1003 			return e;
  1004 		len = strlen(n);
  1005 		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
  1006 		    pattern[len + 1] == '/') {
  1007 			return find_entry(set, e, pattern + len + 1);
  1008 		}
  1009 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1010 
  1011 	return NULL;
  1012 }
  1013 
  1014 static void
  1015 list_dir(struct razor_set *set, struct razor_entry *dir,
  1016 	 char *prefix, const char *pattern)
  1017 {
  1018 	struct razor_entry *e;
  1019 	const char *n, *pool = set->string_pool.data;
  1020 
  1021 	e = (struct razor_entry *) set->files.data + dir->start;
  1022 	do {
  1023 		n = pool + e->name;
  1024 		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
  1025 			continue;
  1026 		printf("%s/%s\n", prefix, n);
  1027 		if (e->start) {
  1028 			char *sub = prefix + strlen (prefix);
  1029 			*sub = '/';
  1030 			strcpy (sub + 1, n);
  1031 			list_dir(set, e, prefix, pattern);
  1032 			*sub = '\0';
  1033 		}
  1034 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1035 }
  1036 
  1037 void
  1038 razor_set_list_files(struct razor_set *set, const char *pattern)
  1039 {
  1040 	struct razor_entry *e;
  1041 	char buffer[512], *p, *base;
  1042 
  1043 	if (pattern == NULL || !strcmp (pattern, "/")) {
  1044 		buffer[0] = '\0';
  1045 		list_dir(set, set->files.data, buffer, NULL);
  1046 		return;
  1047 	}
  1048 
  1049 	strcpy(buffer, pattern);
  1050 	e = find_entry(set, set->files.data, buffer);
  1051 	if (e && e->start > 0) {
  1052 		base = NULL;
  1053 	} else {
  1054 		p = strrchr(buffer, '/');
  1055 		if (p) {
  1056 			*p = '\0';
  1057 			base = p + 1;
  1058 		} else {
  1059 			base = NULL;
  1060 		}
  1061 	}
  1062 	e = find_entry(set, set->files.data, buffer);
  1063 	if (e->start != 0)
  1064 		list_dir(set, e, buffer, base);
  1065 }
  1066 
  1067 struct razor_package_iterator *
  1068 razor_package_iterator_create_for_file(struct razor_set *set,
  1069 				       const char *filename)
  1070 {
  1071 	struct razor_entry *entry;
  1072 	struct list *index;
  1073 
  1074 	entry = find_entry(set, set->files.data, filename);
  1075 	if (entry == NULL)
  1076 		return NULL;
  1077 	
  1078 	index = list_first(&entry->packages, &set->package_pool);
  1079 	return razor_package_iterator_create_with_index(set, index);
  1080 }
  1081 
  1082 static struct list *
  1083 list_package_files(struct razor_set *set, struct list *r,
  1084 		   struct razor_entry *dir, uint32_t end,
  1085 		   char *prefix)
  1086 {
  1087 	struct razor_entry *e, *f, *entries;
  1088 	uint32_t next, file;
  1089 	char *pool;
  1090 	int len;
  1091 	
  1092 	entries = (struct razor_entry *) set->files.data;
  1093 	pool = set->string_pool.data;
  1094 
  1095 	e = entries + dir->start;
  1096 	do {
  1097 		if (entries + r->data == e) {
  1098 			printf("%s/%s\n", prefix, pool + e->name);
  1099 			r = list_next(r);
  1100 			if (!r)
  1101 				return NULL;
  1102 			if (r->data >= end)
  1103 				return r;
  1104 		}
  1105 	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  1106 
  1107 	e = entries + dir->start;
  1108 	do {
  1109 		if (e->start == 0)
  1110 			continue;
  1111 
  1112 		if (e->flags & RAZOR_ENTRY_LAST)
  1113 			next = end;
  1114 		else {
  1115 			f = e + 1; 
  1116 			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
  1117 				f++;
  1118 			if (f->start == 0)
  1119 				next = end;
  1120 			else
  1121 				next = f->start;
  1122 		}
  1123 
  1124 		file = r->data;
  1125 		if (e->start <= file && file < next) {
  1126 			len = strlen(prefix);
  1127 			prefix[len] = '/';
  1128 			strcpy(prefix + len + 1, pool + e->name);
  1129 			r = list_package_files(set, r, e, next, prefix);
  1130 			prefix[len] = '\0';
  1131 		}
  1132 	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
  1133 
  1134 	return r;
  1135 }
  1136 
  1137 void
  1138 razor_set_list_package_files(struct razor_set *set, const char *name)
  1139 {
  1140 	struct razor_package *package;
  1141 	struct list *r;
  1142 	uint32_t end;
  1143 	char buffer[512];
  1144 
  1145 	package = razor_set_get_package(set, name);
  1146 
  1147 	r = list_first(&package->files, &set->file_pool);
  1148 	end = set->files.size / sizeof (struct razor_entry);
  1149 	buffer[0] = '\0';
  1150 	list_package_files(set, r, set->files.data, end, buffer);
  1151 }
  1152 
  1153 #define UPSTREAM_SOURCE 0x80
  1154 
  1155 struct source {
  1156 	struct razor_set *set;
  1157 	uint32_t *property_map;
  1158 	uint32_t *file_map;
  1159 };
  1160 
  1161 struct razor_merger {
  1162 	struct razor_set *set;
  1163 	struct hashtable table;
  1164 	struct source source1;
  1165 	struct source source2;
  1166 };
  1167 
  1168 static struct razor_merger *
  1169 razor_merger_create(struct razor_set *set1, struct razor_set *set2)
  1170 {
  1171 	struct razor_merger *merger;
  1172 	int count;
  1173 	size_t size;
  1174 
  1175 	merger = zalloc(sizeof *merger);
  1176 	merger->set = razor_set_create();
  1177 	hashtable_init(&merger->table, &merger->set->string_pool);
  1178 
  1179 	merger->source1.set = set1;
  1180 	count = set1->properties.size / sizeof (struct razor_property);
  1181 	size = count * sizeof merger->source1.property_map[0];
  1182 	merger->source1.property_map = zalloc(size);
  1183 	count = set1->files.size / sizeof (struct razor_entry);
  1184 	size = count * sizeof merger->source1.file_map[0];
  1185 	merger->source1.file_map = zalloc(size);
  1186 
  1187 	merger->source2.set = set2;
  1188 	count = set2->properties.size / sizeof (struct razor_property);
  1189 	size = count * sizeof merger->source2.property_map[0];
  1190 	merger->source2.property_map = zalloc(size);
  1191 	count = set2->files.size / sizeof (struct razor_entry);
  1192 	size = count * sizeof merger->source2.file_map[0];
  1193 	merger->source2.file_map = zalloc(size);
  1194 
  1195 	return merger;
  1196 }
  1197 
  1198 static void
  1199 razor_merger_add_package(struct razor_merger *merger,
  1200 			 struct razor_package *package)
  1201 {
  1202 	char *pool;
  1203 	struct list *r;
  1204 	struct razor_package *p;
  1205 	struct razor_set *set1;
  1206 	struct source *source;
  1207 	uint32_t flags;
  1208 
  1209 	set1 = merger->source1.set;
  1210 	if (set1->packages.data <= (void *) package &&
  1211 	    (void *) package < set1->packages.data + set1->packages.size) {
  1212 		source = &merger->source1;
  1213 		flags = 0;
  1214 	} else {
  1215 		source = &merger->source2;
  1216 		flags = UPSTREAM_SOURCE;
  1217 	}
  1218 
  1219 	pool = source->set->string_pool.data;
  1220 	p = array_add(&merger->set->packages, sizeof *p);
  1221 	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
  1222 	p->flags = flags;
  1223 	p->version = hashtable_tokenize(&merger->table,
  1224 					&pool[package->version]);
  1225 	p->arch = hashtable_tokenize(&merger->table,
  1226 				     &pool[package->arch]);
  1227 
  1228 	p->properties = package->properties;
  1229 	r = list_first(&package->properties, &source->set->property_pool);
  1230 	while (r) {
  1231 		source->property_map[r->data] = 1;
  1232 		r = list_next(r);
  1233 	}
  1234 
  1235 	p->files = package->files;
  1236 	r = list_first(&package->files, &source->set->file_pool);
  1237 	while (r) {
  1238 		source->file_map[r->data] = 1;
  1239 		r = list_next(r);
  1240 	}
  1241 }
  1242 
  1243 static uint32_t
  1244 add_property(struct razor_merger *merger,
  1245 	     const char *name, enum razor_version_relation relation,
  1246 	     const char *version, int type)
  1247 {
  1248 	struct razor_property *p;
  1249 
  1250 	p = array_add(&merger->set->properties, sizeof *p);
  1251 	p->name = hashtable_tokenize(&merger->table, name);
  1252 	p->flags = 0;
  1253 	p->type = type;
  1254 	p->relation = relation;
  1255 	p->version = hashtable_tokenize(&merger->table, version);
  1256 
  1257 	return p - (struct razor_property *) merger->set->properties.data;
  1258 }
  1259 
  1260 static void
  1261 merge_properties(struct razor_merger *merger)
  1262 {
  1263 	struct razor_property *p1, *p2;
  1264 	struct razor_set *set1, *set2;
  1265 	uint32_t *map1, *map2;
  1266 	int i, j, cmp, count1, count2;
  1267 	char *pool1, *pool2;
  1268 
  1269 	set1 = merger->source1.set;
  1270 	set2 = merger->source2.set;
  1271 	map1 = merger->source1.property_map;
  1272 	map2 = merger->source2.property_map;
  1273 
  1274 	i = 0;
  1275 	j = 0;
  1276 	pool1 = set1->string_pool.data;
  1277 	pool2 = set2->string_pool.data;
  1278 
  1279 	count1 = set1->properties.size / sizeof *p1;
  1280 	count2 = set2->properties.size / sizeof *p2;
  1281 	while (i < count1 || j < count2) {
  1282 		if (i < count1 && map1[i] == 0) {
  1283 			i++;
  1284 			continue;
  1285 		}
  1286 		if (j < count2 && map2[j] == 0) {
  1287 			j++;
  1288 			continue;
  1289 		}
  1290 		p1 = (struct razor_property *) set1->properties.data + i;
  1291 		p2 = (struct razor_property *) set2->properties.data + j;
  1292 		if (i < count1 && j < count2)
  1293 			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
  1294 		else if (i < count1)
  1295 			cmp = -1;
  1296 		else
  1297 			cmp = 1;
  1298 		if (cmp == 0)
  1299 			cmp = p1->type - p2->type;
  1300 		if (cmp == 0)
  1301 			cmp = p1->relation - p2->relation;
  1302 		if (cmp == 0)
  1303 			cmp = versioncmp(&pool1[p1->version],
  1304 					 &pool2[p2->version]);
  1305 		if (cmp < 0) {
  1306 			map1[i++] = add_property(merger,
  1307 						 &pool1[p1->name],
  1308 						 p1->relation,
  1309 						 &pool1[p1->version],
  1310 						 p1->type);
  1311 		} else if (cmp > 0) {
  1312 			map2[j++] = add_property(merger,
  1313 						 &pool2[p2->name],
  1314 						 p2->relation,
  1315 						 &pool2[p2->version],
  1316 						 p2->type);
  1317 		} else  {
  1318 			map1[i++] = map2[j++] = add_property(merger,
  1319 							     &pool1[p1->name],
  1320 							     p1->relation,
  1321 							     &pool1[p1->version],
  1322 							     p1->type);
  1323 		}
  1324 	}
  1325 }
  1326 
  1327 static void
  1328 emit_properties(struct list_head *properties, struct array *source_pool,
  1329 		uint32_t *map, struct array *pool)
  1330 {
  1331 	uint32_t r;
  1332 	struct list *p, *q;
  1333 
  1334 	r = pool->size / sizeof *q;
  1335 	p = list_first(properties, source_pool);
  1336 	while (p) {
  1337 		q = array_add(pool, sizeof *q);
  1338 		q->data = map[p->data];
  1339 		q->flags = p->flags;
  1340 		p = list_next(p);
  1341 	}
  1342 
  1343 	list_set_ptr(properties, r);
  1344 }
  1345 
  1346 static uint32_t
  1347 add_file(struct razor_merger *merger, const char *name)
  1348 {
  1349 	struct razor_entry *e;
  1350 
  1351 	e = array_add(&merger->set->files, sizeof *e);
  1352 	e->name = hashtable_tokenize(&merger->table, name);
  1353 	e->flags = 0;
  1354 	e->start = 0;
  1355 
  1356 	return e - (struct razor_entry *)merger->set->files.data;
  1357 }
  1358 
  1359 /* FIXME. Blah */
  1360 static int
  1361 fix_file_map(uint32_t *map,
  1362 	     struct razor_entry *files,
  1363 	     struct razor_entry *top)
  1364 {
  1365 	uint32_t e;
  1366 	int found_file = 0;
  1367 
  1368 	e = top->start;
  1369 	do {
  1370 		if (files[e].start)
  1371 			fix_file_map(map, files, &files[e]);
  1372 		if (map[e])
  1373 			found_file = 1;
  1374 	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
  1375 
  1376 	if (found_file)
  1377 		map[top - files] = 1;
  1378 	return found_file;
  1379 }
  1380 
  1381 struct merge_directory {
  1382 	uint32_t merged, dir1, dir2;
  1383 };
  1384 
  1385 static void
  1386 merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
  1387 {
  1388 	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
  1389 	struct razor_set *set1, *set2;
  1390 	struct array merge_stack;
  1391 	struct merge_directory *child_md, *end_md;
  1392 	uint32_t *map1, *map2, start, last;
  1393 	int cmp;
  1394 	char *pool1, *pool2;
  1395 
  1396 	set1 = merger->source1.set;
  1397 	set2 = merger->source2.set;
  1398 	map1 = merger->source1.file_map;
  1399 	map2 = merger->source2.file_map;
  1400 	pool1 = set1->string_pool.data;
  1401 	pool2 = set2->string_pool.data;
  1402 	root1 = (struct razor_entry *) set1->files.data;
  1403 	root2 = (struct razor_entry *) set2->files.data;
  1404 
  1405 	array_init(&merge_stack);
  1406 
  1407 	start = merger->set->files.size / sizeof (struct razor_entry);
  1408 	last = 0;
  1409 	e1 = md->dir1 ? root1 + md->dir1 : NULL;
  1410 	e2 = md->dir2 ? root2 + md->dir2 : NULL;
  1411 	while (e1 || e2) {
  1412 		if (!e2 && !map1[e1 - root1]) {
  1413 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1414 				e1 = NULL;
  1415 			continue;
  1416 		}
  1417 		if (!e1 && !map2[e2 - root2]) {
  1418 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1419 				e2 = NULL;
  1420 			continue;
  1421 		}
  1422 		if (e1 && !map1[e1 - root1] &&
  1423 		    e2 && !map1[e2 - root2]) {
  1424 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1425 				e1 = NULL;
  1426 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1427 				e2 = NULL;
  1428 			continue;
  1429 		}
  1430 
  1431 		if (!e1)
  1432 			cmp = 1;
  1433 		else if (!e2)
  1434 			cmp = -1;
  1435 		else {
  1436 			cmp = strcmp (&pool1[e1->name],
  1437 				      &pool2[e2->name]);
  1438 		}
  1439 
  1440 		if (cmp < 0) {
  1441 			if (map1[e1 - root1]) {
  1442 				map1[e1 - root1] = last =
  1443 					add_file(merger, &pool1[e1->name]);
  1444 				if (e1->start) {
  1445 					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1446 					child_md->merged = last;
  1447 					child_md->dir1 = e1->start;
  1448 					child_md->dir2 = 0;
  1449 				}
  1450 			}
  1451 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1452 				e1 = NULL;
  1453 		} else if (cmp > 0) {
  1454 			if (map2[e2 - root2]) {
  1455 				map2[e2 - root2] = last =
  1456 					add_file(merger, &pool2[e2->name]);
  1457 				if (e2->start) {
  1458 					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1459 					child_md->merged = last;
  1460 					child_md->dir1 = 0;
  1461 					child_md->dir2 = e2->start;
  1462 				}
  1463 			}
  1464 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1465 				e2 = NULL;
  1466 		} else {
  1467 			map1[e1 - root1] = map2[e2- root2] = last =
  1468 				add_file(merger, &pool1[e1->name]);
  1469 			if (e1->start || e2->start) {
  1470 				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  1471 				child_md->merged = last;
  1472 				child_md->dir1 = e1->start;
  1473 				child_md->dir2 = e2->start;
  1474 			}
  1475 			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  1476 				e1 = NULL;
  1477 			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  1478 				e2 = NULL;
  1479 		}
  1480 	}
  1481 
  1482 	mroot = (struct razor_entry *)merger->set->files.data;
  1483 	if (last) {
  1484 		mroot[last].flags = RAZOR_ENTRY_LAST;
  1485 		mroot[md->merged].start = start;
  1486 	} else
  1487 		mroot[md->merged].start = 0;
  1488 
  1489 	end_md = merge_stack.data + merge_stack.size;
  1490 	for (child_md = merge_stack.data; child_md < end_md; child_md++)
  1491 		merge_one_directory(merger, child_md);
  1492 	array_release(&merge_stack);
  1493 }
  1494 
  1495 static void
  1496 merge_files(struct razor_merger *merger)
  1497 {
  1498 	struct razor_entry *root;
  1499 	struct merge_directory md;
  1500 	uint32_t *map1, *map2;
  1501 
  1502 	map1 = merger->source1.file_map;
  1503 	map2 = merger->source2.file_map;
  1504 
  1505 	md.merged = 0;
  1506 
  1507 	if (merger->source1.set->files.size) {
  1508 		root = (struct razor_entry *) merger->source1.set->files.data;
  1509 		if (root->start)
  1510 			fix_file_map(map1, root, root);
  1511 		md.dir1 = root->start;
  1512 	} else
  1513 		md.dir1 = 0;
  1514 
  1515 	if (merger->source2.set->files.size) {
  1516 		root = (struct razor_entry *) merger->source2.set->files.data;
  1517 		if (root->start)
  1518 			fix_file_map(map2, root, root);
  1519 		md.dir2 = root->start;
  1520 	} else
  1521 		md.dir2 = 0;
  1522 
  1523 	merge_one_directory(merger, &md);
  1524 }
  1525 
  1526 static void
  1527 emit_files(struct list_head *files, struct array *source_pool,
  1528 	   uint32_t *map, struct array *pool)
  1529 {
  1530 	uint32_t r;
  1531 	struct list *p, *q;
  1532 
  1533 	r = pool->size / sizeof *q;
  1534 	p = list_first(files, source_pool);
  1535 	while (p) {
  1536 		q = array_add(pool, sizeof *q);
  1537 		q->data = map[p->data];
  1538 		q->flags = p->flags;
  1539 		p = list_next(p);
  1540 	}
  1541 
  1542 	list_set_ptr(files, r);
  1543 }
  1544 
  1545 /* Rebuild property->packages maps.  We can't just remap these, as a
  1546  * property may have lost or gained a number of packages.  Allocate an
  1547  * array per property and loop through the packages and add them to
  1548  * the arrays for their properties. */
  1549 static void
  1550 rebuild_property_package_lists(struct razor_set *set)
  1551 {
  1552 	struct array *pkgs, *a;
  1553 	struct razor_package *pkg, *pkg_end;
  1554 	struct razor_property *prop, *prop_end;
  1555 	struct list *r;
  1556 	uint32_t *q;
  1557 	int count;
  1558 
  1559 	count = set->properties.size / sizeof (struct razor_property);
  1560 	pkgs = zalloc(count * sizeof *pkgs);
  1561 	pkg_end = set->packages.data + set->packages.size;
  1562 
  1563 	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  1564 		r = list_first(&pkg->properties, &set->property_pool);
  1565 		while (r) {
  1566 			q = array_add(&pkgs[r->data], sizeof *q);
  1567 			*q = pkg - (struct razor_package *) set->packages.data;
  1568 			r = list_next(r);
  1569 		}
  1570 	}
  1571 
  1572 	prop_end = set->properties.data + set->properties.size;
  1573 	a = pkgs;
  1574 	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
  1575 		list_set_array(&prop->packages, &set->package_pool, a, 0);
  1576 		array_release(a);
  1577 	}
  1578 	free(pkgs);
  1579 }
  1580 
  1581 static void
  1582 rebuild_file_package_lists(struct razor_set *set)
  1583 {
  1584 	struct array *pkgs, *a;
  1585 	struct razor_package *pkg, *pkg_end;
  1586 	struct razor_entry *entry, *entry_end;
  1587 	struct list *r;
  1588 	uint32_t *q;
  1589 	int count;
  1590 
  1591 	count = set->files.size / sizeof (struct razor_entry);
  1592 	pkgs = zalloc(count * sizeof *pkgs);
  1593 	pkg_end = set->packages.data + set->packages.size;
  1594 
  1595 	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  1596 		r = list_first(&pkg->files, &set->file_pool);
  1597 		while (r) {
  1598 			q = array_add(&pkgs[r->data], sizeof *q);
  1599 			*q = pkg - (struct razor_package *) set->packages.data;
  1600 			r = list_next(r);
  1601 		}
  1602 	}
  1603 
  1604 	entry_end = set->files.data + set->files.size;
  1605 	a = pkgs;
  1606 	for (entry = set->files.data; entry < entry_end; entry++, a++) {
  1607 		list_set_array(&entry->packages, &set->package_pool, a, 0);
  1608 		array_release(a);
  1609 	}
  1610 	free(pkgs);
  1611 }
  1612 
  1613 static struct razor_set *
  1614 razor_merger_finish(struct razor_merger *merger)
  1615 {
  1616 	struct razor_set *result;
  1617 	struct razor_package *p, *pend;
  1618 
  1619 	/* As we built the package list, we filled out a bitvector of
  1620 	 * the properties that are referenced by the packages in the
  1621 	 * new set.  Now we do a parallel loop through the properties
  1622 	 * and emit those marked in the bit vector to the new set.  In
  1623 	 * the process, we update the bit vector to actually map from
  1624 	 * indices in the old property list to indices in the new
  1625 	 * property list for both sets. */
  1626 
  1627 	merge_properties(merger);
  1628 	merge_files(merger);
  1629 
  1630 	/* Now we loop through the packages again and emit the
  1631 	 * property lists, remapped to point to the new properties. */
  1632 
  1633 	pend = merger->set->packages.data + merger->set->packages.size;
  1634 	for (p = merger->set->packages.data; p < pend; p++) {
  1635 		struct source *src;
  1636 
  1637 		if (p->flags & UPSTREAM_SOURCE)
  1638 			src = &merger->source2;
  1639 		else
  1640 			src = &merger->source1;
  1641 
  1642 		emit_properties(&p->properties,
  1643 				&src->set->property_pool,
  1644 				src->property_map,
  1645 				&merger->set->property_pool);
  1646 		emit_files(&p->files,
  1647 			   &src->set->file_pool,
  1648 			   src->file_map,
  1649 			   &merger->set->file_pool);
  1650 		p->flags &= ~UPSTREAM_SOURCE;
  1651 	}
  1652 
  1653 	rebuild_property_package_lists(merger->set);
  1654 	rebuild_file_package_lists(merger->set);
  1655 
  1656 	result = merger->set;
  1657 	hashtable_release(&merger->table);
  1658 	free(merger);
  1659 
  1660 	return result;
  1661 }
  1662 
  1663 /* The diff order matters.  We should sort the packages so that a
  1664  * REMOVE of a package comes before the INSTALL, and so that all
  1665  * requires for a package have been installed before the package.
  1666  **/
  1667 
  1668 void
  1669 razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  1670 	       razor_package_callback_t callback, void *data)
  1671 {
  1672  	struct razor_package_iterator *pi1, *pi2;
  1673  	struct razor_package *p1, *p2;
  1674 	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
  1675 	int res;
  1676 
  1677 	pi1 = razor_package_iterator_create(set);
  1678 	pi2 = razor_package_iterator_create(upstream);
  1679 
  1680 	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
  1681 	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
  1682 
  1683 	while (p1 || p2) {
  1684 		if (p1 && p2) {
  1685 			res = strcmp(name1, name2);
  1686 			if (res == 0)
  1687 				res = versioncmp(version1, version2);
  1688 		} else {
  1689 			res = 0;
  1690 		}
  1691 
  1692 		if (p2 == NULL || res < 0)
  1693 			callback(name1, version1, NULL, arch1, data);
  1694 		else if (p1 == NULL || res > 0)
  1695 			callback(name2, NULL, version2, arch2, data);
  1696 
  1697 		if (p1 != NULL && res <= 0)
  1698 			razor_package_iterator_next(pi1, &p1,
  1699 						    &name1, &version1, &arch1);
  1700 		if (p2 != NULL && res >= 0)
  1701 			razor_package_iterator_next(pi2, &p2,
  1702 						    &name2, &version2, &arch2);
  1703 	}
  1704 
  1705 	razor_package_iterator_destroy(pi1);
  1706 	razor_package_iterator_destroy(pi2);
  1707 }
  1708 
  1709 static int
  1710 provider_satisfies_requirement(struct razor_property *provider,
  1711 			       const char *provider_strings,
  1712 			       enum razor_version_relation relation,
  1713 			       const char *required)
  1714 {
  1715 	int cmp, len;
  1716 	const char *provided = &provider_strings[provider->version];
  1717 
  1718 	if (!*required)
  1719 		return 1;
  1720 	if (!*provided) {
  1721 		if (relation >= RAZOR_VERSION_EQUAL)
  1722 			return 1;
  1723 		else
  1724 			return 0;
  1725 	}
  1726 
  1727 	cmp = versioncmp(provided, required);
  1728 
  1729 	switch (relation) {
  1730 	case RAZOR_VERSION_LESS:
  1731 		return cmp < 0;
  1732 
  1733 	case RAZOR_VERSION_LESS_OR_EQUAL:
  1734 		if (cmp <= 0)
  1735 			return 1;
  1736 		/* fall through: FIXME, make sure this is correct */
  1737 
  1738 	case RAZOR_VERSION_EQUAL:
  1739 		if (cmp == 0)
  1740 			return 1;
  1741 
  1742 		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
  1743 		len = strlen(required);
  1744 		if (!strncmp(required, provided, len) && provided[len] == '-')
  1745 			return 1;
  1746 		return 0;
  1747 
  1748 	case RAZOR_VERSION_GREATER_OR_EQUAL:
  1749 		return cmp >= 0;
  1750 
  1751 	case RAZOR_VERSION_GREATER:
  1752 		return cmp > 0;
  1753 	}
  1754 
  1755 	/* shouldn't happen */
  1756 	return 0;
  1757 }
  1758 
  1759 #define TRANS_PACKAGE_PRESENT		1
  1760 #define TRANS_PACKAGE_UPDATE		2
  1761 #define TRANS_PROPERTY_SATISFIED	0x80000000
  1762 
  1763 struct transaction_set {
  1764 	struct razor_set *set;
  1765 	uint32_t *packages;
  1766 	uint32_t *properties;
  1767 };
  1768 
  1769 struct razor_transaction {
  1770 	int package_count, errors;
  1771 	struct transaction_set system, upstream;
  1772 	int changes;
  1773 };
  1774 
  1775 static void
  1776 transaction_set_init(struct transaction_set *ts, struct razor_set *set)
  1777 {
  1778 	int count;
  1779 
  1780 	ts->set = set;
  1781 	count = set->packages.size / sizeof (struct razor_package);
  1782 	ts->packages = zalloc(count * sizeof *ts->packages);
  1783 	count = set->properties.size / sizeof (struct razor_property);
  1784 	ts->properties = zalloc(count * sizeof *ts->properties);
  1785 }
  1786 
  1787 static void
  1788 transaction_set_release(struct transaction_set *ts)
  1789 {
  1790 	free(ts->packages);
  1791 	free(ts->properties);
  1792 }
  1793 
  1794 static void
  1795 transaction_set_install_package(struct transaction_set *ts,
  1796 				struct razor_package *package)
  1797 {
  1798 	struct razor_package *pkgs;
  1799 	struct list *prop;
  1800 	int i;
  1801 
  1802 	pkgs = ts->set->packages.data;
  1803 	i = package - pkgs;
  1804 	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
  1805 		return;
  1806 
  1807 	ts->packages[i] = TRANS_PACKAGE_PRESENT;
  1808 
  1809 	prop = list_first(&package->properties, &ts->set->property_pool);
  1810 	while (prop) {
  1811 		ts->properties[prop->data]++;
  1812 		prop = list_next(prop);
  1813 	}
  1814 }
  1815 
  1816 static void
  1817 transaction_set_remove_package(struct transaction_set *ts,
  1818 			       struct razor_package *package)
  1819 {
  1820 	struct razor_package *pkgs;
  1821 	struct list *prop;
  1822 	int i;
  1823 
  1824 	pkgs = ts->set->packages.data;
  1825 	i = package - pkgs;
  1826 	if (ts->packages[i] == 0)
  1827 		return;
  1828 
  1829 	ts->packages[i] = 0;
  1830 
  1831 	prop = list_first(&package->properties, &ts->set->property_pool);
  1832 	while (prop) {
  1833 		ts->properties[prop->data]--;
  1834 		prop = list_next(prop);
  1835 	}
  1836 }
  1837 
  1838 struct razor_transaction *
  1839 razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  1840 {
  1841 	struct razor_transaction *trans;
  1842 	struct razor_package *p, *spkgs, *pend;
  1843 
  1844 	trans = zalloc(sizeof *trans);
  1845 	transaction_set_init(&trans->system, system);
  1846 	transaction_set_init(&trans->upstream, upstream);
  1847 
  1848 	spkgs = trans->system.set->packages.data;
  1849 	pend = trans->system.set->packages.data +
  1850 		trans->system.set->packages.size;
  1851 	for (p = spkgs; p < pend; p++)
  1852 		transaction_set_install_package(&trans->system, p);
  1853 
  1854 	return trans;
  1855 }
  1856 
  1857 void
  1858 razor_transaction_install_package(struct razor_transaction *trans,
  1859 				  struct razor_package *package)
  1860 {
  1861 	transaction_set_install_package(&trans->upstream, package);
  1862 	trans->changes++;
  1863 }
  1864 
  1865 void
  1866 razor_transaction_remove_package(struct razor_transaction *trans,
  1867 				 struct razor_package *package)
  1868 {
  1869 	transaction_set_remove_package(&trans->system, package);
  1870 	trans->changes++;
  1871 }
  1872 
  1873 void
  1874 razor_transaction_update_package(struct razor_transaction *trans,
  1875 				  struct razor_package *package)
  1876 {
  1877 	struct razor_package *spkgs;
  1878 
  1879 	spkgs = trans->system.set->packages.data;
  1880 	trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  1881 }
  1882 
  1883 struct prop_iter {
  1884 	struct razor_property *p, *start, *end;
  1885 	const char *pool;
  1886 	uint32_t *present;
  1887 };
  1888 
  1889 static void
  1890 prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  1891 {
  1892 	pi->p = ts->set->properties.data;
  1893 	pi->start = ts->set->properties.data;
  1894 	pi->end = ts->set->properties.data + ts->set->properties.size;
  1895 	pi->pool = ts->set->string_pool.data;
  1896 	pi->present = ts->properties;
  1897 }
  1898 
  1899 static int
  1900 prop_iter_next(struct prop_iter *pi,
  1901 	       enum razor_property_type type, struct razor_property **p)
  1902 {
  1903 	while (pi->p < pi->end) {
  1904 		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  1905 		    pi->p->type == type) {
  1906 			*p = pi->p++;
  1907 			return 1;
  1908 		}
  1909 		pi->p++;
  1910 	}
  1911 
  1912 	return 0;
  1913 }
  1914 
  1915 static struct razor_property *
  1916 prop_iter_seek_to(struct prop_iter *pi,
  1917 		  enum razor_property_type type, const char *match)
  1918 {
  1919 	uint32_t name;
  1920 
  1921 	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  1922 		pi->p++;
  1923 
  1924 	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  1925 		return NULL;
  1926 
  1927 	name = pi->p->name;
  1928 	while (pi->p < pi->end &&
  1929 	       pi->p->name == name &&
  1930 	       pi->p->type != type)
  1931 		pi->p++;
  1932 
  1933 	if (pi->p == pi->end || pi->p->name != name)
  1934 		return NULL;
  1935 
  1936 	return pi->p;
  1937 }
  1938 
  1939 /* Remove packages from set that provide any of the matching (same
  1940  * name and type) providers from ppi onwards that match the
  1941  * requirement that rpi points to. */
  1942 static void
  1943 remove_matching_providers(struct razor_transaction *trans,
  1944 			  struct prop_iter *ppi,
  1945 			  enum razor_version_relation relation,
  1946 			  const char *version)
  1947 {
  1948 	struct razor_property *p;
  1949 	struct razor_package *pkg, *pkgs;
  1950 	struct razor_package_iterator pkg_iter;
  1951 	struct razor_set *set;
  1952 	const char *n, *v, *a;
  1953 
  1954 	if (ppi->present == trans->system.properties)
  1955 		set = trans->system.set;
  1956 	else
  1957 		set = trans->upstream.set;
  1958    
  1959 	pkgs = (struct razor_package *) set->packages.data;
  1960 	for (p = ppi->p; 
  1961 	     p < ppi->end && 
  1962 	     p->name == ppi->p->name &&
  1963 	     p->type == ppi->p->type;
  1964 	     p++) {
  1965 		if (!ppi->present[p - ppi->start])
  1966 			continue;
  1967 		if (!provider_satisfies_requirement(p, ppi->pool,
  1968 						    relation, version))
  1969 			continue;
  1970 		    
  1971 		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  1972 		while (razor_package_iterator_next(&pkg_iter,
  1973 						   &pkg, &n, &v, &a)) {
  1974 			fprintf(stderr, "removing %s-%s\n", n, v);
  1975 			razor_transaction_remove_package(trans, pkg);
  1976 		}
  1977 	}
  1978 }
  1979 
  1980 static void
  1981 flag_matching_providers(struct razor_transaction *trans,
  1982 			struct prop_iter *ppi,
  1983 			struct razor_property *r,
  1984 			struct prop_iter *rpi,
  1985 			unsigned int flag)
  1986 {
  1987 	struct razor_property *p;
  1988 	struct razor_package *pkg, *pkgs;
  1989 	struct razor_package_iterator pkg_iter;
  1990 	struct razor_set *set;
  1991 	const char *name, *version, *arch;
  1992 	uint32_t *flags;
  1993 
  1994 	if (ppi->present == trans->system.properties) {
  1995 		set = trans->system.set;
  1996 		flags = trans->system.packages;
  1997 	} else {
  1998 		set = trans->upstream.set;
  1999 		flags = trans->upstream.packages;
  2000 	}
  2001    
  2002 	pkgs = (struct razor_package *) set->packages.data;
  2003 	for (p = ppi->p; 
  2004 	     p < ppi->end && 
  2005 		     p->name == ppi->p->name &&
  2006 		     p->type == ppi->p->type;
  2007 	     p++) {
  2008 		if (!ppi->present[p - ppi->start])
  2009 			continue;
  2010 		if (!provider_satisfies_requirement(p, ppi->pool,
  2011 						    r->relation,
  2012 						    &rpi->pool[r->version]))
  2013 			continue;
  2014 		    
  2015 		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  2016 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2017 						   &name, &version, &arch)) {
  2018 
  2019 			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  2020 				name, version,
  2021 				ppi->pool + p->name,
  2022 				rpi->pool + r->name,
  2023 				rpi->pool + r->version);
  2024 			flags[pkg - pkgs] |= flag;
  2025 		}
  2026 	}
  2027 }
  2028 
  2029 static struct razor_package *
  2030 pick_matching_provider(struct razor_set *set,
  2031 		       struct prop_iter *ppi,
  2032 		       enum razor_version_relation relation,
  2033 		       const char *version)
  2034 {
  2035 	struct razor_property *p;
  2036 	struct razor_package *pkgs;
  2037 	struct list *i;
  2038 
  2039 	/* This is where we decide which pkgs to pull in to satisfy a
  2040 	 * requirement.  There may be several different providers
  2041 	 * (different versions) and each version of a provider may
  2042 	 * come from a number of packages.  We pick the first package
  2043 	 * from the first provider that matches. */
  2044 
  2045 	pkgs = set->packages.data;
  2046 	for (p = ppi->p;
  2047 	     p < ppi->end &&
  2048 		     p->name == ppi->p->name &&
  2049 		     p->type == ppi->p->type &&
  2050 		     ppi->present[p - ppi->start] == 0;
  2051 	     p++) {
  2052 		if (!provider_satisfies_requirement(p, ppi->pool,
  2053 						    relation, version))
  2054 			continue;
  2055 
  2056 		i = list_first(&p->packages, &set->package_pool);
  2057 
  2058 		return &pkgs[i->data];
  2059 	}
  2060 
  2061 	return NULL;
  2062 }
  2063 
  2064 static void
  2065 remove_obsoleted_packages(struct razor_transaction *trans)
  2066 {
  2067 	struct razor_property *up;
  2068 	struct razor_package *spkgs;
  2069 	struct prop_iter spi, upi;
  2070 
  2071 	spkgs = trans->system.set->packages.data;
  2072 	prop_iter_init(&spi, &trans->system);
  2073 	prop_iter_init(&upi, &trans->upstream);
  2074 	
  2075 	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  2076 		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  2077 				       &upi.pool[up->name]))
  2078 			continue;
  2079 		remove_matching_providers(trans, &spi, up->relation,
  2080 					  &upi.pool[up->version]);
  2081 	}
  2082 }
  2083 
  2084 static int
  2085 any_provider_satisfies_requirement(struct prop_iter *ppi,
  2086 				   enum razor_version_relation relation,
  2087 				   const char *version)
  2088 {
  2089 	struct razor_property *p;
  2090 
  2091 	for (p = ppi->p;
  2092 	     p < ppi->end &&
  2093 		     p->name == ppi->p->name &&
  2094 		     p->type == ppi->p->type;
  2095 	     p++) {
  2096 		if (ppi->present[p - ppi->start] > 0 &&
  2097 		    provider_satisfies_requirement(p, ppi->pool,
  2098 						   relation, version))
  2099 			return 1;
  2100 	}
  2101 
  2102 	return 0;
  2103 }
  2104 
  2105 static void
  2106 clear_requires_flags(struct transaction_set *ts)
  2107 {
  2108 	struct razor_property *p;
  2109 	const char *pool;
  2110 	int i, count;
  2111 
  2112 	count = ts->set->properties.size / sizeof *p;
  2113 	p = ts->set->properties.data;
  2114 	pool = ts->set->string_pool.data;
  2115 	for (i = 0; i < count; i++) {
  2116 		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  2117 		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  2118 			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  2119 	}
  2120 }
  2121 
  2122 static void
  2123 mark_satisfied_requires(struct razor_transaction *trans,
  2124 			struct transaction_set *rts,
  2125 			struct transaction_set *pts)
  2126 {
  2127 	struct prop_iter rpi, ppi;
  2128 	struct razor_property *rp;
  2129 
  2130 	prop_iter_init(&rpi, rts);
  2131 	prop_iter_init(&ppi, pts);
  2132 
  2133 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2134 		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  2135 				       &rpi.pool[rp->name]))
  2136 			continue;
  2137 
  2138 		if (any_provider_satisfies_requirement(&ppi, rp->relation,
  2139 						       &rpi.pool[rp->version]))
  2140 			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  2141 	}
  2142 }
  2143 
  2144 static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  2145 
  2146 static void
  2147 mark_all_satisfied_requires(struct razor_transaction *trans)
  2148 {
  2149 	struct razor_property *sp;
  2150 	struct prop_iter spi;
  2151 
  2152 	clear_requires_flags(&trans->system);
  2153 	clear_requires_flags(&trans->upstream);
  2154 	mark_satisfied_requires(trans, &trans->system, &trans->system);
  2155 	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  2156 	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  2157 	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  2158 
  2159 	prop_iter_init(&spi, &trans->system);
  2160 	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  2161 		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  2162 			continue;
  2163 		fprintf(stderr, "unsatisfied system requires: %s %s %s\n",
  2164 			spi.pool + sp->name,
  2165 			relation_string[sp->relation],
  2166 			spi.pool + sp->version);
  2167 	}
  2168 
  2169 	prop_iter_init(&spi, &trans->upstream);
  2170 	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  2171 		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  2172 			continue;
  2173 		fprintf(stderr, "unsatisfied upstream requires: %s %s %s\n",
  2174 			spi.pool + sp->name,
  2175 			relation_string[sp->relation],
  2176 			spi.pool + sp->version);
  2177 	}
  2178 }
  2179 
  2180 static void
  2181 update_unsatisfied_packages(struct razor_transaction *trans)
  2182 {
  2183 	struct razor_package *spkgs, *pkg;
  2184 	struct razor_property *sp;
  2185 	struct prop_iter spi;
  2186 	struct razor_package_iterator pkg_iter;
  2187 	const char *name, *version, *arch;
  2188 
  2189 	spkgs = trans->system.set->packages.data;
  2190 	prop_iter_init(&spi, &trans->system);
  2191 	
  2192 	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  2193 		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  2194 			continue;
  2195 		
  2196 		razor_package_iterator_init_for_property(&pkg_iter,
  2197 							 trans->system.set,
  2198 							 sp);
  2199 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2200 						   &name, &version, &arch)) {
  2201 			fprintf(stderr, "updating %s because %s %s %s "
  2202 				"isn't satisfied\n",
  2203 				name, spi.pool + sp->name,
  2204 				relation_string[sp->relation],
  2205 				spi.pool + sp->version);
  2206 			trans->system.packages[pkg - spkgs] |=
  2207 				TRANS_PACKAGE_UPDATE;
  2208 		}
  2209 	}
  2210 }
  2211 
  2212 void
  2213 razor_transaction_update_all(struct razor_transaction *trans)
  2214 {
  2215 	struct razor_package *p;
  2216 	int i, count;
  2217 
  2218 	count = trans->system.set->packages.size / sizeof *p;
  2219 	for (i = 0; i < count; i++)
  2220 		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  2221 }
  2222 
  2223 static void
  2224 update_conflicted_packages(struct razor_transaction *trans)
  2225 {
  2226 	struct razor_package *pkg, *spkgs;
  2227 	struct razor_property *up, *sp;
  2228 	struct prop_iter spi, upi;
  2229 	struct razor_package_iterator pkg_iter;
  2230 	const char *name, *version, *arch;
  2231 
  2232 	spkgs = trans->system.set->packages.data;
  2233 	prop_iter_init(&spi, &trans->system);
  2234 	prop_iter_init(&upi, &trans->upstream);
  2235 
  2236 	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  2237 		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  2238 				       &spi.pool[sp->name]))
  2239 			continue;
  2240 
  2241 		if (!any_provider_satisfies_requirement(&upi, sp->relation,
  2242 							&spi.pool[sp->version]))
  2243 			continue;
  2244 
  2245 		razor_package_iterator_init_for_property(&pkg_iter,
  2246 							 trans->system.set,
  2247 							 sp);
  2248 		while (razor_package_iterator_next(&pkg_iter, &pkg,
  2249 						   &name, &version, &arch)) {
  2250 			fprintf(stderr, "updating %s %s because it conflicts with %s",
  2251 				name, version, spi.pool + sp->name);
  2252 			trans->system.packages[pkg - spkgs] |=
  2253 				TRANS_PACKAGE_UPDATE;
  2254 		}
  2255 	}
  2256 
  2257 	prop_iter_init(&spi, &trans->system);
  2258 	prop_iter_init(&upi, &trans->upstream);
  2259 
  2260 	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  2261 		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  2262 				       &upi.pool[upi.p->name]);
  2263 
  2264 		if (sp)
  2265 			flag_matching_providers(trans, &spi, up, &upi,
  2266 						TRANS_PACKAGE_UPDATE);
  2267 	}
  2268 }
  2269 
  2270 static void
  2271 pull_in_requirements(struct razor_transaction *trans,
  2272 		     struct prop_iter *rpi, struct prop_iter *ppi)
  2273 {
  2274 	struct razor_property *rp, *pp;
  2275 	struct razor_package *pkg, *upkgs;
  2276 
  2277 	upkgs = trans->upstream.set->packages.data;
  2278 	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2279 		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  2280 			continue;
  2281 
  2282 		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  2283 				       &rpi->pool[rp->name]);
  2284 		if (pp == NULL)
  2285 			continue;
  2286 		pkg = pick_matching_provider(trans->upstream.set,
  2287 					     ppi, rp->relation,
  2288 					     &rpi->pool[rp->version]);
  2289 		if (pkg == NULL)
  2290 			continue;
  2291 
  2292 		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  2293 
  2294 		fprintf(stderr, "pulling in %s which provides %s %s %s "
  2295 			"to satisfy %s %s %s\n",
  2296 			ppi->pool + pkg->name,
  2297 			ppi->pool + pp->name, 
  2298 			relation_string[pp->relation],
  2299 			ppi->pool + pp->version, 
  2300 			&rpi->pool[rp->name],
  2301 			relation_string[rp->relation],
  2302 			&rpi->pool[rp->version]);
  2303 
  2304 		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  2305 	}
  2306 }
  2307 
  2308 static void
  2309 pull_in_all_requirements(struct razor_transaction *trans)
  2310 {
  2311 	struct prop_iter rpi, ppi;
  2312 	struct razor_property *rp;
  2313 
  2314 	prop_iter_init(&rpi, &trans->system);
  2315 	prop_iter_init(&ppi, &trans->upstream);
  2316 	pull_in_requirements(trans, &rpi, &ppi);
  2317 	
  2318 	prop_iter_init(&rpi, &trans->upstream);
  2319 	prop_iter_init(&ppi, &trans->upstream);
  2320 	pull_in_requirements(trans, &rpi, &ppi);
  2321 
  2322 	prop_iter_init(&rpi, &trans->system);
  2323 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2324 		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED))
  2325 			fprintf(stderr, "could not satisfy req %s %s %s\n",
  2326 				&rpi.pool[rp->name],
  2327 				relation_string[rp->relation],
  2328 				&rpi.pool[rp->version]);
  2329 	}
  2330 
  2331 	prop_iter_init(&rpi, &trans->upstream);
  2332 	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  2333 		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED))
  2334 			fprintf(stderr, "could not satisfy req %s %s %s\n",
  2335 				&rpi.pool[rp->name],
  2336 				relation_string[rp->relation],
  2337 				&rpi.pool[rp->version]);
  2338 	}
  2339 }
  2340 
  2341 static void
  2342 flush_scheduled_system_updates(struct razor_transaction *trans)
  2343 {
  2344  	struct razor_package_iterator *pi;
  2345  	struct razor_package *p, *pkg, *spkgs;
  2346 	struct prop_iter ppi;
  2347 	const char *name, *version, *arch;
  2348 
  2349 	spkgs = trans->system.set->packages.data;
  2350 	pi = razor_package_iterator_create(trans->system.set);
  2351 	prop_iter_init(&ppi, &trans->upstream);
  2352 
  2353 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2354 		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  2355 			continue;
  2356 
  2357 		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name)) {
  2358 			fprintf(stderr, "nothing provides %s\n", name);
  2359 			continue;
  2360 		}
  2361 
  2362 		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  2363 					     RAZOR_VERSION_GREATER, version);
  2364 		if (pkg == NULL) {
  2365 			fprintf(stderr,
  2366 				"no newer version of %s available\n", name);
  2367 			continue;
  2368 		}
  2369 		
  2370 		fprintf(stderr, "updating %s from %s to %s\n",
  2371 			name, version, &ppi.pool[pkg->version]);
  2372 
  2373 		razor_transaction_remove_package(trans, p);
  2374 		razor_transaction_install_package(trans, pkg);
  2375 	}
  2376 
  2377 	razor_package_iterator_destroy(pi);
  2378 }
  2379 
  2380 static void
  2381 flush_scheduled_upstream_updates(struct razor_transaction *trans)
  2382 {
  2383  	struct razor_package_iterator *pi;
  2384  	struct razor_package *p, *upkgs;
  2385 	struct prop_iter spi;
  2386 	const char *name, *version, *arch;
  2387 
  2388 	upkgs = trans->upstream.set->packages.data;
  2389 	pi = razor_package_iterator_create(trans->upstream.set);
  2390 	prop_iter_init(&spi, &trans->system);
  2391 
  2392 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2393 		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  2394 			continue;
  2395 
  2396 		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  2397 			continue;
  2398 		remove_matching_providers(trans, &spi,
  2399 					  RAZOR_VERSION_LESS, version);
  2400 		razor_transaction_install_package(trans, p);
  2401 		fprintf(stderr, "installing %s-%s\n", name, version);
  2402 	}
  2403 }
  2404 
  2405 int
  2406 razor_transaction_resolve(struct razor_transaction *trans)
  2407 {
  2408 	int last = 0;
  2409 
  2410 	flush_scheduled_system_updates(trans);
  2411 
  2412 	while (last < trans->changes) {
  2413 		last = trans->changes;
  2414 		remove_obsoleted_packages(trans);
  2415 		mark_all_satisfied_requires(trans);
  2416 		update_unsatisfied_packages(trans);
  2417 		update_conflicted_packages(trans);
  2418 		pull_in_all_requirements(trans);
  2419 		flush_scheduled_system_updates(trans);
  2420 		flush_scheduled_upstream_updates(trans);
  2421 	}
  2422 
  2423 	return trans->changes;
  2424 }
  2425 
  2426 int
  2427 razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  2428 				       const char *name,
  2429 				       enum razor_version_relation rel,
  2430 				       const char *version,
  2431 				       enum razor_property_type type)
  2432 {
  2433 	struct prop_iter pi;
  2434 	struct razor_property *p;
  2435 
  2436 	prop_iter_init(&pi, &trans->system);
  2437 	while (prop_iter_next(&pi, type, &p)) {
  2438 		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  2439 		    p->relation == rel &&
  2440 		    strcmp(&pi.pool[p->name], name) == 0 &&
  2441 		    strcmp(&pi.pool[p->version], version) == 0)
  2442 		    
  2443 			return 1;
  2444 	}
  2445 
  2446 	prop_iter_init(&pi, &trans->upstream);
  2447 	while (prop_iter_next(&pi, type, &p)) {
  2448 		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  2449 		    p->relation == rel &&
  2450 		    strcmp(&pi.pool[p->name], name) == 0 &&
  2451 		    strcmp(&pi.pool[p->version], version) == 0)
  2452 		    
  2453 			return 1;
  2454 	}
  2455 
  2456 	return 0;
  2457 }
  2458 
  2459 struct razor_set *
  2460 razor_transaction_finish(struct razor_transaction *trans)
  2461 {
  2462 	struct razor_merger *merger;
  2463 	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  2464 	char *upool, *spool;
  2465 	int cmp;
  2466 
  2467 	s = trans->system.set->packages.data;
  2468 	spkgs = trans->system.set->packages.data;
  2469 	send = trans->system.set->packages.data +
  2470 		trans->system.set->packages.size;
  2471 	spool = trans->system.set->string_pool.data;
  2472 
  2473 	u = trans->upstream.set->packages.data;
  2474 	upkgs = trans->upstream.set->packages.data;
  2475 	uend = trans->upstream.set->packages.data +
  2476 		trans->upstream.set->packages.size;
  2477 	upool = trans->upstream.set->string_pool.data;
  2478 
  2479 	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  2480 	while (s < send || u < uend) {
  2481 		if (s < send && u < uend)
  2482 			cmp = strcmp(&spool[s->name], &upool[u->name]);
  2483 		else if (s < send)
  2484 			cmp = -1;
  2485 		else
  2486 			cmp = 1;
  2487 
  2488 		if (cmp < 0) {
  2489 			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  2490 				razor_merger_add_package(merger, s);
  2491 			s++;
  2492 		} else if (cmp == 0) {
  2493 			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  2494 				razor_merger_add_package(merger, s);
  2495 			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  2496 				razor_merger_add_package(merger, u);
  2497 
  2498 			s++;
  2499 			u++;
  2500 		} else {
  2501 			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  2502 				razor_merger_add_package(merger, u);
  2503 			u++;
  2504 		}
  2505 	}
  2506 
  2507 	razor_transaction_destroy(trans);
  2508 
  2509 	return razor_merger_finish(merger);
  2510 }
  2511 
  2512 void
  2513 razor_transaction_destroy(struct razor_transaction *trans)
  2514 {
  2515 	transaction_set_release(&trans->system);
  2516 	transaction_set_release(&trans->upstream);
  2517 	free(trans);
  2518 
  2519 	/* FIXME: free upstream if it was created as an empty set */
  2520 }
  2521 
  2522 struct razor_package_query {
  2523 	struct razor_set *set;
  2524 	char *vector;
  2525 	int count;
  2526 };
  2527 
  2528 struct razor_package_query *
  2529 razor_package_query_create(struct razor_set *set)
  2530 {
  2531 	struct razor_package_query *pq;
  2532 	int count;
  2533 
  2534 	pq = zalloc(sizeof *pq);
  2535 	pq->set = set;
  2536 	count = set->packages.size / sizeof(struct razor_package);
  2537 	pq->vector = zalloc(count * sizeof(char));
  2538 
  2539 	return pq;
  2540 }
  2541 
  2542 void
  2543 razor_package_query_add_package(struct razor_package_query *pq,
  2544 				struct razor_package *p)
  2545 {
  2546 	struct razor_package *packages;
  2547 
  2548 	packages = pq->set->packages.data;
  2549 	pq->count += pq->vector[p - packages] ^ 1;
  2550 	pq->vector[p - packages] = 1;
  2551 }
  2552 
  2553 void
  2554 razor_package_query_add_iterator(struct razor_package_query *pq,
  2555 				 struct razor_package_iterator *pi)
  2556 {
  2557 	struct razor_package *packages, *p;
  2558 	const char *name, *version, *arch;
  2559 
  2560 	packages = pq->set->packages.data;
  2561 	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  2562 		pq->count += pq->vector[p - packages] ^ 1;
  2563 		pq->vector[p - packages] = 1;
  2564 	}
  2565 }
  2566 
  2567 struct razor_package_iterator *
  2568 razor_package_query_finish(struct razor_package_query *pq)
  2569 {
  2570 	struct razor_package_iterator *pi;
  2571 	struct razor_set *set;
  2572 	struct list *index;
  2573 	int i, j, count;
  2574 
  2575 	set = pq->set;
  2576 	count = set->packages.size / sizeof(struct razor_package);
  2577 	index = zalloc(pq->count * sizeof *index);
  2578 
  2579 	for (i = 0, j = 0; i < count; i++) {
  2580 		if (!pq->vector[i])
  2581 			continue;
  2582 
  2583 		index[j].data = i;
  2584 		if (j == pq->count - 1)
  2585 			index[j].flags = 0x80;
  2586 		j++;
  2587 	}
  2588 
  2589 	free(pq);
  2590 
  2591 	pi = razor_package_iterator_create_with_index(set, index);
  2592 	pi->free_index = 1;
  2593 
  2594 	return pi;
  2595 }