2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage data coming from one repository
13 * a repository can contain multiple repodata entries, consisting of
14 * different sets of keys and different sets of solvables
29 #include "poolid_private.h"
35 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
36 unsigned char *out, unsigned int out_len);
37 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
40 unsigned int out_len);
42 #define REPODATA_BLOCK 255
46 repodata_init(Repodata *data, Repo *repo, int localpool)
48 memset(data, 0, sizeof (*data));
50 data->localpool = localpool;
52 stringpool_init_empty(&data->spool);
53 data->keys = sat_calloc(1, sizeof(Repokey));
55 data->schemata = sat_calloc(1, sizeof(Id));
56 data->schemadata = sat_calloc(1, sizeof(Id));
58 data->schemadatalen = 1;
59 repopagestore_init(&data->store);
63 repodata_free(Repodata *data)
69 sat_free(data->schemata);
70 sat_free(data->schemadata);
71 sat_free(data->schematahash);
73 stringpool_free(&data->spool);
74 dirpool_free(&data->dirpool);
76 sat_free(data->mainschemaoffsets);
77 sat_free(data->incoredata);
78 sat_free(data->incoreoffset);
79 sat_free(data->verticaloffset);
81 repopagestore_free(&data->store);
83 sat_free(data->vincore);
86 for (i = 0; i < data->end - data->start; i++)
87 sat_free(data->attrs[i]);
88 sat_free(data->attrs);
90 for (i = 0; i < data->nxattrs; i++)
91 sat_free(data->xattrs[i]);
92 sat_free(data->xattrs);
94 sat_free(data->attrdata);
95 sat_free(data->attriddata);
99 /***************************************************************
100 * key pool management
103 /* this is not so time critical that we need a hash, so we do a simple
106 repodata_key2id(Repodata *data, Repokey *key, int create)
110 for (keyid = 1; keyid < data->nkeys; keyid++)
111 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
113 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
117 if (keyid == data->nkeys)
121 /* allocate new key */
122 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
123 data->keys[data->nkeys++] = *key;
124 if (data->verticaloffset)
126 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
127 data->verticaloffset[data->nkeys - 1] = 0;
129 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
135 /***************************************************************
136 * schema pool management
139 #define SCHEMATA_BLOCK 31
140 #define SCHEMATADATA_BLOCK 255
143 repodata_schema2id(Repodata *data, Id *schema, int create)
149 if ((schematahash = data->schematahash) == 0)
151 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
152 for (i = 0; i < data->nschemata; i++)
154 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
157 schematahash[h] = i + 1;
159 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
160 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
163 for (sp = schema, len = 0, h = 0; *sp; len++)
168 cid = schematahash[h];
172 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
175 for (cid = 0; cid < data->nschemata; cid++)
176 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
182 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
183 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
185 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
186 data->schemata[data->nschemata] = data->schemadatalen;
187 data->schemadatalen += len;
188 schematahash[h] = data->nschemata + 1;
190 fprintf(stderr, "schema2id: new schema\n");
192 return data->nschemata++;
196 repodata_free_schemahash(Repodata *data)
198 data->schematahash = sat_free(data->schematahash);
200 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
201 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
205 /***************************************************************
206 * dir pool management
210 repodata_str2dir(Repodata *data, const char *dir, int create)
216 while (*dir == '/' && dir[1] == '/')
218 if (*dir == '/' && !dir[1])
222 dire = strchrnul(dir, '/');
224 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
226 id = strn2id(data->repo->pool, dir, dire - dir, create);
229 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
242 repodata_dir2str(Repodata *data, Id did, const char *suf)
244 Pool *pool = data->repo->pool;
251 return suf ? suf : "";
255 comp = dirpool_compid(&data->dirpool, parent);
256 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
258 parent = dirpool_parent(&data->dirpool, parent);
263 l += strlen(suf) + 1;
264 p = pool_alloctmpspace(pool, l + 1) + l;
275 comp = dirpool_compid(&data->dirpool, parent);
276 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
279 strncpy(p, comps, l);
280 parent = dirpool_parent(&data->dirpool, parent);
288 /***************************************************************
292 static inline unsigned char *
293 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
295 Id *keyp = data->schemadata + data->schemata[schema];
296 for (; *keyp; keyp++)
297 dp = data_skip_key(data, dp, data->keys + *keyp);
302 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
304 int nentries, schema;
307 case REPOKEY_TYPE_FIXARRAY:
308 dp = data_read_id(dp, &nentries);
311 dp = data_read_id(dp, &schema);
313 dp = data_skip_schema(data, dp, schema);
315 case REPOKEY_TYPE_FLEXARRAY:
316 dp = data_read_id(dp, &nentries);
319 dp = data_read_id(dp, &schema);
320 dp = data_skip_schema(data, dp, schema);
324 if (key->storage == KEY_STORAGE_INCORE)
325 dp = data_skip(dp, key->type);
326 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
328 dp = data_skip(dp, REPOKEY_TYPE_ID);
329 dp = data_skip(dp, REPOKEY_TYPE_ID);
335 static unsigned char *
336 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
342 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
345 for (i = 0; (k = *keyp++) != 0; i++)
347 return data->incoredata + data->mainschemaoffsets[i];
350 while ((k = *keyp++) != 0)
354 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
356 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
357 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
360 if (data->keys[k].storage != KEY_STORAGE_INCORE)
362 dp = data_skip_key(data, dp, data->keys + k);
367 static unsigned char *
368 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
373 if (off >= data->lastverticaloffset)
375 off -= data->lastverticaloffset;
376 if (off + len > data->vincorelen)
378 return data->vincore + off;
380 if (off + len > key->size)
382 /* we now have the offset, go into vertical */
383 off += data->verticaloffset[key - data->keys];
384 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
385 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
387 dp += off % BLOB_PAGESIZE;
391 static inline unsigned char *
392 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
394 unsigned char *dp = *dpp;
398 if (key->storage == KEY_STORAGE_INCORE)
401 *dpp = data_skip_key(data, dp, key);
404 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
407 dp = data_read_id(dp, &off);
408 dp = data_read_id(dp, &len);
411 return get_vertical_data(data, key, off, len);
417 load_repodata(Repodata *data)
419 if (data->loadcallback)
421 data->loadcallback(data);
422 if (data->state == REPODATA_AVAILABLE)
425 data->state = REPODATA_ERROR;
430 maybe_load_repodata(Repodata *data, Id keyname)
432 if (keyname && !repodata_precheck_keyname(data, keyname))
433 return 0; /* do not bother... */
440 for (i = 0; i < data->nkeys; i++)
441 if (keyname == data->keys[i].name)
443 if (i == data->nkeys)
446 return load_repodata(data);
449 case REPODATA_AVAILABLE:
452 data->state = REPODATA_ERROR;
457 static inline unsigned char *
458 solvid2data(Repodata *data, Id solvid, Id *schemap)
460 unsigned char *dp = data->incoredata;
463 if (solvid == SOLVID_META) /* META */
465 else if (solvid == SOLVID_POS) /* META */
467 Pool *pool = data->repo->pool;
468 if (data->repo != pool->pos.repo)
470 if (data != data->repo->repodata + pool->pos.repodataid)
472 *schemap = pool->pos.schema;
473 return data->incoredata + pool->pos.dp;
477 if (solvid < data->start || solvid >= data->end)
479 dp += data->incoreoffset[solvid - data->start];
481 return data_read_id(dp, schemap);
484 /************************************************************************
488 static inline unsigned char *
489 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
492 Id schema, *keyp, *kp;
495 if (!maybe_load_repodata(data, keyname))
497 dp = solvid2data(data, solvid, &schema);
500 keyp = data->schemadata + data->schemata[schema];
501 for (kp = keyp; *kp; kp++)
502 if (data->keys[*kp].name == keyname)
506 *keypp = key = data->keys + *kp;
507 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
508 return dp; /* no need to forward... */
509 dp = forward_to_key(data, *kp, keyp, dp);
512 return get_data(data, key, &dp, 0);
517 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
523 dp = find_key_data(data, solvid, keyname, &key);
526 if (key->type == REPOKEY_TYPE_CONSTANTID)
528 if (key->type != REPOKEY_TYPE_ID)
530 dp = data_read_id(dp, &id);
535 repodata_globalize_id(Repodata *data, Id id, int create)
537 if (!id || !data || !data->localpool)
539 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
543 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
549 dp = find_key_data(data, solvid, keyname, &key);
552 if (key->type == REPOKEY_TYPE_STR)
553 return (const char *)dp;
554 if (key->type == REPOKEY_TYPE_CONSTANTID)
555 return id2str(data->repo->pool, key->size);
556 if (key->type == REPOKEY_TYPE_ID)
557 dp = data_read_id(dp, &id);
561 return data->spool.stringspace + data->spool.strings[id];
562 return id2str(data->repo->pool, id);
566 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
573 dp = find_key_data(data, solvid, keyname, &key);
576 if (key->type == REPOKEY_TYPE_NUM
577 || key->type == REPOKEY_TYPE_U32
578 || key->type == REPOKEY_TYPE_CONSTANT)
580 dp = data_fetch(dp, &kv, key);
588 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
594 if (!maybe_load_repodata(data, keyname))
596 dp = solvid2data(data, solvid, &schema);
599 /* can't use find_key_data as we need to test the type */
600 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
601 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
606 const unsigned char *
607 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
612 dp = find_key_data(data, solvid, keyname, &key);
620 /************************************************************************
626 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
630 case REPOKEY_TYPE_ID:
631 case REPOKEY_TYPE_CONSTANTID:
632 case REPOKEY_TYPE_IDARRAY:
633 if (data && data->localpool)
634 kv->str = stringpool_id2str(&data->spool, kv->id);
636 kv->str = id2str(pool, kv->id);
637 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
639 const char *s = strchr(kv->str, ':');
644 case REPOKEY_TYPE_STR:
646 case REPOKEY_TYPE_DIRSTRARRAY:
647 if (!(flags & SEARCH_FILES))
648 return 1; /* match just the basename */
649 /* Put the full filename into kv->str. */
650 kv->str = repodata_dir2str(data, kv->id, kv->str);
651 /* And to compensate for that put the "empty" directory into
652 kv->id, so that later calls to repodata_dir2str on this data
653 come up with the same filename again. */
662 struct subschema_data {
668 /* search a specific repodata */
670 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
674 Id keyid, *kp, *keyp;
675 unsigned char *dp, *ddp;
681 if (!maybe_load_repodata(data, keyname))
683 if (solvid == SOLVID_SUBSCHEMA)
685 struct subschema_data *subd = cbdata;
686 cbdata = subd->cbdata;
688 schema = subd->parent->id;
689 dp = (unsigned char *)subd->parent->str;
690 kv.parent = subd->parent;
695 dp = solvid2data(data, solvid, &schema);
698 s = data->repo->pool->solvables + solvid;
701 keyp = data->schemadata + data->schemata[schema];
704 /* search for a specific key */
705 for (kp = keyp; *kp; kp++)
706 if (data->keys[*kp].name == keyname)
710 dp = forward_to_key(data, *kp, keyp, dp);
716 while ((keyid = *keyp++) != 0)
719 key = data->keys + keyid;
720 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
722 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
724 struct subschema_data subd;
728 subd.cbdata = cbdata;
731 ddp = data_read_id(ddp, &nentries);
735 while (ddp && nentries > 0)
739 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
740 ddp = data_read_id(ddp, &schema);
742 kv.str = (char *)ddp;
743 stop = callback(cbdata, s, data, key, &kv);
744 if (stop > SEARCH_NEXT_KEY)
746 if (stop && stop != SEARCH_ENTERSUB)
748 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
749 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
750 ddp = data_skip_schema(data, ddp, schema);
753 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
757 kv.str = (char *)ddp;
758 stop = callback(cbdata, s, data, key, &kv);
759 if (stop > SEARCH_NEXT_KEY)
769 ddp = data_fetch(ddp, &kv, key);
772 stop = callback(cbdata, s, data, key, &kv);
775 while (!kv.eof && !stop);
776 if (onekey || stop > SEARCH_NEXT_KEY)
782 repodata_setpos_kv(Repodata *data, KeyValue *kv)
784 Pool *pool = data->repo->pool;
786 pool_clear_pos(pool);
789 pool->pos.repo = data->repo;
790 pool->pos.repodataid = data - data->repo->repodata;
791 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
792 pool->pos.schema = kv->id;
796 /************************************************************************
797 * data iterator functions
800 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
801 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
802 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
803 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
804 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
805 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
806 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
807 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
808 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
809 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
810 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
811 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
812 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
813 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
817 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
831 case SOLVABLE_VENDOR:
834 case SOLVABLE_PROVIDES:
836 return s->provides ? s->repo->idarraydata + s->provides : 0;
837 case SOLVABLE_OBSOLETES:
839 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
840 case SOLVABLE_CONFLICTS:
842 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
843 case SOLVABLE_REQUIRES:
845 return s->requires ? s->repo->idarraydata + s->requires : 0;
846 case SOLVABLE_RECOMMENDS:
848 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
849 case SOLVABLE_SUPPLEMENTS:
851 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
852 case SOLVABLE_SUGGESTS:
854 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
855 case SOLVABLE_ENHANCES:
857 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
860 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
867 datamatcher_init(Datamatcher *ma, const char *match, int flags)
869 ma->match = (void *)match;
872 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
874 ma->match = sat_calloc(1, sizeof(regex_t));
875 ma->error = regcomp((regex_t *)ma->match, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
879 ma->match = (void *)match;
880 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
887 datamatcher_free(Datamatcher *ma)
889 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->match)
892 ma->match = sat_free(ma->match);
897 datamatcher_match(Datamatcher *ma, const char *str)
899 switch ((ma->flags & SEARCH_STRINGMASK))
901 case SEARCH_SUBSTRING:
902 if (ma->flags & SEARCH_NOCASE)
904 if (!strcasestr(str, (const char *)ma->match))
909 if (!strstr(str, (const char *)ma->match))
914 if (ma->flags & SEARCH_NOCASE)
916 if (strcasecmp((const char *)ma->match, str))
921 if (strcmp((const char *)ma->match, str))
926 if (fnmatch((const char *)ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
930 if (regexec((const regex_t *)ma->match, str, 0, NULL, 0))
965 /* see repo.h for documentation */
967 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
969 memset(di, 0, sizeof(*di));
971 if (!pool || (repo && repo->pool != pool))
979 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
986 di->keyname = keyname;
987 di->keynames[0] = keyname;
988 di->flags = flags & ~SEARCH_THISSOLVID;
997 dataiterator_jump_to_solvid(di, p);
1001 di->repo = pool->repos[0];
1002 di->state = di_enterrepo;
1008 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1012 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1014 di->state = di_bye; /* sorry */
1017 for (i = di->nkeynames + 1; i > 0; i--)
1018 di->keynames[i] = di->keynames[i - 1];
1019 di->keynames[0] = di->keyname = keyname;
1024 dataiterator_free(Dataiterator *di)
1026 if (di->matcher.match)
1027 datamatcher_free(&di->matcher);
1030 static inline unsigned char *
1031 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1033 Id *keyp = di->keyp;
1034 Repokey *keys = di->data->keys;
1037 for (keyp = di->keyp; *keyp; keyp++)
1038 if (keys[*keyp].name == keyname)
1042 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1050 dataiterator_step(Dataiterator *di)
1058 case di_enterrepo: di_enterrepo:
1061 if (!(di->flags & SEARCH_THISSOLVID))
1063 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1064 goto di_nextsolvable;
1068 case di_entersolvable: di_entersolvable:
1069 if (di->repodataid >= 0)
1071 di->repodataid = 0; /* reset repodata iterator */
1072 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1074 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1076 goto di_entersolvablekey;
1081 case di_enterrepodata: di_enterrepodata:
1082 if (di->repodataid >= 0)
1084 if (di->repodataid >= di->repo->nrepodata)
1085 goto di_nextsolvable;
1086 di->data = di->repo->repodata + di->repodataid;
1088 if (!maybe_load_repodata(di->data, di->keyname))
1089 goto di_nextrepodata;
1090 di->dp = solvid2data(di->data, di->solvid, &schema);
1092 goto di_nextrepodata;
1093 if (di->solvid == SOLVID_POS)
1094 di->solvid = di->pool->pos.solvid;
1095 /* reset key iterator */
1096 di->keyp = di->data->schemadata + di->data->schemata[schema];
1099 case di_enterschema: di_enterschema:
1101 di->dp = dataiterator_find_keyname(di, di->keyname);
1102 if (!di->dp || !*di->keyp)
1106 goto di_nextrepodata;
1110 case di_enterkey: di_enterkey:
1112 di->key = di->data->keys + *di->keyp;
1113 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1116 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1118 if (di->nparents < di->nkeynames)
1124 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1126 di->state = di_nextkey;
1128 di->state = di_nextattr;
1131 case di_nextkey: di_nextkey:
1132 if (!di->keyname && *++di->keyp)
1138 case di_nextrepodata: di_nextrepodata:
1139 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1140 goto di_enterrepodata;
1143 case di_nextsolvable: di_nextsolvable:
1144 if (!(di->flags & SEARCH_THISSOLVID))
1147 di->solvid = di->repo->start;
1150 for (; di->solvid < di->repo->end; di->solvid++)
1152 if (di->pool->solvables[di->solvid].repo == di->repo)
1153 goto di_entersolvable;
1159 if (di->repoid >= 0)
1162 if (di->repoid < di->pool->nrepos)
1164 di->repo = di->pool->repos[di->repoid];
1170 case di_bye: di_bye:
1174 case di_enterarray: di_enterarray:
1175 if (di->key->name == REPOSITORY_SOLVABLES)
1177 di->ddp = data_read_id(di->ddp, &di->kv.num);
1182 case di_nextarrayelement: di_nextarrayelement:
1185 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1186 if (di->kv.entry == di->kv.num)
1188 if (di->nparents < di->nkeynames)
1190 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1192 di->kv.str = (char *)di->ddp;
1194 di->state = di_nextkey;
1197 if (di->kv.entry == di->kv.num - 1)
1199 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1200 di->ddp = data_read_id(di->ddp, &di->kv.id);
1201 di->kv.str = (char *)di->ddp;
1202 if (di->nparents < di->nkeynames)
1204 if ((di->flags & SEARCH_SUB) != 0)
1205 di->state = di_entersub;
1207 di->state = di_nextarrayelement;
1210 case di_entersub: di_entersub:
1211 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1212 goto di_nextarrayelement; /* sorry, full */
1213 di->parents[di->nparents].kv = di->kv;
1214 di->parents[di->nparents].dp = di->dp;
1215 di->parents[di->nparents].keyp = di->keyp;
1216 di->dp = (unsigned char *)di->kv.str;
1217 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1218 memset(&di->kv, 0, sizeof(di->kv));
1219 di->kv.parent = &di->parents[di->nparents].kv;
1221 di->keyname = di->keynames[di->nparents];
1222 goto di_enterschema;
1224 case di_leavesub: di_leavesub:
1226 di->dp = di->parents[di->nparents].dp;
1227 di->kv = di->parents[di->nparents].kv;
1228 di->keyp = di->parents[di->nparents].keyp;
1229 di->key = di->data->keys + *di->keyp;
1230 di->ddp = (unsigned char *)di->kv.str;
1231 di->keyname = di->keynames[di->nparents];
1232 goto di_nextarrayelement;
1234 /* special solvable attr handling follows */
1236 case di_nextsolvableattr:
1237 di->kv.id = *di->idp++;
1242 di->state = di_nextsolvablekey;
1246 case di_nextsolvablekey: di_nextsolvablekey:
1247 if (di->keyname || di->key->name == RPM_RPMDBID)
1248 goto di_enterrepodata;
1252 case di_entersolvablekey: di_entersolvablekey:
1253 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1254 if (!di->idp || !di->idp[0])
1255 goto di_nextsolvablekey;
1256 di->kv.id = di->idp[0];
1257 di->kv.num = di->idp[0];
1259 if (!di->kv.eof && !di->idp[0])
1263 di->state = di_nextsolvablekey;
1265 di->state = di_nextsolvableattr;
1269 if (di->matcher.match)
1271 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1273 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1277 if (!datamatcher_match(&di->matcher, di->kv.str))
1280 /* found something! */
1286 dataiterator_entersub(Dataiterator *di)
1288 if (di->state == di_nextarrayelement)
1289 di->state = di_entersub;
1293 dataiterator_setpos(Dataiterator *di)
1295 if (di->kv.eof == 2)
1297 pool_clear_pos(di->pool);
1300 di->pool->pos.solvid = di->solvid;
1301 di->pool->pos.repo = di->repo;
1302 di->pool->pos.repodataid = di->data - di->repo->repodata;
1303 di->pool->pos.schema = di->kv.id;
1304 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1308 dataiterator_setpos_parent(Dataiterator *di)
1310 if (!di->kv.parent || di->kv.parent->eof == 2)
1312 pool_clear_pos(di->pool);
1315 di->pool->pos.solvid = di->solvid;
1316 di->pool->pos.repo = di->repo;
1317 di->pool->pos.repodataid = di->data - di->repo->repodata;
1318 di->pool->pos.schema = di->kv.parent->id;
1319 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1323 dataiterator_skip_attribute(Dataiterator *di)
1325 if (di->state == di_nextsolvableattr)
1326 di->state = di_nextsolvablekey;
1328 di->state = di_nextkey;
1332 dataiterator_skip_solvable(Dataiterator *di)
1334 di->state = di_nextsolvable;
1338 dataiterator_skip_repo(Dataiterator *di)
1340 di->state = di_nextrepo;
1344 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1347 if (solvid == SOLVID_POS)
1349 di->repo = di->pool->pos.repo;
1356 di->data = di->repo->repodata + di->pool->pos.repodataid;
1357 di->repodataid = -1;
1358 di->solvid = solvid;
1359 di->state = di_enterrepo;
1360 di->flags |= SEARCH_THISSOLVID;
1365 di->repo = di->pool->solvables[solvid].repo;
1368 else if (di->repoid >= 0)
1370 if (!di->pool->nrepos)
1375 di->repo = di->pool->repos[0];
1379 di->solvid = solvid;
1381 di->flags |= SEARCH_THISSOLVID;
1382 di->state = di_enterrepo;
1386 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1393 di->flags &= ~SEARCH_THISSOLVID;
1394 di->state = di_enterrepo;
1398 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1400 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1404 return datamatcher_match(ma, di->kv.str);
1407 /************************************************************************
1408 * data modify functions
1411 /* extend repodata so that it includes solvables p */
1413 repodata_extend(Repodata *data, Id p)
1415 if (data->start == data->end)
1416 data->start = data->end = p;
1419 int old = data->end - data->start;
1420 int new = p - data->end + 1;
1423 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1424 memset(data->attrs + old, 0, new * sizeof(Id *));
1426 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1427 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1430 if (p < data->start)
1432 int old = data->end - data->start;
1433 int new = data->start - p;
1436 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1437 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1438 memset(data->attrs, 0, new * sizeof(Id *));
1440 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1441 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1442 memset(data->incoreoffset, 0, new * sizeof(Id));
1447 /* extend repodata so that it includes solvables from start to start + num - 1 */
1449 repodata_extend_block(Repodata *data, Id start, Id num)
1453 if (!data->incoreoffset)
1455 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1456 data->start = start;
1457 data->end = start + num;
1460 repodata_extend(data, start);
1462 repodata_extend(data, start + num - 1);
1465 /**********************************************************************/
1467 #define REPODATA_ATTRS_BLOCK 63
1468 #define REPODATA_ATTRDATA_BLOCK 1023
1469 #define REPODATA_ATTRIDDATA_BLOCK 63
1473 repodata_new_handle(Repodata *data)
1477 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1480 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1481 data->xattrs[data->nxattrs] = 0;
1482 return -(data->nxattrs++);
1486 repodata_get_attrp(Repodata *data, Id handle)
1488 if (handle == SOLVID_META)
1492 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1497 return data->xattrs - handle;
1498 if (handle < data->start || handle >= data->end)
1499 repodata_extend(data, handle);
1501 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1502 return data->attrs + (handle - data->start);
1506 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1512 app = repodata_get_attrp(data, handle);
1517 for (pp = ap; *pp; pp += 2)
1518 /* Determine equality based on the name only, allows us to change
1519 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1520 if (data->keys[*pp].name == data->keys[keyid].name)
1533 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1543 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1547 keyid = repodata_key2id(data, key, 1);
1548 repodata_insert_keyid(data, solvid, keyid, val, 1);
1552 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1556 key.type = REPOKEY_TYPE_ID;
1558 key.storage = KEY_STORAGE_INCORE;
1559 repodata_set(data, solvid, &key, id);
1563 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1567 key.type = REPOKEY_TYPE_NUM;
1569 key.storage = KEY_STORAGE_INCORE;
1570 repodata_set(data, solvid, &key, (Id)num);
1574 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1578 if (data->localpool)
1579 id = stringpool_str2id(&data->spool, str, 1);
1581 id = str2id(data->repo->pool, str, 1);
1583 key.type = REPOKEY_TYPE_ID;
1585 key.storage = KEY_STORAGE_INCORE;
1586 repodata_set(data, solvid, &key, id);
1590 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1594 key.type = REPOKEY_TYPE_CONSTANT;
1595 key.size = constant;
1596 key.storage = KEY_STORAGE_INCORE;
1597 repodata_set(data, solvid, &key, 0);
1601 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1605 key.type = REPOKEY_TYPE_CONSTANTID;
1607 key.storage = KEY_STORAGE_INCORE;
1608 repodata_set(data, solvid, &key, 0);
1612 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1616 key.type = REPOKEY_TYPE_VOID;
1618 key.storage = KEY_STORAGE_INCORE;
1619 repodata_set(data, solvid, &key, 0);
1623 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1628 l = strlen(str) + 1;
1630 key.type = REPOKEY_TYPE_STR;
1632 key.storage = KEY_STORAGE_INCORE;
1633 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1634 memcpy(data->attrdata + data->attrdatalen, str, l);
1635 repodata_set(data, solvid, &key, data->attrdatalen);
1636 data->attrdatalen += l;
1639 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
1640 * so that the caller can append the new element there */
1642 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1645 Id *ida, *pp, **ppp;
1647 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1649 /* great! just append the new data */
1650 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1651 data->attriddatalen--; /* overwrite terminating 0 */
1652 data->lastdatalen += entrysize;
1655 ppp = repodata_get_attrp(data, handle);
1658 for (; *pp; pp += 2)
1659 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1663 /* not found. allocate new key */
1668 key.storage = KEY_STORAGE_INCORE;
1669 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1670 repodata_set(data, handle, &key, data->attriddatalen);
1671 data->lasthandle = 0; /* next time... */
1675 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1676 oldsize += entrysize;
1677 if (ida + 1 == data->attriddata + data->attriddatalen)
1679 /* this was the last entry, just append it */
1680 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1681 data->attriddatalen--; /* overwrite terminating 0 */
1685 /* too bad. move to back. */
1686 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1687 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1688 pp[1] = data->attriddatalen;
1689 data->attriddatalen += oldsize;
1691 data->lasthandle = handle;
1692 data->lastkey = *pp;
1693 data->lastdatalen = data->attriddatalen + entrysize + 1;
1697 checksumtype2len(Id type)
1701 case REPOKEY_TYPE_MD5:
1703 case REPOKEY_TYPE_SHA1:
1705 case REPOKEY_TYPE_SHA256:
1706 return SIZEOF_SHA256;
1713 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1714 const unsigned char *str)
1717 int l = checksumtype2len(type);
1724 key.storage = KEY_STORAGE_INCORE;
1725 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1726 memcpy(data->attrdata + data->attrdatalen, str, l);
1727 repodata_set(data, solvid, &key, data->attrdatalen);
1728 data->attrdatalen += l;
1732 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1735 for (i = 0; i < buflen; i++)
1737 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1738 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
1739 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
1750 buf[i] = (buf[i] << 4) | v;
1757 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1760 unsigned char buf[64];
1761 int l = checksumtype2len(type);
1765 if (hexstr2bytes(buf, str, l) != l)
1767 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1771 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1776 l = checksumtype2len(type);
1779 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1780 for (i = 0; i < l; i++)
1782 unsigned char v = buf[i];
1783 unsigned char w = v >> 4;
1784 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1786 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1792 /* rpm filenames don't contain the epoch, so strip it */
1793 static inline const char *
1794 evrid2vrstr(Pool *pool, Id evrid)
1796 const char *p, *evr = id2str(pool, evrid);
1799 for (p = evr; *p >= '0' && *p <= '9'; p++)
1801 return p != evr && *p == ':' ? p + 1 : evr;
1805 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
1807 Pool *pool = data->repo->pool;
1809 const char *str, *fp;
1813 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
1816 if ((dir = strrchr(file, '/')) != 0)
1827 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
1832 if (l == 1 && dir[0] == '.')
1834 s = pool->solvables + solvid;
1837 str = id2str(pool, s->arch);
1838 if (!strncmp(dir, str, l) && !str[l])
1839 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
1841 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
1844 char *dir2 = strdup(dir);
1846 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
1851 str = id2str(pool, s->name);
1853 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
1856 str = evrid2vrstr(pool, s->evr);
1858 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
1861 str = id2str(pool, s->arch);
1863 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
1865 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
1870 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
1874 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1878 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1880 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1881 data->attriddata[data->attriddatalen++] = dir;
1882 data->attriddata[data->attriddatalen++] = num;
1883 data->attriddata[data->attriddatalen++] = num2;
1884 data->attriddata[data->attriddatalen++] = 0;
1888 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1894 l = strlen(str) + 1;
1895 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1896 memcpy(data->attrdata + data->attrdatalen, str, l);
1897 stroff = data->attrdatalen;
1898 data->attrdatalen += l;
1901 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1903 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1904 data->attriddata[data->attriddatalen++] = dir;
1905 data->attriddata[data->attriddatalen++] = stroff;
1906 data->attriddata[data->attriddatalen++] = 0;
1910 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1913 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1915 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1916 data->attriddata[data->attriddatalen++] = id;
1917 data->attriddata[data->attriddatalen++] = 0;
1921 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1925 if (data->localpool)
1926 id = stringpool_str2id(&data->spool, str, 1);
1928 id = str2id(data->repo->pool, str, 1);
1929 repodata_add_idarray(data, solvid, keyname, id);
1933 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1935 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1936 data->attriddata[data->attriddatalen++] = ghandle;
1937 data->attriddata[data->attriddatalen++] = 0;
1941 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1943 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1944 data->attriddata[data->attriddatalen++] = ghandle;
1945 data->attriddata[data->attriddatalen++] = 0;
1948 /* add all attrs from src to dest */
1950 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1953 if (dest == src || !(keyp = data->attrs[src - data->start]))
1955 for (; *keyp; keyp += 2)
1956 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1962 /**********************************************************************/
1964 /* unify with repo_write! */
1966 #define EXTDATA_BLOCK 1023
1974 data_addid(struct extdata *xd, Id x)
1977 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1978 dp = xd->buf + xd->len;
1983 *dp++ = (x >> 28) | 128;
1985 *dp++ = (x >> 21) | 128;
1986 *dp++ = (x >> 14) | 128;
1989 *dp++ = (x >> 7) | 128;
1991 xd->len = dp - xd->buf;
1995 data_addideof(struct extdata *xd, Id x, int eof)
1998 x = (x & 63) | ((x & ~63) << 1);
1999 data_addid(xd, (eof ? x: x | 64));
2003 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2005 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2006 memcpy(xd->buf + xd->len, blob, len);
2010 /*********************************/
2013 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2014 struct extdata *newvincore,
2016 Repokey *key, Id val)
2018 /* Otherwise we have a new value. Parse it into the internal
2022 unsigned int oldvincorelen = 0;
2026 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2029 oldvincorelen = xd->len;
2033 case REPOKEY_TYPE_VOID:
2034 case REPOKEY_TYPE_CONSTANT:
2035 case REPOKEY_TYPE_CONSTANTID:
2037 case REPOKEY_TYPE_STR:
2038 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2040 case REPOKEY_TYPE_MD5:
2041 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2043 case REPOKEY_TYPE_SHA1:
2044 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2046 case REPOKEY_TYPE_SHA256:
2047 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2049 case REPOKEY_TYPE_ID:
2050 case REPOKEY_TYPE_NUM:
2051 case REPOKEY_TYPE_DIR:
2052 data_addid(xd, val);
2054 case REPOKEY_TYPE_IDARRAY:
2055 for (ida = data->attriddata + val; *ida; ida++)
2056 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2058 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2059 for (ida = data->attriddata + val; *ida; ida += 3)
2061 data_addid(xd, ida[0]);
2062 data_addid(xd, ida[1]);
2063 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2066 case REPOKEY_TYPE_DIRSTRARRAY:
2067 for (ida = data->attriddata + val; *ida; ida += 2)
2069 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2070 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2073 case REPOKEY_TYPE_FIXARRAY:
2077 for (ida = data->attriddata + val; *ida; ida++)
2080 fprintf(stderr, "serialize struct %d\n", *ida);
2083 Id *kp = data->xattrs[-*ida];
2090 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2096 schemaid = repodata_schema2id(data, schema, 1);
2097 else if (schemaid != repodata_schema2id(data, schema, 0))
2099 pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
2103 fprintf(stderr, " schema %d\n", schemaid);
2108 data_addid(xd, num);
2109 data_addid(xd, schemaid);
2110 for (ida = data->attriddata + val; *ida; ida++)
2112 Id *kp = data->xattrs[-*ida];
2117 repodata_serialize_key(data, newincore, newvincore,
2118 schema, data->keys + *kp, kp[1]);
2123 case REPOKEY_TYPE_FLEXARRAY:
2126 for (ida = data->attriddata + val; *ida; ida++)
2128 data_addid(xd, num);
2129 for (ida = data->attriddata + val; *ida; ida++)
2131 Id *kp = data->xattrs[-*ida];
2134 data_addid(xd, 0); /* XXX */
2141 schemaid = repodata_schema2id(data, schema, 1);
2142 data_addid(xd, schemaid);
2143 kp = data->xattrs[-*ida];
2146 repodata_serialize_key(data, newincore, newvincore,
2147 schema, data->keys + *kp, kp[1]);
2153 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2156 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2158 /* put offset/len in incore */
2159 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2160 oldvincorelen = xd->len - oldvincorelen;
2161 data_addid(newincore, oldvincorelen);
2166 repodata_internalize(Repodata *data)
2168 Repokey *key, solvkey;
2170 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2171 unsigned char *dp, *ndp;
2172 int newschema, oldcount;
2173 struct extdata newincore;
2174 struct extdata newvincore;
2177 if (!data->attrs && !data->xattrs)
2180 newvincore.buf = data->vincore;
2181 newvincore.len = data->vincorelen;
2183 /* find the solvables key, create if needed */
2184 memset(&solvkey, 0, sizeof(solvkey));
2185 solvkey.name = REPOSITORY_SOLVABLES;
2186 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2188 solvkey.storage = KEY_STORAGE_INCORE;
2189 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2191 schema = sat_malloc2(data->nkeys, sizeof(Id));
2192 seen = sat_malloc2(data->nkeys, sizeof(Id));
2194 /* Merge the data already existing (in data->schemata, ->incoredata and
2195 friends) with the new attributes in data->attrs[]. */
2196 nentry = data->end - data->start;
2197 memset(&newincore, 0, sizeof(newincore));
2198 data_addid(&newincore, 0); /* start data at offset 1 */
2200 data->mainschema = 0;
2201 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2203 /* join entry data */
2204 /* we start with the meta data, entry -1 */
2205 for (entry = -1; entry < nentry; entry++)
2207 memset(seen, 0, data->nkeys * sizeof(Id));
2209 dp = data->incoredata;
2212 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2213 dp = data_read_id(dp, &oldschema);
2216 fprintf(stderr, "oldschema %d\n", oldschema);
2217 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2218 fprintf(stderr, "schemadata %p\n", data->schemadata);
2220 /* seen: -1: old data 0: skipped >0: id + 1 */
2224 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2228 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2236 keyp = data->attrs ? data->attrs[entry] : 0;
2239 /* strip solvables key */
2241 for (sp = keyp = schema; *sp; sp++)
2242 if (*sp != solvkeyid)
2247 seen[solvkeyid] = 0;
2248 keyp = data->xattrs ? data->xattrs[1] : 0;
2251 for (; *keyp; keyp += 2)
2258 seen[*keyp] = keyp[1] + 1;
2260 if (entry < 0 && data->end != data->start)
2267 /* Ideally we'd like to sort the new schema here, to ensure
2268 schema equality independend of the ordering. We can't do that
2269 yet. For once see below (old ids need to come before new ids).
2270 An additional difficulty is that we also need to move
2271 the values with the keys. */
2272 schemaid = repodata_schema2id(data, schema, 1);
2274 schemaid = oldschema;
2277 /* Now create data blob. We walk through the (possibly new) schema
2278 and either copy over old data, or insert the new. */
2279 /* XXX Here we rely on the fact that the (new) schema has the form
2280 o1 o2 o3 o4 ... | n1 n2 n3 ...
2281 (oX being the old keyids (possibly overwritten), and nX being
2282 the new keyids). This rules out sorting the keyids in order
2283 to ensure a small schema count. */
2285 data->incoreoffset[entry] = newincore.len;
2286 data_addid(&newincore, schemaid);
2289 data->mainschema = schemaid;
2290 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2292 keypstart = data->schemadata + data->schemata[schemaid];
2293 for (keyp = keypstart; *keyp; keyp++)
2296 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2297 if (*keyp == solvkeyid)
2299 /* add flexarray entry count */
2300 data_addid(&newincore, data->end - data->start);
2303 key = data->keys + *keyp;
2305 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2310 /* Skip the data associated with this old key. */
2311 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2313 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2314 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2316 else if (key->storage == KEY_STORAGE_INCORE)
2317 ndp = data_skip_key(data, dp, key);
2320 if (seen[*keyp] == -1)
2322 /* If this key was an old one _and_ was not overwritten with
2323 a different value copy over the old value (we skipped it
2326 data_addblob(&newincore, dp, ndp - dp);
2329 else if (seen[*keyp])
2331 /* Otherwise we have a new value. Parse it into the internal
2333 repodata_serialize_key(data, &newincore, &newvincore,
2334 schema, key, seen[*keyp] - 1);
2338 if (entry >= 0 && data->attrs && data->attrs[entry])
2339 data->attrs[entry] = sat_free(data->attrs[entry]);
2341 /* free all xattrs */
2342 for (entry = 0; entry < data->nxattrs; entry++)
2343 if (data->xattrs[entry])
2344 sat_free(data->xattrs[entry]);
2345 data->xattrs = sat_free(data->xattrs);
2348 data->lasthandle = 0;
2350 data->lastdatalen = 0;
2353 repodata_free_schemahash(data);
2355 sat_free(data->incoredata);
2356 data->incoredata = newincore.buf;
2357 data->incoredatalen = newincore.len;
2358 data->incoredatafree = 0;
2360 sat_free(data->vincore);
2361 data->vincore = newvincore.buf;
2362 data->vincorelen = newvincore.len;
2364 data->attrs = sat_free(data->attrs);
2365 data->attrdata = sat_free(data->attrdata);
2366 data->attriddata = sat_free(data->attriddata);
2367 data->attrdatalen = 0;
2368 data->attriddatalen = 0;
2372 repodata_disable_paging(Repodata *data)
2374 if (maybe_load_repodata(data, 0))
2375 repopagestore_disable_paging(&data->store);
2379 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: