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;
203 int idsizes[RPM_RPMDBID + 1];
208 idarraydata = repo->idarraydata;
210 needid = (NeedId *)calloc(pool->ss.nstrings + pool->nrels, sizeof(*needid));
212 memset(idsizes, 0, sizeof(idsizes));
214 for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
219 needid[s->name].need++;
220 needid[s->arch].need++;
221 needid[s->evr].need++;
224 needid[s->vendor].need++;
225 idsizes[SOLVABLE_VENDOR] = 1;
228 idsizes[SOLVABLE_PROVIDES] += incneedid(pool, idarraydata + s->provides, needid);
230 idsizes[SOLVABLE_REQUIRES] += incneedid(pool, idarraydata + s->requires, needid);
232 idsizes[SOLVABLE_CONFLICTS] += incneedid(pool, idarraydata + s->conflicts, needid);
234 idsizes[SOLVABLE_OBSOLETES] += incneedid(pool, idarraydata + s->obsoletes, needid);
236 idsizes[SOLVABLE_RECOMMENDS] += incneedid(pool, idarraydata + s->recommends, needid);
238 idsizes[SOLVABLE_SUGGESTS] += incneedid(pool, idarraydata + s->suggests, needid);
240 idsizes[SOLVABLE_SUPPLEMENTS] += incneedid(pool, idarraydata + s->supplements, needid);
242 idsizes[SOLVABLE_ENHANCES] += incneedid(pool, idarraydata + s->enhances, needid);
244 idsizes[SOLVABLE_FRESHENS] += incneedid(pool, idarraydata + s->freshens, needid);
246 if (nsolvables != repo->nsolvables)
249 idsizes[SOLVABLE_NAME] = 1;
250 idsizes[SOLVABLE_ARCH] = 1;
251 idsizes[SOLVABLE_EVR] = 1;
253 idsizes[RPM_RPMDBID] = 1;
255 for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++)
262 needid[pool->ss.nstrings].need = 0;
263 for (i = 0; i < pool->ss.nstrings + pool->nrels; i++)
266 qsort(needid + 1, pool->ss.nstrings - 1, sizeof(*needid), needid_cmp_need);
267 qsort(needid + pool->ss.nstrings, pool->nrels, sizeof(*needid), needid_cmp_need);
270 for (i = 1; i < pool->ss.nstrings; i++)
275 sizeid += strlen(pool->ss.stringspace + pool->ss.strings[needid[i].map]) + 1;
279 for (i = 0; i < nstrings; i++)
280 needid[needid[i].map].need = i;
282 for (i = 0; i < pool->nrels; i++)
284 if (!needid[pool->ss.nstrings + i].need)
287 needid[pool->ss.nstrings + i].need = 0;
291 for (i = 0; i < nrels; i++)
293 needid[needid[pool->ss.nstrings + i].map].need = nstrings + i;
296 /* write file header */
297 write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
298 write_u32(fp, SOLV_VERSION);
301 write_u32(fp, nstrings);
302 write_u32(fp, nrels);
303 write_u32(fp, nsolvables);
304 write_u32(fp, sizeid);
309 for (i = 1; i < nstrings; i++)
311 char *str = pool->ss.stringspace + pool->ss.strings[needid[i].map];
312 if (fwrite(str, strlen(str) + 1, 1, fp) != 1)
314 perror("write error");
322 for (i = 0; i < nrels; i++)
324 ran = pool->rels + (needid[pool->ss.nstrings + i].map - pool->ss.nstrings);
325 write_id(fp, needid[ISRELDEP(ran->name) ? GETRELID(pool, ran->name) : ran->name].need);
326 write_id(fp, needid[ISRELDEP(ran->evr) ? GETRELID(pool, ran->evr) : ran->evr].need);
327 write_u8( fp, ran->flags);
330 write_u32(fp, 0); /* no repo data */
337 for (i = SOLVABLE_NAME; i <= RPM_RPMDBID; i++)
342 write_u32(fp, (unsigned int)numsolvdata);
345 for (i = SOLVABLE_NAME; i <= SOLVABLE_FRESHENS; i++)
349 if (i >= SOLVABLE_PROVIDES && i <= SOLVABLE_FRESHENS)
351 write_u8(fp, TYPE_IDARRAY|TYPE_BITMAP);
355 write_u8(fp, TYPE_ID);
356 write_id(fp, needid[i].need);
357 if (i >= SOLVABLE_PROVIDES && i <= SOLVABLE_FRESHENS)
358 write_u32(fp, idsizes[i]);
365 write_u8(fp, TYPE_U32);
366 write_id(fp, needid[RPM_RPMDBID].need);
370 for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
375 if (idsizes[SOLVABLE_FRESHENS])
376 bits = (bits << 1) | (s->freshens ? 1 : 0);
377 if (idsizes[SOLVABLE_ENHANCES])
378 bits = (bits << 1) | (s->enhances ? 1 : 0);
379 if (idsizes[SOLVABLE_SUPPLEMENTS])
380 bits = (bits << 1) | (s->supplements ? 1 : 0);
381 if (idsizes[SOLVABLE_SUGGESTS])
382 bits = (bits << 1) | (s->suggests ? 1 : 0);
383 if (idsizes[SOLVABLE_RECOMMENDS])
384 bits = (bits << 1) | (s->recommends ? 1 : 0);
385 if (idsizes[SOLVABLE_REQUIRES])
386 bits = (bits << 1) | (s->requires ? 1 : 0);
387 if (idsizes[SOLVABLE_CONFLICTS])
388 bits = (bits << 1) | (s->conflicts ? 1 : 0);
389 if (idsizes[SOLVABLE_OBSOLETES])
390 bits = (bits << 1) | (s->obsoletes ? 1 : 0);
391 if (idsizes[SOLVABLE_PROVIDES])
392 bits = (bits << 1) | (s->provides ? 1 : 0);
395 write_u8(fp, bits >> 24);
397 write_u8(fp, bits >> 16);
399 write_u8(fp, bits >> 8);
403 write_id(fp, needid[s->name].need);
404 write_id(fp, needid[s->arch].need);
405 write_id(fp, needid[s->evr].need);
406 if (idsizes[SOLVABLE_VENDOR])
407 write_id(fp, needid[s->vendor].need);
410 write_idarray(fp, pool, needid, idarraydata + s->provides);
412 write_idarray(fp, pool, needid, idarraydata + s->obsoletes);
414 write_idarray(fp, pool, needid, idarraydata + s->conflicts);
416 write_idarray(fp, pool, needid, idarraydata + s->requires);
418 write_idarray(fp, pool, needid, idarraydata + s->recommends);
420 write_idarray(fp, pool, needid, idarraydata + s->suggests);
422 write_idarray(fp, pool, needid, idarraydata + s->supplements);
424 write_idarray(fp, pool, needid, idarraydata + s->enhances);
426 write_idarray(fp, pool, needid, idarraydata + s->freshens);
428 write_u32(fp, repo->rpmdbid[i - repo->start]);