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",
54 "namespace:installed",
66 int count, totalsize = 0;
69 pool = (Pool *)xcalloc(1, sizeof(*pool));
71 // count number and total size of predefined strings
72 for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
73 totalsize += strlen(initpool_data[count]) + 1;
75 // alloc appropriate space
76 pool->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
77 pool->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
79 // now copy predefined strings into allocated space
81 for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
83 strcpy(pool->stringspace + pool->sstrings, initpool_data[count]);
84 pool->strings[count] = pool->sstrings;
85 pool->sstrings += strlen(initpool_data[count]) + 1;
87 pool->nstrings = count;
89 // pre-alloc space for a RelDep
90 pool->rels = (Reldep *)xcalloc(1 + REL_BLOCK, sizeof(Reldep));
93 // pre-alloc space for a Solvable
94 pool->solvables = (Solvable *)xcalloc(1, sizeof(Solvable));
104 pool_free(Pool *pool)
109 pool_freewhatprovides(pool);
110 pool_freeidhashes(pool);
111 for (i = 0; i < pool->nsources; i++)
113 source = pool->sources[i];
114 xfree(source->idarraydata);
115 xfree(source->rpmdbid);
118 xfree(pool->solvables);
119 xfree(pool->sources);
120 xfree(pool->stringspace);
121 xfree(pool->strings);
130 * create hashes over complete pool to ease lookups
135 pool_prepare(Pool *pool)
137 int i, num, np, extra;
143 Offset *whatprovides;
144 Id *whatprovidesdata, *d;
147 printf("number of solvables: %d\n", pool->nsolvables);
149 printf("number of ids: %d + %d\n", pool->nstrings, pool->nrels);
151 pool_freeidhashes(pool);
152 pool_freewhatprovides(pool);
153 num = pool->nstrings + pool->nrels;
154 whatprovides = (Offset *)xcalloc(num, sizeof(Offset));
156 /* count providers for each name */
158 for (i = 1; i < pool->nsolvables; i++) /* loop over all, but first, solvables */
161 s = pool->solvables + i;
162 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
163 continue; /* sources do not provide anything */
164 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
165 continue; /* architecture not installable */
167 if (!pp) /* solvable does not provide anything */
169 while ((id = *pp++) != ID_NULL)
173 Reldep *rd = GETRELDEP(pool, id);
176 whatprovides[id]++; /* inc count of providers */
180 off = 2; /* first entry is undef, second is empty list */
182 np = 0; /* number of names provided */
183 for (i = 0; i < num; i++, idp++)
186 if (!n) /* no providers */
188 *idp = off; /* move from counts to offsets into whatprovidesdata */
189 off += n + 1; /* make space for all providers + terminating ID_NULL */
190 np++; /* inc # of provider 'slots' */
194 printf("provide ids: %d\n", np);
195 extra = 2 * pool->nrels;
201 printf("provide space needed: %d + %d\n", off, extra);
203 /* alloc space for all providers + extra */
204 whatprovidesdata = (Id *)xcalloc(off + extra, sizeof(Id));
206 /* now fill data for all provides */
207 for (i = 1; i < pool->nsolvables; i++)
210 s = pool->solvables + i;
211 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
212 continue; /* sources do not provide anything */
213 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
214 continue; /* architecture not installable */
216 if (!pp) /* solvable does not provide anything */
219 /* for all provides of this solvable */
220 while ((id = *pp++) != 0)
224 Reldep *rd = GETRELDEP(pool, id);
227 d = whatprovidesdata + whatprovides[id]; /* offset into whatprovidesdata */
231 while (*d) /* find free slot */
236 if (pool->verbose) printf("duplicate entry for %s in package %s.%s\n", id2str(pool, id), id2str(pool, s->name), id2str(pool, s->arch));
241 *d = i; /* put solvable Id into data */
245 pool->whatprovides = whatprovides;
246 pool->whatprovidesdata = whatprovidesdata;
247 pool->whatprovidesdataoff = off;
248 pool->whatprovidesdataleft = extra;
251 /******************************************************************************/
254 * pool_queuetowhatprovides
256 * on-demand filling of provider information
257 * move queue data into whatprovidesdata
259 * returns: Offset into whatprovides
263 pool_queuetowhatprovides(Pool *pool, Queue *q)
266 int count = q->count;
268 if (count == 0) /* queue empty -> ID_EMPTY */
271 /* extend whatprovidesdata if needed, +1 for ID_NULL-termination */
272 if (pool->whatprovidesdataleft < count + 1)
275 printf("growing provides hash data...\n");
276 pool->whatprovidesdata = (Id *)xrealloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
277 pool->whatprovidesdataleft = count + 4096;
280 /* copy queue to next free slot */
281 off = pool->whatprovidesdataoff;
282 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id));
284 /* adapt count and ID_NULL-terminate */
285 pool->whatprovidesdataoff += count;
286 pool->whatprovidesdata[pool->whatprovidesdataoff++] = ID_NULL;
287 pool->whatprovidesdataleft -= count + 1;
296 * add RangeDep to whatprovides
297 * no exact providers, do range match
302 addrelproviders(Pool *pool, Id d)
304 Reldep *rd = GETRELDEP(pool, d);
310 int flags = rd->flags;
312 Id p, *pp, *pp2, *pp3;
314 d = GETRELID(pool, d);
315 queueinit_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
320 pp = GET_PROVIDESP(name, p);
321 pp2 = GET_PROVIDESP(evr, p);
322 while ((p = *pp++) != 0)
324 for (pp3 = pp2; *pp3;)
327 queuepush(&plist, p);
333 pp = GET_PROVIDESP(name, p);
334 while ((p = *pp++) != 0)
335 queuepush(&plist, p);
336 pp = GET_PROVIDESP(evr, p);
337 while ((p = *pp++) != 0)
338 queuepushunique(&plist, p);
342 /* unknown namespace, just pass through */
343 pp = GET_PROVIDESP(evr, p);
344 while ((p = *pp++) != 0)
345 queuepush(&plist, p);
352 /* convert to whatprovides id */
355 printf("addrelproviders: what provides %s?\n", id2str(pool, name));
357 if (flags && flags < 8)
359 FOR_PROVIDES(p, pp, name)
363 printf("addrelproviders: checking package %s\n", id2str(pool, pool->p[p].name));
365 /* solvable p provides name in some rels */
366 for (pidp = pool->solvables[p].provides; (pid = *pidp++) != 0; )
372 break; /* yes, provides all versions */
374 continue; /* wrong provides name */
375 prd = GETRELDEP(pool, pid);
376 if (prd->name != name)
377 continue; /* wrong provides name */
378 /* right package, both deps are rels */
382 if (flags == 7 || pflags == 7)
383 break; /* included */
384 if ((pflags & flags & 5) != 0)
385 break; /* same direction, match */
389 if ((pflags & flags & 2) != 0)
390 break; /* both have =, match */
394 int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
395 if ((f & (1 << (1 + evrcmp(pool, pevr, evr)))) != 0)
400 continue; /* no rel match */
401 queuepush(&plist, p);
404 /* add providers to whatprovides */
406 if (pool->verbose) printf("addrelproviders: adding %d packages to %d\n", plist.count, d);
408 pool->whatprovides[d] = pool_queuetowhatprovides(pool, &plist);
411 return pool->whatprovidesdata + pool->whatprovides[d];
416 * return source of solvable
421 pool_source(Pool *pool, Solvable *s)
425 int off = s - pool->solvables;
427 for (i = 0; i < pool->nsources; i++)
429 source = pool->sources[i];
430 if (off >= source->start
431 && off < source->start+source->nsolvables)