2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Write Repo data out to binary file
13 * See doc/README.format for a description
14 * of the binary file format
18 #include <sys/types.h>
26 #include "repo_write.h"
28 /*------------------------------------------------------------------*/
29 /* Id map optimizations */
31 typedef struct needid {
38 * idarray: array of Ids, ID_NULL terminated
39 * needid: array of Id->NeedId
46 incneedid(Pool *pool, Id *idarray, NeedId *needid)
54 while ((id = *idarray++) != 0)
59 Reldep *rd = GETRELDEP(pool, id);
60 needid[GETRELID(pool, id)].need++;
61 if (ISRELDEP(rd->evr))
66 incneedid(pool, ida, needid);
69 needid[rd->evr].need++;
83 needid_cmp_need(const void *ap, const void *bp)
88 r = b->need - a->need;
91 return a->map - b->map;
95 /*------------------------------------------------------------------*/
103 write_u32(FILE *fp, unsigned int x)
105 if (putc(x >> 24, fp) == EOF ||
106 putc(x >> 16, fp) == EOF ||
107 putc(x >> 8, fp) == EOF ||
110 perror("write error");
121 write_u8(FILE *fp, unsigned int x)
123 if (putc(x, fp) == EOF)
125 perror("write error");
136 write_id(FILE *fp, Id x)
141 putc((x >> 28) | 128, fp);
143 putc((x >> 21) | 128, fp);
144 putc((x >> 14) | 128, fp);
147 putc((x >> 7) | 128, fp);
148 if (putc(x & 127, fp) == EOF)
150 perror("write error");
161 write_idarray(FILE *fp, Pool *pool, NeedId *needid, Id *ids)
168 write_u8(fp, ID_NULL);
174 id = needid[ISRELDEP(id) ? GETRELID(pool, id) : id].need;
176 id = (id & 63) | ((id & ~63) << 1);
182 write_id(fp, id | 64);
192 repo_write(Repo *repo, FILE *fp)
194 Pool *pool = repo->pool;
196 Solvable *s, *sstart;
203 int idsizes[RPM_RPMDBID + 1];
207 nsolvables = repo->nsolvables;
208 sstart = pool->solvables + repo->start;
209 idarraydata = repo->idarraydata;
211 needid = (NeedId *)calloc(pool->nstrings + pool->nrels, sizeof(*needid));
213 memset(idsizes, 0, sizeof(idsizes));
215 for (i = 0; i < nsolvables; i++)
218 needid[s->name].need++;
219 needid[s->arch].need++;
220 needid[s->evr].need++;
223 needid[s->vendor].need++;
224 idsizes[SOLVABLE_VENDOR] = 1;
227 idsizes[SOLVABLE_PROVIDES] += incneedid(pool, idarraydata + s->provides, needid);
229 idsizes[SOLVABLE_REQUIRES] += incneedid(pool, idarraydata + s->requires, needid);
231 idsizes[SOLVABLE_CONFLICTS] += incneedid(pool, idarraydata + s->conflicts, needid);
233 idsizes[SOLVABLE_OBSOLETES] += incneedid(pool, idarraydata + s->obsoletes, needid);
235 idsizes[SOLVABLE_RECOMMENDS] += incneedid(pool, idarraydata + s->recommends, needid);
237 idsizes[SOLVABLE_SUGGESTS] += incneedid(pool, idarraydata + s->suggests, needid);
239 idsizes[SOLVABLE_SUPPLEMENTS] += incneedid(pool, idarraydata + s->supplements, needid);
241 idsizes[SOLVABLE_ENHANCES] += incneedid(pool, idarraydata + s->enhances, needid);
243 idsizes[SOLVABLE_FRESHENS] += incneedid(pool, idarraydata + s->freshens, needid);
246 idsizes[SOLVABLE_NAME] = 1;
247 idsizes[SOLVABLE_ARCH] = 1;
248 idsizes[SOLVABLE_EVR] = 1;
250 idsizes[RPM_RPMDBID] = 1;
252 for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++)
259 needid[pool->nstrings].need = 0;
260 for (i = 0; i < pool->nstrings + pool->nrels; i++)
263 qsort(needid + 1, pool->nstrings - 1, sizeof(*needid), needid_cmp_need);
264 qsort(needid + pool->nstrings, pool->nrels, sizeof(*needid), needid_cmp_need);
267 for (i = 1; i < pool->nstrings; i++)
272 sizeid += strlen(pool->stringspace + pool->strings[needid[i].map]) + 1;
276 for (i = 0; i < nstrings; i++)
277 needid[needid[i].map].need = i;
279 for (i = 0; i < pool->nrels; i++)
281 if (!needid[pool->nstrings + i].need)
284 needid[pool->nstrings + i].need = 0;
288 for (i = 0; i < nrels; i++)
290 needid[needid[pool->nstrings + i].map].need = nstrings + i;
293 /* write file header */
294 write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
295 write_u32(fp, SOLV_VERSION);
298 write_u32(fp, nstrings);
299 write_u32(fp, nrels);
300 write_u32(fp, nsolvables);
301 write_u32(fp, sizeid);
306 for (i = 1; i < nstrings; i++)
308 char *str = pool->stringspace + pool->strings[needid[i].map];
309 if (fwrite(str, strlen(str) + 1, 1, fp) != 1)
311 perror("write error");
319 for (i = 0; i < nrels; i++)
321 ran = pool->rels + (needid[pool->nstrings + i].map - pool->nstrings);
322 write_id(fp, needid[ISRELDEP(ran->name) ? GETRELID(pool, ran->name) : ran->name].need);
323 write_id(fp, needid[ISRELDEP(ran->evr) ? GETRELID(pool, ran->evr) : ran->evr].need);
324 write_u8( fp, ran->flags);
327 write_u32(fp, 0); /* no repo data */
334 for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++)
339 write_u32(fp, (unsigned int)numsolvdata);
342 for (i = SOLVABLE_NAME; i <= SOLVABLE_FRESHENS; i++)
346 if (i >= SOLVABLE_PROVIDES && i <= SOLVABLE_FRESHENS)
348 write_u8(fp, TYPE_IDARRAY|TYPE_BITMAP);
352 write_u8(fp, TYPE_ID);
353 write_id(fp, needid[i].need);
354 if (i >= SOLVABLE_PROVIDES && i <= SOLVABLE_FRESHENS)
355 write_u32(fp, idsizes[i]);
362 write_u8(fp, TYPE_U32);
363 write_id(fp, needid[RPM_RPMDBID].need);
367 for (i = 0; i < nsolvables; ++i)
371 if (idsizes[SOLVABLE_FRESHENS])
372 bits = (bits << 1) | (s->freshens ? 1 : 0);
373 if (idsizes[SOLVABLE_ENHANCES])
374 bits = (bits << 1) | (s->enhances ? 1 : 0);
375 if (idsizes[SOLVABLE_SUPPLEMENTS])
376 bits = (bits << 1) | (s->supplements ? 1 : 0);
377 if (idsizes[SOLVABLE_SUGGESTS])
378 bits = (bits << 1) | (s->suggests ? 1 : 0);
379 if (idsizes[SOLVABLE_RECOMMENDS])
380 bits = (bits << 1) | (s->recommends ? 1 : 0);
381 if (idsizes[SOLVABLE_REQUIRES])
382 bits = (bits << 1) | (s->requires ? 1 : 0);
383 if (idsizes[SOLVABLE_CONFLICTS])
384 bits = (bits << 1) | (s->conflicts ? 1 : 0);
385 if (idsizes[SOLVABLE_OBSOLETES])
386 bits = (bits << 1) | (s->obsoletes ? 1 : 0);
387 if (idsizes[SOLVABLE_PROVIDES])
388 bits = (bits << 1) | (s->provides ? 1 : 0);
391 write_u8(fp, bits >> 24);
393 write_u8(fp, bits >> 16);
395 write_u8(fp, bits >> 8);
399 write_id(fp, needid[s->name].need);
400 write_id(fp, needid[s->arch].need);
401 write_id(fp, needid[s->evr].need);
402 if (idsizes[SOLVABLE_VENDOR])
403 write_id(fp, needid[s->vendor].need);
406 write_idarray(fp, pool, needid, idarraydata + s->provides);
408 write_idarray(fp, pool, needid, idarraydata + s->obsoletes);
410 write_idarray(fp, pool, needid, idarraydata + s->conflicts);
412 write_idarray(fp, pool, needid, idarraydata + s->requires);
414 write_idarray(fp, pool, needid, idarraydata + s->recommends);
416 write_idarray(fp, pool, needid, idarraydata + s->suggests);
418 write_idarray(fp, pool, needid, idarraydata + s->supplements);
420 write_idarray(fp, pool, needid, idarraydata + s->enhances);
422 write_idarray(fp, pool, needid, idarraydata + s->freshens);
424 write_u32(fp, repo->rpmdbid[i]);