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