Clean up the merging code a bit.
authorKristian H?gsberg <krh@redhat.com>
Mon Nov 12 00:05:03 2007 -0500 (2007-11-12)
changeset 799f302fa29d83
parent 78 89c06e68824a
child 80 72671f8e5741
Clean up the merging code a bit.

Use the hashtable instead of reusing razor_importer for this.
Introduce struct razor_merger for this. All this is steps
towards making the merging policy external to the core razor_set code.
razor.c
     1.1 --- a/razor.c	Sun Nov 11 14:57:42 2007 -0500
     1.2 +++ b/razor.c	Mon Nov 12 00:05:03 2007 -0500
     1.3 @@ -407,18 +407,24 @@
     1.4  }
     1.5  
     1.6  static unsigned long
     1.7 -razor_importer_tokenize(struct razor_importer *importer, const char *string)
     1.8 +hashtable_tokenize(struct hashtable *table, const char *string)
     1.9  {
    1.10  	unsigned long token;
    1.11  
    1.12  	if (string == NULL)
    1.13  		string = "";
    1.14  
    1.15 -	token = hashtable_lookup(&importer->table, string);
    1.16 +	token = hashtable_lookup(table, string);
    1.17  	if (token != 0)
    1.18  		return token;
    1.19  
    1.20 -	return hashtable_insert(&importer->table, string);
    1.21 +	return hashtable_insert(table, string);
    1.22 +}
    1.23 +
    1.24 +static unsigned long
    1.25 +razor_importer_tokenize(struct razor_importer *importer, const char *string)
    1.26 +{
    1.27 +	return hashtable_tokenize(&importer->table, string);
    1.28  }
    1.29  
    1.30  void
    1.31 @@ -1357,21 +1363,39 @@
    1.32  	unsigned long *property_map;
    1.33  };
    1.34  
    1.35 -static void
    1.36 -prepare_source(struct source *source, struct razor_set *set)
    1.37 +struct razor_merger {
    1.38 +	struct razor_set *set;
    1.39 +	struct hashtable table;
    1.40 +	struct source source1;
    1.41 +	struct source source2;
    1.42 +};
    1.43 +
    1.44 +static struct razor_merger *
    1.45 +razor_merger_create(struct razor_set *set1, struct razor_set *set2)
    1.46  {
    1.47 +	struct razor_merger *merger;
    1.48  	int count;
    1.49  	size_t size;
    1.50  
    1.51 -	source->set = set;
    1.52 +	merger = zalloc(sizeof *merger);
    1.53 +	merger->set = razor_set_create();
    1.54 +	hashtable_init(&merger->table, &merger->set->string_pool);
    1.55  
    1.56 -	count = set->properties.size / sizeof (struct razor_property);
    1.57 -	size = count * sizeof *source->property_map;
    1.58 -	source->property_map = zalloc(size);
    1.59 +	count = set1->properties.size / sizeof (struct razor_property);
    1.60 +	size = count * sizeof merger->source1.property_map[0];
    1.61 +	merger->source1.property_map = zalloc(size);
    1.62 +	merger->source1.set = set1;
    1.63 +
    1.64 +	count = set2->properties.size / sizeof (struct razor_property);
    1.65 +	size = count * sizeof merger->source2.property_map[0];
    1.66 +	merger->source2.property_map = zalloc(size);
    1.67 +	merger->source2.set = set2;
    1.68 +
    1.69 +	return merger;
    1.70  }
    1.71  
    1.72  static void
    1.73 -add_package(struct razor_importer *importer,
    1.74 +add_package(struct razor_merger *merger,
    1.75  	    struct razor_package *package, struct source *source,
    1.76  	    unsigned long flags)
    1.77  {
    1.78 @@ -1380,11 +1404,11 @@
    1.79  	struct razor_package *p;
    1.80  
    1.81  	pool = source->set->string_pool.data;
    1.82 -	p = array_add(&importer->set->packages, sizeof *p);
    1.83 -	p->name = razor_importer_tokenize(importer, &pool[package->name]);
    1.84 +	p = array_add(&merger->set->packages, sizeof *p);
    1.85 +	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
    1.86  	p->name |= flags;
    1.87 -	p->version = razor_importer_tokenize(importer,
    1.88 -					     &pool[package->version]);
    1.89 +	p->version = hashtable_tokenize(&merger->table,
    1.90 +					&pool[package->version]);
    1.91  	p->properties = package->properties;
    1.92  
    1.93  	if (package->properties & RAZOR_IMMEDIATE)
    1.94 @@ -1401,18 +1425,18 @@
    1.95  
    1.96  
    1.97  /* Build the new package list sorted by merging the two package lists.
    1.98 - * Build new string pool as we go. (for now we just re-use that part of
    1.99 - * the importer). */
   1.100 + * Build new string pool as we go. */
   1.101  static void
   1.102 -merge_packages(struct razor_importer *importer,
   1.103 -	       struct source *source1, struct source *source2,
   1.104 -	       struct array *packages)
   1.105 +merge_packages(struct razor_merger *merger, struct array *packages)
   1.106  {
   1.107  	struct razor_package *upstream_packages, *p, *s, *send;
   1.108 +	struct source *source1, *source2;
   1.109  	char *spool, *upool;
   1.110  	unsigned long *u, *uend;
   1.111  	int cmp;
   1.112  
   1.113 +	source1 = &merger->source1;
   1.114 +	source2 = &merger->source2;
   1.115  	upstream_packages = source2->set->packages.data;
   1.116  
   1.117  	u = packages->data;
   1.118 @@ -1429,43 +1453,46 @@
   1.119  		if (u < uend)
   1.120  			cmp = strcmp(&spool[s->name], &upool[p->name]);
   1.121  		if (u >= uend || cmp < 0) {
   1.122 -			add_package(importer, s, source1, 0);
   1.123 +			add_package(merger, s, source1, 0);
   1.124  			s++;
   1.125  		} else if (cmp == 0) {
   1.126 -			add_package(importer, p, source2, UPSTREAM_SOURCE);
   1.127 +			add_package(merger, p, source2, UPSTREAM_SOURCE);
   1.128  			s++;
   1.129  			u++;
   1.130  		} else {
   1.131 -			add_package(importer, p, source2, UPSTREAM_SOURCE);
   1.132 +			add_package(merger, p, source2, UPSTREAM_SOURCE);
   1.133  			u++;
   1.134  		}
   1.135  	}
   1.136  }
   1.137  
   1.138  static unsigned long
   1.139 -add_property(struct razor_importer *importer,
   1.140 +add_property(struct razor_merger *merger,
   1.141  	     const char *name, const char *version, int type)
   1.142  {
   1.143  	struct razor_property *p;
   1.144  
   1.145 -	p = array_add(&importer->set->properties, sizeof *p);
   1.146 -	p->name = razor_importer_tokenize(importer, name) | (type << 30);
   1.147 -	p->version = razor_importer_tokenize(importer, version);
   1.148 +	p = array_add(&merger->set->properties, sizeof *p);
   1.149 +	p->name = hashtable_tokenize(&merger->table, name) | (type << 30);
   1.150 +	p->version = hashtable_tokenize(&merger->table, version);
   1.151  
   1.152 -	return p - (struct razor_property *) importer->set->properties.data;
   1.153 +	return p - (struct razor_property *) merger->set->properties.data;
   1.154  }
   1.155  
   1.156  static void
   1.157 -merge_properties(struct razor_importer *importer,
   1.158 -		 struct razor_set *set1,
   1.159 -		 unsigned long *map1,
   1.160 -		 struct razor_set *set2,
   1.161 -		 unsigned long *map2)
   1.162 +merge_properties(struct razor_merger *merger)
   1.163  {
   1.164  	struct razor_property *p1, *p2;
   1.165 +	struct razor_set *set1, *set2;
   1.166 +	unsigned long *map1, *map2;
   1.167  	int i, j, cmp, count1, count2;
   1.168  	char *pool1, *pool2;
   1.169  
   1.170 +	set1 = merger->source1.set;
   1.171 +	set2 = merger->source2.set;
   1.172 +	map1 = merger->source1.property_map;
   1.173 +	map2 = merger->source2.property_map;
   1.174 +
   1.175  	i = 0;
   1.176  	j = 0;
   1.177  	pool1 = set1->string_pool.data;
   1.178 @@ -1495,17 +1522,17 @@
   1.179  			cmp = versioncmp(&pool1[p1->version],
   1.180  					 &pool2[p2->version]);
   1.181  		if (cmp < 0) {
   1.182 -			map1[i++] = add_property(importer,
   1.183 +			map1[i++] = add_property(merger,
   1.184  						 &pool1[p1->name & RAZOR_ENTRY_MASK],
   1.185  						 &pool1[p1->version],
   1.186  						 (p1->name >> 30));
   1.187  		} else if (cmp > 0) {
   1.188 -			map2[j++] = add_property(importer,
   1.189 +			map2[j++] = add_property(merger,
   1.190  						 &pool2[p2->name & RAZOR_ENTRY_MASK],
   1.191  						 &pool2[p2->version],
   1.192  						 (p2->name >> 30));
   1.193  		} else  {
   1.194 -			map1[i++] = map2[j++] = add_property(importer,
   1.195 +			map1[i++] = map2[j++] = add_property(merger,
   1.196  							     &pool1[p1->name & RAZOR_ENTRY_MASK],
   1.197  							     &pool1[p1->version],
   1.198  							     (p1->name >> 30));
   1.199 @@ -1573,6 +1600,18 @@
   1.200  	free(pkgs);
   1.201  }
   1.202  
   1.203 +struct razor_set *
   1.204 +razor_merger_finish(struct razor_merger *merger)
   1.205 +{
   1.206 +	struct razor_set *result;
   1.207 +
   1.208 +	result = merger->set;
   1.209 +	hashtable_release(&merger->table);
   1.210 +	free(merger);
   1.211 +
   1.212 +	return result;
   1.213 +}
   1.214 +
   1.215  /* Add packages from 'upstream' to 'set'.  The packages to add are
   1.216   * specified by the 'packages' array, which is a sorted list of
   1.217   * package indexes.  Returns a newly allocated package set.  Does not
   1.218 @@ -1587,17 +1626,12 @@
   1.219  razor_set_add(struct razor_set *set, struct razor_set *upstream,
   1.220  	      struct array *packages)
   1.221  {
   1.222 -	struct razor_set *result;
   1.223 -	struct razor_importer *importer;
   1.224 +	struct razor_merger *merger;
   1.225  	struct razor_package *p, *pend;
   1.226 -	struct source source, upstream_source;
   1.227  
   1.228 -	importer = razor_importer_new();
   1.229 +	merger = razor_merger_create(set, upstream);
   1.230  
   1.231 -	prepare_source(&upstream_source, upstream);
   1.232 -	prepare_source(&source, set);
   1.233 -
   1.234 -	merge_packages(importer, &source, &upstream_source, packages);
   1.235 +	merge_packages(merger, packages);
   1.236  
   1.237  	/* As we built the package list, we filled out a bitvector of
   1.238  	 * the properties that are referenced by the packages in the
   1.239 @@ -1607,36 +1641,30 @@
   1.240  	 * indices in the old property list to indices in the new
   1.241  	 * property list for both sets. */
   1.242  
   1.243 -	merge_properties(importer,
   1.244 -			 set, source.property_map,
   1.245 -			 upstream, upstream_source.property_map);
   1.246 +	merge_properties(merger);
   1.247  
   1.248  	/* Now we loop through the packages again and emit the
   1.249  	 * property lists, remapped to point to the new properties. */
   1.250  
   1.251 -	pend = importer->set->packages.data + importer->set->packages.size;
   1.252 -	for (p = importer->set->packages.data; p < pend; p++) {
   1.253 +	pend = merger->set->packages.data + merger->set->packages.size;
   1.254 +	for (p = merger->set->packages.data; p < pend; p++) {
   1.255  		struct source *src;
   1.256  
   1.257  		if (p->name & UPSTREAM_SOURCE)
   1.258 -			src = &upstream_source;
   1.259 +			src = &merger->source2;
   1.260  		else
   1.261 -			src = &source;
   1.262 +			src = &merger->source1;
   1.263  
   1.264  		p->properties = emit_properties(&src->set->property_pool,
   1.265  						p->properties,
   1.266  						src->property_map,
   1.267 -						&importer->set->property_pool);
   1.268 +						&merger->set->property_pool);
   1.269  		p->name &= INDEX_MASK;
   1.270  	}
   1.271  
   1.272 -	rebuild_package_lists(importer->set);
   1.273 +	rebuild_package_lists(merger->set);
   1.274  
   1.275 -	result = importer->set;
   1.276 -	hashtable_release(&importer->table);
   1.277 -	free(importer);
   1.278 -
   1.279 -	return result;
   1.280 +	return razor_merger_finish(merger);
   1.281  }
   1.282  
   1.283  void