4 * The pool contains information about solvables
5 * stored optimized for memory consumption and fast retrieval.
15 #include "poolid_private.h"
21 // reset all whatprovides
24 pool_freewhatprovides(Pool *pool)
26 pool->whatprovides = xfree(pool->whatprovides);
27 pool->whatprovidesdata = xfree(pool->whatprovidesdata);
28 pool->whatprovidesdataoff = 0;
29 pool->whatprovidesdataleft = 0;
33 // list of string constants, so we can do pointer/Id instead of string comparison
34 // index into array matches ID_xxx constants in pool.h
36 static char *initpool_data[] = {
46 "solvable:recommends",
48 "solvable:supplements",
51 "rpm:dbid", /* direct key into rpmdb */
52 "solvable:prereqmarker",
53 "solvable:filemarker",
64 int count, totalsize = 0;
67 pool = (Pool *)xcalloc(1, sizeof(*pool));
69 // count number and total size of predefined strings
70 for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
71 totalsize += strlen(initpool_data[count]) + 1;
73 // alloc appropriate space
74 pool->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
75 pool->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
77 // now copy predefined strings into allocated space
79 for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
81 strcpy(pool->stringspace + pool->sstrings, initpool_data[count]);
82 pool->strings[count] = pool->sstrings;
83 pool->sstrings += strlen(initpool_data[count]) + 1;
85 pool->nstrings = count;
87 // pre-alloc space for a RelDep
88 pool->rels = (Reldep *)xcalloc(1 + REL_BLOCK, sizeof(Reldep));
91 // pre-alloc space for a Solvable
92 pool->solvables = (Solvable *)xcalloc(1, sizeof(Solvable));
102 pool_free(Pool *pool)
107 pool_freewhatprovides(pool);
108 pool_freeidhashes(pool);
109 for (i = 0; i < pool->nsources; i++)
111 source = pool->sources[i];
112 xfree(source->idarraydata);
113 xfree(source->rpmdbid);
116 xfree(pool->solvables);
117 xfree(pool->sources);
118 xfree(pool->stringspace);
119 xfree(pool->strings);
128 * create hashes over complete pool to ease lookups
133 pool_prepare(Pool *pool)
135 int i, num, np, extra;
141 Offset *whatprovides;
142 Id *whatprovidesdata, *d;
145 printf("number of solvables: %d\n", pool->nsolvables);
147 printf("number of ids: %d + %d\n", pool->nstrings, pool->nrels);
149 pool_freeidhashes(pool);
150 pool_freewhatprovides(pool);
151 num = pool->nstrings + pool->nrels;
152 whatprovides = (Offset *)xcalloc(num, sizeof(Offset));
154 /* count providers for each name */
156 for (i = 1; i < pool->nsolvables; i++) /* loop over all, but first, solvables */
159 s = pool->solvables + i;
160 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
161 continue; /* sources do not provide anything */
162 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
163 continue; /* architecture not installable */
165 if (!pp) /* solvable does not provide anything */
167 while ((id = *pp++) != ID_NULL)
171 Reldep *rd = GETRELDEP(pool, id);
174 whatprovides[id]++; /* inc count of providers */
178 off = 2; /* first entry is undef, second is empty list */
180 np = 0; /* number of names provided */
181 for (i = 0; i < num; i++, idp++)
184 if (!n) /* no providers */
186 *idp = off; /* move from counts to offsets into whatprovidesdata */
187 off += n + 1; /* make space for all providers + terminating ID_NULL */
188 np++; /* inc # of provider 'slots' */
192 printf("provide ids: %d\n", np);
193 extra = 2 * pool->nrels;
199 printf("provide space needed: %d + %d\n", off, extra);
201 /* alloc space for all providers + extra */
202 whatprovidesdata = (Id *)xcalloc(off + extra, sizeof(Id));
204 /* now fill data for all provides */
205 for (i = 1; i < pool->nsolvables; i++)
208 s = pool->solvables + i;
209 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
210 continue; /* sources do not provide anything */
211 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
212 continue; /* architecture not installable */
214 if (!pp) /* solvable does not provide anything */
217 /* for all provides of this solvable */
218 while ((id = *pp++) != 0)
222 Reldep *rd = GETRELDEP(pool, id);
225 d = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */
229 while (*d) /* find free slot */
234 if (pool->verbose) printf("duplicate entry for %s in package %s.%s\n", id2str(pool, id), id2str(pool, s->name), id2str(pool, s->arch));
239 *d = i; /* put solvable Id into data */
243 pool->whatprovides = whatprovides;
244 pool->whatprovidesdata = whatprovidesdata;
245 pool->whatprovidesdataoff = off;
246 pool->whatprovidesdataleft = extra;
249 /******************************************************************************/
252 * pool_queuetowhatprovides
254 * on-demand filling of provider information
255 * move queue data into whatprovidesdata
257 * returns: Offset into whatprovides
261 pool_queuetowhatprovides(Pool *pool, Queue *q)
264 int count = q->count;
266 if (count == 0) /* queue empty -> ID_EMPTY */
269 /* extend whatprovidesdata if needed, +1 for ID_NULL-termination */
270 if (pool->whatprovidesdataleft < count + 1)
273 printf("growing provides hash data...\n");
274 pool->whatprovidesdata = (Id *)xrealloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
275 pool->whatprovidesdataleft = count + 4096;
278 /* copy queue to next free slot */
279 off = pool->whatprovidesdataoff;
280 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id));
282 /* adapt count and ID_NULL-terminate */
283 pool->whatprovidesdataoff += count;
284 pool->whatprovidesdata[pool->whatprovidesdataoff++] = ID_NULL;
285 pool->whatprovidesdataleft -= count + 1;
294 * add RangeDep to whatprovides
295 * no exact providers, do range match
300 addrelproviders(Pool *pool, Id d)
302 Reldep *rd = GETRELDEP(pool, d);
308 int flags = rd->flags;
310 Id p, *pp, *pp2, *pp3;
312 d = GETRELID(pool, d);
313 queueinit_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
318 pp = GET_PROVIDESP(name, p);
319 pp2 = GET_PROVIDESP(evr, p);
320 while ((p = *pp++) != 0)
322 for (pp3 = pp2; *pp3;)
325 queuepush(&plist, p);
331 pp = GET_PROVIDESP(name, p);
332 while ((p = *pp++) != 0)
333 queuepush(&plist, p);
334 pp = GET_PROVIDESP(evr, p);
335 while ((p = *pp++) != 0)
336 queuepushunique(&plist, p);
340 /* unknown namespace, just pass through */
341 pp = GET_PROVIDESP(evr, p);
342 while ((p = *pp++) != 0)
343 queuepush(&plist, p);
350 /* convert to whatprovides id */
353 printf("addrelproviders: what provides %s?\n", id2str(pool, name));
355 if (flags && flags < 8)
357 FOR_PROVIDES(p, pp, name)
361 printf("addrelproviders: checking package %s\n", id2str(pool, pool->p[p].name));
363 /* solvable p provides name in some rels */
364 for (pidp = pool->solvables[p].provides; (pid = *pidp++) != 0; )
370 break; /* yes, provides all versions */
372 continue; /* wrong provides name */
373 prd = GETRELDEP(pool, pid);
374 if (prd->name != name)
375 continue; /* wrong provides name */
376 /* right package, both deps are rels */
380 if (flags == 7 || pflags == 7)
381 break; /* included */
382 if ((pflags & flags & 5) != 0)
383 break; /* same direction, match */
387 if ((pflags & flags & 2) != 0)
388 break; /* both have =, match */
392 int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
393 if ((f & (1 << (1 + evrcmp(pool, pevr, evr)))) != 0)
398 continue; /* no rel match */
399 queuepush(&plist, p);
402 /* add providers to whatprovides */
404 if (pool->verbose) printf("addrelproviders: adding %d packages to %d\n", plist.count, d);
406 pool->whatprovides[d] = pool_queuetowhatprovides(pool, &plist);
409 return pool->whatprovidesdata + pool->whatprovides[d];
414 * return source of solvable
419 pool_source(Pool *pool, Solvable *s)
423 int off = s - pool->solvables;
425 for (i = 0; i < pool->nsources; i++)
427 source = pool->sources[i];
428 if (off >= source->start
429 && off < source->start+source->nsolvables)