types.c
author Kristian H?gsberg <krh@redhat.com>
Mon Jun 09 12:47:37 2008 -0400 (2008-06-09)
changeset 230 c1e2aed8dd07
parent 195 7a53d1711083
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 #include <stdlib.h>
     2 #include <string.h>
     3 
     4 #include "types.h"
     5 
     6 void
     7 array_init(struct array *array)
     8 {
     9 	memset(array, 0, sizeof *array);
    10 }
    11 
    12 void
    13 array_release(struct array *array)
    14 {
    15 	free(array->data);
    16 }
    17 
    18 void *
    19 array_add(struct array *array, int size)
    20 {
    21 	int alloc;
    22 	void *data, *p;
    23 
    24 	if (array->alloc > 0)
    25 		alloc = array->alloc;
    26 	else
    27 		alloc = 16;
    28 
    29 	while (alloc < array->size + size)
    30 		alloc *= 2;
    31 
    32 	if (array->alloc < alloc) {
    33 		data = realloc(array->data, alloc);
    34 		if (data == NULL)
    35 			return 0;
    36 		array->data = data;
    37 		array->alloc = alloc;
    38 	}
    39 
    40 	p = array->data + array->size;
    41 	array->size += size;
    42 
    43 	return p;
    44 }
    45 
    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
    50 
    51 void
    52 list_set_empty(struct list_head *head)
    53 {
    54 	head->list_ptr = ~0;
    55 	head->flags = RAZOR_EMPTY_LIST;
    56 }
    57 
    58 void
    59 list_set_ptr(struct list_head *head, uint32_t ptr)
    60 {
    61 	head->list_ptr = ptr;
    62 	head->flags = 0;
    63 }
    64 
    65 void
    66 list_set_array(struct list_head *head, struct array *pool,
    67 	       struct array *items, int force_indirect)
    68 {
    69 	struct list *p;
    70 
    71 	if (!force_indirect) {
    72 		if (items->size == 0) {
    73 			list_set_empty(head);
    74 			return;
    75 		} else if (items->size == sizeof (uint32_t)) {
    76 			head->list_ptr = *(uint32_t *) items->data;
    77 			head->flags = RAZOR_IMMEDIATE;
    78 			return;
    79 		}
    80 	}
    81 
    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);
    86 }
    87 
    88 struct list *
    89 list_first(struct list_head *head, struct array *pool)
    90 {
    91 	if (head->flags == RAZOR_EMPTY_LIST)
    92 		return NULL;
    93 	else if (head->flags == RAZOR_IMMEDIATE)
    94 		return (struct list *) head;
    95 	else
    96 		return (struct list *) pool->data + head->list_ptr;
    97 }
    98 
    99 struct list *
   100 list_next(struct list *list)
   101 {
   102 	if (list->flags)
   103 		return NULL;
   104 	return ++list;
   105 }
   106 
   107 void
   108 list_remap_pool(struct array *pool, uint32_t *map)
   109 {
   110 	struct list *p, *end;
   111 
   112 	end = pool->data + pool->size;
   113 	for (p = pool->data; p < end; p++)
   114 		p->data = map[p->data];
   115 }
   116 
   117 void
   118 list_remap_head(struct list_head *head, uint32_t *map)
   119 {
   120 	if (head->flags == RAZOR_IMMEDIATE)
   121 		head->list_ptr = map[head->list_ptr];
   122 }
   123 
   124 
   125 void
   126 hashtable_init(struct hashtable *table, struct array *pool)
   127 {
   128 	array_init(&table->buckets);
   129 	table->pool = pool;
   130 }
   131 
   132 void
   133 hashtable_release(struct hashtable *table)
   134 {
   135 	array_release(&table->buckets);
   136 }
   137 
   138 static unsigned int
   139 hash_string(const char *key)
   140 {
   141 	const char *p;
   142 	unsigned int hash = 0;
   143 
   144 	for (p = key; *p; p++)
   145 		hash = (hash * 617) ^ *p;
   146 
   147 	return hash;
   148 }
   149 
   150 uint32_t
   151 hashtable_lookup(struct hashtable *table, const char *key)
   152 {
   153 	unsigned int mask, start, i;
   154 	uint32_t *b;
   155 	char *pool;
   156 
   157 	pool = table->pool->data;
   158 	mask = table->buckets.alloc - 1;
   159 	start = hash_string(key) * sizeof(uint32_t);
   160 
   161 	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   162 		b = table->buckets.data + ((start + i) & mask);
   163 
   164 		if (*b == 0)
   165 			return 0;
   166 
   167 		if (strcmp(key, &pool[*b]) == 0)
   168 			return *b;
   169 	}
   170 
   171 	return 0;
   172 }
   173 
   174 static void
   175 do_insert(struct hashtable *table, uint32_t value)
   176 {
   177 	unsigned int mask, start, i;
   178 	uint32_t *b;
   179 	const char *key;
   180 
   181 	key = (char *) table->pool->data + value;
   182 	mask = table->buckets.alloc - 1;
   183 	start = hash_string(key) * sizeof(uint32_t);
   184 
   185 	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
   186 		b = table->buckets.data + ((start + i) & mask);
   187 		if (*b == 0) {
   188 			*b = value;
   189 			break;
   190 		}
   191 	}
   192 }
   193 
   194 static uint32_t
   195 add_to_string_pool(struct hashtable *table, const char *key)
   196 {
   197 	int len;
   198 	char *p;
   199 
   200 	len = strlen(key) + 1;
   201 	p = array_add(table->pool, len);
   202 	memcpy(p, key, len);
   203 
   204 	return p - (char *) table->pool->data;
   205 }
   206 
   207 uint32_t
   208 hashtable_insert(struct hashtable *table, const char *key)
   209 {
   210 	uint32_t value, *buckets, *b, *end;
   211 	int alloc;
   212 
   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++) {
   219 			value = *b;
   220 			if (value != 0) {
   221 				*b = 0;
   222 				do_insert(table, value);
   223 			}
   224 		}
   225 	}
   226 
   227 	value = add_to_string_pool(table, key);
   228 	do_insert (table, value);
   229 
   230 	return value;
   231 }
   232 
   233 uint32_t
   234 hashtable_tokenize(struct hashtable *table, const char *string)
   235 {
   236 	uint32_t token;
   237 
   238 	if (string == NULL)
   239 		string = "";
   240 
   241 	token = hashtable_lookup(table, string);
   242 	if (token != 0)
   243 		return token;
   244 
   245 	return hashtable_insert(table, string);
   246 }