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.
7 array_init(struct array *array)
9 memset(array, 0, sizeof *array);
13 array_release(struct array *array)
19 array_add(struct array *array, int size)
29 while (alloc < array->size + size)
32 if (array->alloc < alloc) {
33 data = realloc(array->data, alloc);
40 p = array->data + array->size;
46 /* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
47 #define RAZOR_ENTRY_LAST 0x80
48 #define RAZOR_IMMEDIATE 0x80
49 #define RAZOR_EMPTY_LIST 0xff
52 list_set_empty(struct list_head *head)
55 head->flags = RAZOR_EMPTY_LIST;
59 list_set_ptr(struct list_head *head, uint32_t ptr)
66 list_set_array(struct list_head *head, struct array *pool,
67 struct array *items, int force_indirect)
71 if (!force_indirect) {
72 if (items->size == 0) {
75 } else if (items->size == sizeof (uint32_t)) {
76 head->list_ptr = *(uint32_t *) items->data;
77 head->flags = RAZOR_IMMEDIATE;
82 p = array_add(pool, items->size);
83 memcpy(p, items->data, items->size);
84 p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
85 list_set_ptr(head, p - (struct list *) pool->data);
89 list_first(struct list_head *head, struct array *pool)
91 if (head->flags == RAZOR_EMPTY_LIST)
93 else if (head->flags == RAZOR_IMMEDIATE)
94 return (struct list *) head;
96 return (struct list *) pool->data + head->list_ptr;
100 list_next(struct list *list)
108 list_remap_pool(struct array *pool, uint32_t *map)
110 struct list *p, *end;
112 end = pool->data + pool->size;
113 for (p = pool->data; p < end; p++)
114 p->data = map[p->data];
118 list_remap_head(struct list_head *head, uint32_t *map)
120 if (head->flags == RAZOR_IMMEDIATE)
121 head->list_ptr = map[head->list_ptr];
126 hashtable_init(struct hashtable *table, struct array *pool)
128 array_init(&table->buckets);
133 hashtable_release(struct hashtable *table)
135 array_release(&table->buckets);
139 hash_string(const char *key)
142 unsigned int hash = 0;
144 for (p = key; *p; p++)
145 hash = (hash * 617) ^ *p;
151 hashtable_lookup(struct hashtable *table, const char *key)
153 unsigned int mask, start, i;
157 pool = table->pool->data;
158 mask = table->buckets.alloc - 1;
159 start = hash_string(key) * sizeof(uint32_t);
161 for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
162 b = table->buckets.data + ((start + i) & mask);
167 if (strcmp(key, &pool[*b]) == 0)
175 do_insert(struct hashtable *table, uint32_t value)
177 unsigned int mask, start, i;
181 key = (char *) table->pool->data + value;
182 mask = table->buckets.alloc - 1;
183 start = hash_string(key) * sizeof(uint32_t);
185 for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
186 b = table->buckets.data + ((start + i) & mask);
195 add_to_string_pool(struct hashtable *table, const char *key)
200 len = strlen(key) + 1;
201 p = array_add(table->pool, len);
204 return p - (char *) table->pool->data;
208 hashtable_insert(struct hashtable *table, const char *key)
210 uint32_t value, *buckets, *b, *end;
213 alloc = table->buckets.alloc;
214 array_add(&table->buckets, 4 * sizeof *buckets);
215 if (alloc != table->buckets.alloc) {
216 end = table->buckets.data + alloc;
217 memset(end, 0, table->buckets.alloc - alloc);
218 for (b = table->buckets.data; b < end; b++) {
222 do_insert(table, value);
227 value = add_to_string_pool(table, key);
228 do_insert (table, value);
234 hashtable_tokenize(struct hashtable *table, const char *string)
241 token = hashtable_lookup(table, string);
245 return hashtable_insert(table, string);