razor.c
changeset 3 917677cdceb3
parent 0 e15eb9ef9c28
child 4 c8e9dbcfaf02
     1.1 --- a/razor.c	Mon Sep 03 14:36:59 2007 -0400
     1.2 +++ b/razor.c	Mon Sep 03 23:13:19 2007 -0400
     1.3 @@ -50,6 +50,12 @@
     1.4  #define HASHTABLE_VERSION 1
     1.5  #define HASHTABLE_BUCKETS 1
     1.6  #define HASHTABLE_STRINGS 2
     1.7 +#define HASHTABLE_PACKAGES 3
     1.8 +
     1.9 +struct package {
    1.10 +	unsigned long name;
    1.11 +	unsigned long version;
    1.12 +};
    1.13  
    1.14  struct hashtable {
    1.15  	unsigned long *buckets;
    1.16 @@ -57,6 +63,9 @@
    1.17  	char *string_pool;
    1.18  	int pool_size, pool_alloc;
    1.19  	struct hashtable_header *header;
    1.20 +
    1.21 +	struct package *packages;
    1.22 +	int package_count, package_alloc;
    1.23  };
    1.24  
    1.25  static void *
    1.26 @@ -84,6 +93,10 @@
    1.27  	ht->pool_size = 1;
    1.28  	ht->pool_alloc = 4096;
    1.29  
    1.30 +	ht->packages = zalloc(4096 * sizeof *ht->packages);
    1.31 +	ht->package_count = 0;
    1.32 +	ht->package_alloc = 4096;
    1.33 +
    1.34  	return ht;
    1.35  }
    1.36  
    1.37 @@ -120,6 +133,11 @@
    1.38  			ht->pool_size = size;
    1.39  			ht->pool_alloc = size;
    1.40  			break;
    1.41 +		case HASHTABLE_PACKAGES:
    1.42 +			ht->packages = (void *) ht->header + offset;
    1.43 +			ht->package_count = size / sizeof *ht->packages;
    1.44 +			ht->package_alloc = size / sizeof *ht->packages;
    1.45 +			break;
    1.46  		}
    1.47  	}
    1.48  	close(fd);
    1.49 @@ -149,9 +167,14 @@
    1.50  static int
    1.51  hashtable_write(struct hashtable *ht, const char *filename)
    1.52  {
    1.53 -	int fd;
    1.54  	char data[4096];
    1.55  	struct hashtable_header *header = (struct hashtable_header *) data;
    1.56 +	int fd, pool_size, package_size;
    1.57 +
    1.58 +	/* Align these to pages sizes */
    1.59 +	pool_size = (ht->pool_size + 4095) & ~4095;
    1.60 +	package_size =
    1.61 +		(ht->package_alloc * sizeof *ht->packages + 4095) & ~4095;
    1.62  
    1.63  	memset(data, 0, sizeof data);
    1.64  	header->magic = HASHTABLE_MAGIC;
    1.65 @@ -161,12 +184,14 @@
    1.66  	header->sections[0].offset = sizeof data;
    1.67  
    1.68  	header->sections[1].type = HASHTABLE_STRINGS;
    1.69 -	header->sections[1].offset =
    1.70 -		sizeof data + ht->bucket_alloc * sizeof *ht->buckets;
    1.71 +	header->sections[1].offset = header->sections[0].offset +
    1.72 +		ht->bucket_alloc * sizeof *ht->buckets;
    1.73  
    1.74 -	header->sections[2].type = 0;
    1.75 -	header->sections[2].offset =
    1.76 -		header->sections[1].offset + ht->pool_size;
    1.77 +	header->sections[2].type = HASHTABLE_PACKAGES;
    1.78 +	header->sections[2].offset = header->sections[1].offset + pool_size;
    1.79 +
    1.80 +	header->sections[3].type = 0;
    1.81 +	header->sections[3].offset = header->sections[2].offset + package_size;
    1.82  
    1.83  	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    1.84  	if (fd < 0)
    1.85 @@ -174,7 +199,8 @@
    1.86  
    1.87  	write_to_fd(fd, data, sizeof data);
    1.88  	write_to_fd(fd, ht->buckets, ht->bucket_alloc * sizeof *ht->buckets);
    1.89 -	write_to_fd(fd, ht->string_pool, ht->pool_size);
    1.90 +	write_to_fd(fd, ht->string_pool, pool_size);
    1.91 +	write_to_fd(fd, ht->packages, package_size);
    1.92  
    1.93  	return 0;
    1.94  }
    1.95 @@ -297,6 +323,32 @@
    1.96  	return value;
    1.97  }
    1.98  
    1.99 +static unsigned long
   1.100 +hashtable_add_package(struct hashtable *ht,
   1.101 +		      unsigned long name, unsigned long version)
   1.102 +{
   1.103 +	struct package *packages;
   1.104 +	int alloc;
   1.105 +
   1.106 +	alloc = ht->package_alloc;
   1.107 +	while (alloc < ht->package_count + 1)
   1.108 +		alloc *= 2;
   1.109 +	if (ht->package_alloc < alloc) {
   1.110 +		packages = realloc(ht->packages, alloc * sizeof ht->packages);
   1.111 +		if (packages == NULL)
   1.112 +			return 0;
   1.113 +		ht->packages = packages;
   1.114 +		ht->package_alloc = alloc;
   1.115 +	}
   1.116 +
   1.117 +	ht->packages[ht->package_count].name = name;
   1.118 +	ht->packages[ht->package_count].version = version;
   1.119 +	ht->package_count++;
   1.120 +
   1.121 +	return 0;
   1.122 +}
   1.123 +
   1.124 +
   1.125  struct razor_context {
   1.126  	struct hashtable *global_ht;
   1.127  };
   1.128 @@ -335,6 +387,27 @@
   1.129  	return hashtable_insert(ctx->global_ht, string);
   1.130  }
   1.131  
   1.132 +static struct hashtable *qsort_ht;
   1.133 +
   1.134 +static int
   1.135 +compare_packages(const void *p1, const void *p2)
   1.136 +{
   1.137 +	const struct package *pkg1 = p1, *pkg2 = p2;
   1.138 +
   1.139 +	return strcmp(&qsort_ht->string_pool[pkg1->name],
   1.140 +		      &qsort_ht->string_pool[pkg2->name]);
   1.141 +}
   1.142 +
   1.143 +static void
   1.144 +razor_context_sort(struct razor_context *ctx)
   1.145 +{
   1.146 +	struct hashtable *ht = ctx->global_ht;
   1.147 +
   1.148 +	qsort_ht = ht;
   1.149 +	qsort(ht->packages, ht->package_count, sizeof *ht->packages,
   1.150 +	      compare_packages);
   1.151 +}
   1.152 +
   1.153  struct razor_set {
   1.154  	struct razor_context *ctx;
   1.155  };
   1.156 @@ -344,11 +417,36 @@
   1.157  };
   1.158  
   1.159  static void
   1.160 +parse_package(struct parsing_context *ctx, const char **atts)
   1.161 +{
   1.162 +	unsigned long name, version;
   1.163 +	int i;
   1.164 +
   1.165 +	for (i = 0; atts[i]; i += 2) {
   1.166 +		if (strcmp(atts[i], "name") == 0)
   1.167 +			name = razor_context_tokenize(ctx->ctx, atts[i + 1]);
   1.168 +		else if (strcmp(atts[i], "version") == 0)
   1.169 +			version = razor_context_tokenize(ctx->ctx, atts[i + 1]);
   1.170 +	}
   1.171 +
   1.172 +	if (name == 0 || version == 0) {
   1.173 +		fprintf(stderr, "invalid package tag, "
   1.174 +			"missing name or version attributes\n");
   1.175 +		return;
   1.176 +	}
   1.177 +
   1.178 +	hashtable_add_package(ctx->ctx->global_ht, name, version);
   1.179 +}
   1.180 +
   1.181 +static void
   1.182  start_element(void *data, const char *name, const char **atts)
   1.183  {
   1.184  	struct parsing_context *ctx = data;
   1.185  	int i;
   1.186  
   1.187 +	if (strcmp(name, "package") == 0)
   1.188 +		parse_package(ctx, atts);
   1.189 +
   1.190  	for (i = 0; atts[i]; i += 2)
   1.191  		razor_context_tokenize(ctx->ctx, atts[i + 1]);
   1.192  }
   1.193 @@ -432,6 +530,47 @@
   1.194  }
   1.195  
   1.196  void
   1.197 +razor_context_list_packages(struct razor_context *ctx)
   1.198 +{
   1.199 +	int i;
   1.200 +	struct hashtable *ht = ctx->global_ht;
   1.201 +	struct package *p;
   1.202 +
   1.203 +	p = ht->packages;
   1.204 +	for (i = 0; i < ht->package_count && p->name; i++, p++) {
   1.205 +		printf("%s %s\n",
   1.206 +		       &ht->string_pool[p->name],
   1.207 +		       &ht->string_pool[p->version]);
   1.208 +	}
   1.209 +}
   1.210 +
   1.211 +void
   1.212 +razor_context_info(struct razor_context *ctx)
   1.213 +{
   1.214 +	struct hashtable *ht = ctx->global_ht;
   1.215 +	unsigned int offset, size;
   1.216 +	int i;
   1.217 +
   1.218 +	for (i = 0; i < ht->header->sections[i].type; i++) {
   1.219 +		offset = ht->header->sections[i].offset;
   1.220 +		size = ht->header->sections[i + 1].offset - offset;
   1.221 +
   1.222 +		switch (ht->header->sections[i].type) {
   1.223 +		case HASHTABLE_BUCKETS:
   1.224 +			printf("bucket section:\t\t%dkb\n", size / 1024);
   1.225 +			break;
   1.226 +		case HASHTABLE_STRINGS:
   1.227 +			printf("string pool:\t\t%dkb\n", size / 1024);
   1.228 +			break;
   1.229 +		case HASHTABLE_PACKAGES:
   1.230 +			printf("package section:\t%dkb\n", size / 1024);
   1.231 +			break;
   1.232 +		}
   1.233 +	}
   1.234 +
   1.235 +}
   1.236 +
   1.237 +void
   1.238  razor_context_destroy(struct razor_context *ctx)
   1.239  {
   1.240  	hashtable_destroy(ctx->global_ht);
   1.241 @@ -441,7 +580,7 @@
   1.242  static int
   1.243  usage(void)
   1.244  {
   1.245 -	printf("usage: razor [ import FILES | lookup <key> ]\n");
   1.246 +	printf("usage: razor [ import FILES | lookup <key> | list | info ]\n");
   1.247  	exit(1);
   1.248  }
   1.249  
   1.250 @@ -454,7 +593,7 @@
   1.251  	struct razor_context *ctx;
   1.252  	struct stat statbuf;
   1.253  
   1.254 -	if (argc < 3) {
   1.255 +	if (argc < 2) {
   1.256  		usage();
   1.257  	} else if (strcmp(argv[1], "import") == 0) {
   1.258  		if (stat("set", &statbuf) && mkdir("set", 0777)) {
   1.259 @@ -472,6 +611,8 @@
   1.260  			}
   1.261  		}
   1.262  
   1.263 +		razor_context_sort(ctx);
   1.264 +
   1.265  		printf("number of buckets: %d\n",
   1.266  		       ctx->global_ht->bucket_count);
   1.267  		printf("bucket allocation: %d\n",
   1.268 @@ -487,6 +628,14 @@
   1.269  		printf("%s is %lu\n", argv[2],
   1.270  		       hashtable_lookup(ctx->global_ht, argv[2]));
   1.271  		razor_context_destroy(ctx);
   1.272 +	} else if (strcmp(argv[1], "list") == 0) {
   1.273 +		ctx = razor_context_create_from_file(repo_filename);
   1.274 +		razor_context_list_packages(ctx);
   1.275 +		razor_context_destroy(ctx);
   1.276 +	} else if (strcmp(argv[1], "info") == 0) {
   1.277 +		ctx = razor_context_create_from_file(repo_filename);
   1.278 +		razor_context_info(ctx);
   1.279 +		razor_context_destroy(ctx);
   1.280  	} else {
   1.281  		usage();
   1.282  	}