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
27 #include "poolid_private.h"
33 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
34 unsigned char *out, unsigned int out_len);
35 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
38 unsigned int out_len);
40 #define REPODATA_BLOCK 255
44 repodata_init(Repodata *data, Repo *repo, int localpool)
46 memset(data, 0, sizeof (*data));
48 data->localpool = localpool;
50 stringpool_init_empty(&data->spool);
51 data->keys = sat_calloc(1, sizeof(Repokey));
53 data->schemata = sat_calloc(1, sizeof(Id));
54 data->schemadata = sat_calloc(1, sizeof(Id));
56 data->schemadatalen = 1;
57 repopagestore_init(&data->store);
61 repodata_free(Repodata *data)
67 sat_free(data->schemata);
68 sat_free(data->schemadata);
69 sat_free(data->schematahash);
71 stringpool_free(&data->spool);
72 dirpool_free(&data->dirpool);
74 sat_free(data->mainschemaoffsets);
75 sat_free(data->incoredata);
76 sat_free(data->incoreoffset);
77 sat_free(data->verticaloffset);
79 repopagestore_free(&data->store);
81 sat_free(data->vincore);
84 for (i = 0; i < data->end - data->start; i++)
85 sat_free(data->attrs[i]);
86 sat_free(data->attrs);
88 for (i = 0; i < data->nxattrs; i++)
89 sat_free(data->xattrs[i]);
90 sat_free(data->xattrs);
92 sat_free(data->attrdata);
93 sat_free(data->attriddata);
97 /***************************************************************
101 /* this is not so time critical that we need a hash, so we do a simple
104 repodata_key2id(Repodata *data, Repokey *key, int create)
108 for (keyid = 1; keyid < data->nkeys; keyid++)
109 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
111 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
115 if (keyid == data->nkeys)
119 /* allocate new key */
120 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
121 data->keys[data->nkeys++] = *key;
122 if (data->verticaloffset)
124 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
125 data->verticaloffset[data->nkeys - 1] = 0;
127 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
133 /***************************************************************
134 * schema pool management
137 #define SCHEMATA_BLOCK 31
138 #define SCHEMATADATA_BLOCK 255
141 repodata_schema2id(Repodata *data, Id *schema, int create)
147 if ((schematahash = data->schematahash) == 0)
149 data->schematahash = schematahash = sat_calloc(256, sizeof(Id));
150 for (i = 0; i < data->nschemata; i++)
152 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
155 schematahash[h] = i + 1;
157 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
158 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
161 for (sp = schema, len = 0, h = 0; *sp; len++)
166 cid = schematahash[h];
170 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
173 for (cid = 0; cid < data->nschemata; cid++)
174 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
180 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
181 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
183 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
184 data->schemata[data->nschemata] = data->schemadatalen;
185 data->schemadatalen += len;
186 schematahash[h] = data->nschemata + 1;
188 fprintf(stderr, "schema2id: new schema\n");
190 return data->nschemata++;
194 repodata_free_schemahash(Repodata *data)
196 data->schematahash = sat_free(data->schematahash);
198 data->schemata = sat_realloc2(data->schemata, data->nschemata, sizeof(Id));
199 data->schemadata = sat_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
203 /***************************************************************
204 * dir pool management
208 repodata_str2dir(Repodata *data, const char *dir, int create)
214 while (*dir == '/' && dir[1] == '/')
216 if (*dir == '/' && !dir[1])
220 dire = strchrnul(dir, '/');
222 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
224 id = strn2id(data->repo->pool, dir, dire - dir, create);
227 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
240 repodata_dir2str(Repodata *data, Id did, const char *suf)
242 Pool *pool = data->repo->pool;
249 return suf ? suf : "";
253 comp = dirpool_compid(&data->dirpool, parent);
254 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
256 parent = dirpool_parent(&data->dirpool, parent);
261 l += strlen(suf) + 1;
262 p = pool_alloctmpspace(pool, l + 1) + l;
273 comp = dirpool_compid(&data->dirpool, parent);
274 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
277 strncpy(p, comps, l);
278 parent = dirpool_parent(&data->dirpool, parent);
286 /***************************************************************
290 static inline unsigned char *
291 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
293 Id *keyp = data->schemadata + data->schemata[schema];
294 for (; *keyp; keyp++)
295 dp = data_skip_key(data, dp, data->keys + *keyp);
300 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
302 int nentries, schema;
305 case REPOKEY_TYPE_FIXARRAY:
306 dp = data_read_id(dp, &nentries);
309 dp = data_read_id(dp, &schema);
311 dp = data_skip_schema(data, dp, schema);
313 case REPOKEY_TYPE_FLEXARRAY:
314 dp = data_read_id(dp, &nentries);
317 dp = data_read_id(dp, &schema);
318 dp = data_skip_schema(data, dp, schema);
322 if (key->storage == KEY_STORAGE_INCORE)
323 dp = data_skip(dp, key->type);
324 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
326 dp = data_skip(dp, REPOKEY_TYPE_ID);
327 dp = data_skip(dp, REPOKEY_TYPE_ID);
333 static unsigned char *
334 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
340 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
343 for (i = 0; (k = *keyp++) != 0; i++)
345 return data->incoredata + data->mainschemaoffsets[i];
348 while ((k = *keyp++) != 0)
352 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
354 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
355 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
358 if (data->keys[k].storage != KEY_STORAGE_INCORE)
360 dp = data_skip_key(data, dp, data->keys + k);
365 static unsigned char *
366 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
371 if (off >= data->lastverticaloffset)
373 off -= data->lastverticaloffset;
374 if (off + len > data->vincorelen)
376 return data->vincore + off;
378 if (off + len > key->size)
380 /* we now have the offset, go into vertical */
381 off += data->verticaloffset[key - data->keys];
382 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
383 dp = repopagestore_load_page_range(&data->store, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
385 dp += off % BLOB_PAGESIZE;
389 static inline unsigned char *
390 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
392 unsigned char *dp = *dpp;
396 if (key->storage == KEY_STORAGE_INCORE)
399 *dpp = data_skip_key(data, dp, key);
402 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
405 dp = data_read_id(dp, &off);
406 dp = data_read_id(dp, &len);
409 return get_vertical_data(data, key, off, len);
415 load_repodata(Repodata *data)
417 if (data->loadcallback)
419 data->loadcallback(data);
420 if (data->state == REPODATA_AVAILABLE)
423 data->state = REPODATA_ERROR;
428 maybe_load_repodata(Repodata *data, Id keyname)
430 if (keyname && !repodata_precheck_keyname(data, keyname))
431 return 0; /* do not bother... */
438 for (i = 0; i < data->nkeys; i++)
439 if (keyname == data->keys[i].name)
441 if (i == data->nkeys)
444 return load_repodata(data);
447 case REPODATA_AVAILABLE:
450 data->state = REPODATA_ERROR;
455 static inline unsigned char*
456 solvid2data(Repodata *data, Id solvid, Id *schemap)
458 unsigned char *dp = data->incoredata;
461 if (solvid == SOLVID_META) /* META */
463 else if (solvid == SOLVID_POS) /* META */
465 Pool *pool = data->repo->pool;
466 if (data->repo != pool->pos.repo)
468 if (data != data->repo->repodata + pool->pos.repodataid)
470 *schemap = pool->pos.schema;
471 return data->incoredata + pool->pos.dp;
475 if (solvid < data->start || solvid >= data->end)
477 dp += data->incoreoffset[solvid - data->start];
479 return data_read_id(dp, schemap);
482 /************************************************************************
486 static inline unsigned char *
487 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
490 Id schema, *keyp, *kp;
493 if (!maybe_load_repodata(data, keyname))
495 dp = solvid2data(data, solvid, &schema);
498 keyp = data->schemadata + data->schemata[schema];
499 for (kp = keyp; *kp; kp++)
500 if (data->keys[*kp].name == keyname)
504 *keypp = key = data->keys + *kp;
505 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
506 return dp; /* no need to forward... */
507 dp = forward_to_key(data, *kp, keyp, dp);
510 return get_data(data, key, &dp, 0);
515 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
521 dp = find_key_data(data, solvid, keyname, &key);
524 if (key->type == REPOKEY_TYPE_CONSTANTID)
526 if (key->type != REPOKEY_TYPE_ID)
528 dp = data_read_id(dp, &id);
533 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
539 dp = find_key_data(data, solvid, keyname, &key);
542 if (key->type == REPOKEY_TYPE_STR)
543 return (const char *)dp;
544 if (key->type == REPOKEY_TYPE_CONSTANTID)
545 return id2str(data->repo->pool, key->size);
546 if (key->type == REPOKEY_TYPE_ID)
547 dp = data_read_id(dp, &id);
551 return data->spool.stringspace + data->spool.strings[id];
552 return id2str(data->repo->pool, id);
556 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned int *value)
563 dp = find_key_data(data, solvid, keyname, &key);
566 if (key->type == REPOKEY_TYPE_NUM
567 || key->type == REPOKEY_TYPE_U32
568 || key->type == REPOKEY_TYPE_CONSTANT)
570 dp = data_fetch(dp, &kv, key);
578 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
584 if (!maybe_load_repodata(data, keyname))
586 dp = solvid2data(data, solvid, &schema);
589 /* can't use find_key_data as we need to test the type */
590 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
591 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
596 const unsigned char *
597 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
602 dp = find_key_data(data, solvid, keyname, &key);
610 /************************************************************************
616 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
620 case REPOKEY_TYPE_ID:
621 case REPOKEY_TYPE_CONSTANTID:
622 case REPOKEY_TYPE_IDARRAY:
623 if (data && data->localpool)
624 kv->str = stringpool_id2str(&data->spool, kv->id);
626 kv->str = id2str(pool, kv->id);
627 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
629 const char *s = strchr(kv->str, ':');
634 case REPOKEY_TYPE_STR:
636 case REPOKEY_TYPE_DIRSTRARRAY:
637 if (!(flags & SEARCH_FILES))
638 return 1; /* match just the basename */
639 /* Put the full filename into kv->str. */
640 kv->str = repodata_dir2str(data, kv->id, kv->str);
641 /* And to compensate for that put the "empty" directory into
642 kv->id, so that later calls to repodata_dir2str on this data
643 come up with the same filename again. */
652 struct subschema_data {
658 /* search a specific repodata */
660 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
664 Id keyid, *kp, *keyp;
665 unsigned char *dp, *ddp;
671 if (!maybe_load_repodata(data, keyname))
673 if (solvid == SOLVID_SUBSCHEMA)
675 struct subschema_data *subd = cbdata;
676 cbdata = subd->cbdata;
678 schema = subd->parent->id;
679 dp = (unsigned char *)subd->parent->str;
680 kv.parent = subd->parent;
685 dp = solvid2data(data, solvid, &schema);
688 s = data->repo->pool->solvables + solvid;
691 keyp = data->schemadata + data->schemata[schema];
694 /* search for a specific key */
695 for (kp = keyp; *kp; kp++)
696 if (data->keys[*kp].name == keyname)
700 dp = forward_to_key(data, *kp, keyp, dp);
706 while ((keyid = *keyp++) != 0)
709 key = data->keys + keyid;
710 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
712 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
714 struct subschema_data subd;
718 subd.cbdata = cbdata;
721 ddp = data_read_id(ddp, &nentries);
725 while (ddp && nentries > 0)
729 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
730 ddp = data_read_id(ddp, &schema);
732 kv.str = (char *)ddp;
733 stop = callback(cbdata, s, data, key, &kv);
734 if (stop > SEARCH_NEXT_KEY)
736 if (stop && stop != SEARCH_ENTERSUB)
738 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
739 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
740 ddp = data_skip_schema(data, ddp, schema);
743 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
747 kv.str = (char *)ddp;
748 stop = callback(cbdata, s, data, key, &kv);
749 if (stop > SEARCH_NEXT_KEY)
759 ddp = data_fetch(ddp, &kv, key);
762 stop = callback(cbdata, s, data, key, &kv);
765 while (!kv.eof && !stop);
766 if (onekey || stop > SEARCH_NEXT_KEY)
772 repodata_setpos_kv(Repodata *data, KeyValue *kv)
774 Pool *pool = data->repo->pool;
776 pool_clear_pos(pool);
779 pool->pos.repo = data->repo;
780 pool->pos.repodataid = data - data->repo->repodata;
781 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
782 pool->pos.schema = kv->id;
786 /************************************************************************
787 * data iterator functions
790 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
791 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
792 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
793 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
794 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
795 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
796 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
797 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
798 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
799 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
800 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
801 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
802 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
803 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
807 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
821 case SOLVABLE_VENDOR:
824 case SOLVABLE_PROVIDES:
826 return s->provides ? s->repo->idarraydata + s->provides : 0;
827 case SOLVABLE_OBSOLETES:
829 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
830 case SOLVABLE_CONFLICTS:
832 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
833 case SOLVABLE_REQUIRES:
835 return s->requires ? s->repo->idarraydata + s->requires : 0;
836 case SOLVABLE_RECOMMENDS:
838 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
839 case SOLVABLE_SUPPLEMENTS:
841 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
842 case SOLVABLE_SUGGESTS:
844 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
845 case SOLVABLE_ENHANCES:
847 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
850 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
857 datamatcher_init(Datamatcher *ma, const char *match, int flags)
859 ma->match = (void *)match;
862 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
864 ma->match = sat_calloc(1, sizeof(regex_t));
865 ma->error = regcomp((regex_t *)ma->match, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
869 ma->match = (void *)match;
870 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
877 datamatcher_free(Datamatcher *ma)
879 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->match)
882 ma->match = sat_free(ma->match);
887 datamatcher_match(Datamatcher *ma, const char *str)
889 switch ((ma->flags & SEARCH_STRINGMASK))
891 case SEARCH_SUBSTRING:
892 if (ma->flags & SEARCH_NOCASE)
894 if (!strcasestr(str, (const char *)ma->match))
899 if (!strstr(str, (const char *)ma->match))
904 if (ma->flags & SEARCH_NOCASE)
906 if (strcasecmp((const char *)ma->match, str))
911 if (strcmp((const char *)ma->match, str))
916 if (fnmatch((const char *)ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
920 if (regexec((const regex_t *)ma->match, str, 0, NULL, 0))
956 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
958 memset(di, 0, sizeof(*di));
963 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
970 di->keyname = keyname;
971 di->keynames[0] = keyname;
972 di->flags = flags & ~SEARCH_THISSOLVID;
981 dataiterator_jump_to_solvid(di, p);
984 di->repo = pool->repos[0];
985 di->state = di_enterrepo;
991 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
995 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
997 di->state = di_bye; /* sorry */
1000 for (i = di->nkeynames + 1; i > 0; i--)
1001 di->keynames[i] = di->keynames[i - 1];
1002 di->keynames[0] = di->keyname = keyname;
1007 dataiterator_free(Dataiterator *di)
1009 if (di->matcher.match)
1010 datamatcher_free(&di->matcher);
1013 static inline unsigned char *
1014 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1016 Id *keyp = di->keyp;
1017 Repokey *keys = di->data->keys;
1020 for (keyp = di->keyp; *keyp; keyp++)
1021 if (keys[*keyp].name == keyname)
1025 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1033 dataiterator_step(Dataiterator *di)
1041 case di_enterrepo: di_enterrepo:
1042 if (!(di->flags & SEARCH_THISSOLVID))
1044 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1045 goto di_nextsolvable;
1049 case di_entersolvable: di_entersolvable:
1050 if (di->repodataid >= 0)
1052 di->repodataid = 0; /* reset repodata iterator */
1053 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1055 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1057 goto di_entersolvablekey;
1062 case di_enterrepodata: di_enterrepodata:
1063 if (di->repodataid >= 0)
1065 if (di->repodataid >= di->repo->nrepodata)
1066 goto di_nextsolvable;
1067 di->data = di->repo->repodata + di->repodataid;
1069 if (!maybe_load_repodata(di->data, di->keyname))
1070 goto di_nextrepodata;
1071 di->dp = solvid2data(di->data, di->solvid, &schema);
1073 goto di_nextrepodata;
1074 /* reset key iterator */
1075 di->keyp = di->data->schemadata + di->data->schemata[schema];
1078 case di_enterschema: di_enterschema:
1080 di->dp = dataiterator_find_keyname(di, di->keyname);
1081 if (!di->dp || !*di->keyp)
1085 goto di_nextrepodata;
1089 case di_enterkey: di_enterkey:
1091 di->key = di->data->keys + *di->keyp;
1092 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1095 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1097 if (di->nparents < di->nkeynames)
1103 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1105 di->state = di_nextkey;
1107 di->state = di_nextattr;
1110 case di_nextkey: di_nextkey:
1111 if (!di->keyname && *++di->keyp)
1117 case di_nextrepodata: di_nextrepodata:
1118 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1119 goto di_enterrepodata;
1122 case di_nextsolvable: di_nextsolvable:
1123 if (!(di->flags & SEARCH_THISSOLVID))
1126 di->solvid = di->repo->start;
1129 for (; di->solvid < di->repo->end; di->solvid++)
1131 if (di->pool->solvables[di->solvid].repo == di->repo)
1132 goto di_entersolvable;
1138 if (di->repoid >= 0)
1141 if (di->repoid < di->pool->nrepos)
1143 di->repo = di->pool->repos[di->repoid];
1153 case di_enterarray: di_enterarray:
1154 if (di->key->name == REPOSITORY_SOLVABLES)
1156 di->ddp = data_read_id(di->ddp, &di->kv.num);
1161 case di_nextarrayelement: di_nextarrayelement:
1164 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1165 if (di->kv.entry == di->kv.num)
1167 if (di->nparents < di->nkeynames)
1169 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1171 di->kv.str = (char *)di->ddp;
1173 di->state = di_nextkey;
1176 if (di->kv.entry == di->kv.num - 1)
1178 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1179 di->ddp = data_read_id(di->ddp, &di->kv.id);
1180 di->kv.str = (char *)di->ddp;
1181 if (di->nparents < di->nkeynames)
1183 if ((di->flags & SEARCH_SUB) != 0)
1184 di->state = di_entersub;
1186 di->state = di_nextarrayelement;
1189 case di_entersub: di_entersub:
1190 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1191 goto di_nextarrayelement; /* sorry, full */
1192 di->parents[di->nparents].kv = di->kv;
1193 di->parents[di->nparents].dp = di->dp;
1194 di->parents[di->nparents].keyp = di->keyp;
1195 di->dp = (unsigned char *)di->kv.str;
1196 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1197 memset(&di->kv, 0, sizeof(di->kv));
1198 di->kv.parent = &di->parents[di->nparents].kv;
1200 di->keyname = di->keynames[di->nparents];
1201 goto di_enterschema;
1203 case di_leavesub: di_leavesub:
1205 di->dp = di->parents[di->nparents].dp;
1206 di->kv = di->parents[di->nparents].kv;
1207 di->keyp = di->parents[di->nparents].keyp;
1208 di->key = di->data->keys + *di->keyp;
1209 di->ddp = (unsigned char *)di->kv.str;
1210 di->keyname = di->keynames[di->nparents];
1211 goto di_nextarrayelement;
1213 /* special solvable attr handling follows */
1215 case di_nextsolvableattr:
1216 di->kv.id = *di->idp++;
1221 di->state = di_nextsolvablekey;
1225 case di_nextsolvablekey: di_nextsolvablekey:
1226 if (di->keyname || di->key->name == RPM_RPMDBID)
1227 goto di_enterrepodata;
1231 case di_entersolvablekey: di_entersolvablekey:
1232 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1233 if (!di->idp || !di->idp[0])
1234 goto di_nextsolvablekey;
1235 di->kv.id = di->idp[0];
1236 di->kv.num = di->idp[0];
1237 if (!di->kv.eof && !di->idp[1])
1241 di->state = di_nextsolvablekey;
1243 di->state = di_nextsolvableattr;
1247 if (di->matcher.match)
1249 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1251 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1255 if (!datamatcher_match(&di->matcher, di->kv.str))
1258 /* found something! */
1264 dataiterator_entersub(Dataiterator *di)
1266 if (di->state == di_nextarrayelement)
1267 di->state = di_entersub;
1271 dataiterator_setpos(Dataiterator *di)
1275 pool_clear_pos(di->pool);
1278 di->pool->pos.solvid = di->solvid;
1279 di->pool->pos.repo = di->repo;
1280 di->pool->pos.repodataid = di->data - di->repo->repodata;
1281 di->pool->pos.schema = di->kv.id;
1282 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1286 dataiterator_setpos_parent(Dataiterator *di)
1290 pool_clear_pos(di->pool);
1293 di->pool->pos.solvid = di->solvid;
1294 di->pool->pos.repo = di->repo;
1295 di->pool->pos.repodataid = di->data - di->repo->repodata;
1296 di->pool->pos.schema = di->kv.parent->id;
1297 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1301 dataiterator_skip_attribute(Dataiterator *di)
1303 if (di->state == di_nextsolvableattr)
1304 di->state = di_nextsolvablekey;
1306 di->state = di_nextkey;
1310 dataiterator_skip_solvable(Dataiterator *di)
1312 di->state = di_nextsolvable;
1316 dataiterator_skip_repo(Dataiterator *di)
1318 di->state = di_nextrepo;
1322 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1325 if (solvid == SOLVID_POS)
1327 di->repo = di->pool->pos.repo;
1334 di->data = di->repo->repodata + di->pool->pos.repodataid;
1335 di->repodataid = -1;
1336 di->solvid = di->pool->pos.solvid;
1337 di->state = di_enterrepo;
1338 di->flags |= SEARCH_THISSOLVID;
1343 di->repo = di->pool->solvables[solvid].repo;
1346 else if (di->repoid >= 0)
1348 if (!di->pool->nrepos)
1353 di->repo = di->pool->repos[0];
1357 di->solvid = solvid;
1359 di->flags |= SEARCH_THISSOLVID;
1360 di->state = di_entersolvable;
1364 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1371 di->flags &= ~SEARCH_THISSOLVID;
1372 di->state = di_enterrepo;
1376 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1378 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1380 return datamatcher_match(ma, di->kv.str);
1384 dataiterator_match_obsolete(Dataiterator *di, int flags, const void *vmatch)
1386 Datamatcher matcher;
1388 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, flags))
1390 matcher = di->matcher;
1391 matcher.flags = flags;
1392 matcher.match = (void *)vmatch;
1393 return datamatcher_match(&matcher, di->kv.str);
1397 /************************************************************************
1398 * data modify functions
1401 /* extend repodata so that it includes solvables p */
1403 repodata_extend(Repodata *data, Id p)
1405 if (data->start == data->end)
1406 data->start = data->end = p;
1409 int old = data->end - data->start;
1410 int new = p - data->end + 1;
1413 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1414 memset(data->attrs + old, 0, new * sizeof(Id *));
1416 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1417 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1420 if (p < data->start)
1422 int old = data->end - data->start;
1423 int new = data->start - p;
1426 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1427 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1428 memset(data->attrs, 0, new * sizeof(Id *));
1430 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1431 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1432 memset(data->incoreoffset, 0, new * sizeof(Id));
1438 repodata_extend_block(Repodata *data, Id start, Id num)
1442 if (!data->incoreoffset)
1444 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1445 data->start = start;
1446 data->end = start + num;
1449 repodata_extend(data, start);
1451 repodata_extend(data, start + num - 1);
1454 /**********************************************************************/
1456 #define REPODATA_ATTRS_BLOCK 63
1457 #define REPODATA_ATTRDATA_BLOCK 1023
1458 #define REPODATA_ATTRIDDATA_BLOCK 63
1462 repodata_new_handle(Repodata *data)
1466 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1469 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1470 data->xattrs[data->nxattrs] = 0;
1471 return -(data->nxattrs++);
1475 repodata_get_attrp(Repodata *data, Id handle)
1477 if (handle == SOLVID_META)
1481 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1486 return data->xattrs - handle;
1487 if (handle < data->start || handle >= data->end)
1488 repodata_extend(data, handle);
1490 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1491 return data->attrs + (handle - data->start);
1495 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1501 app = repodata_get_attrp(data, handle);
1506 for (pp = ap; *pp; pp += 2)
1507 /* Determine equality based on the name only, allows us to change
1508 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1509 if (data->keys[*pp].name == data->keys[keyid].name)
1522 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1532 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1536 keyid = repodata_key2id(data, key, 1);
1537 repodata_insert_keyid(data, solvid, keyid, val, 1);
1541 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1545 key.type = REPOKEY_TYPE_ID;
1547 key.storage = KEY_STORAGE_INCORE;
1548 repodata_set(data, solvid, &key, id);
1552 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1556 key.type = REPOKEY_TYPE_NUM;
1558 key.storage = KEY_STORAGE_INCORE;
1559 repodata_set(data, solvid, &key, (Id)num);
1563 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1567 if (data->localpool)
1568 id = stringpool_str2id(&data->spool, str, 1);
1570 id = str2id(data->repo->pool, str, 1);
1572 key.type = REPOKEY_TYPE_ID;
1574 key.storage = KEY_STORAGE_INCORE;
1575 repodata_set(data, solvid, &key, id);
1579 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1583 key.type = REPOKEY_TYPE_CONSTANT;
1584 key.size = constant;
1585 key.storage = KEY_STORAGE_INCORE;
1586 repodata_set(data, solvid, &key, 0);
1590 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1594 key.type = REPOKEY_TYPE_CONSTANTID;
1596 key.storage = KEY_STORAGE_INCORE;
1597 repodata_set(data, solvid, &key, 0);
1601 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1605 key.type = REPOKEY_TYPE_VOID;
1607 key.storage = KEY_STORAGE_INCORE;
1608 repodata_set(data, solvid, &key, 0);
1612 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1617 l = strlen(str) + 1;
1619 key.type = REPOKEY_TYPE_STR;
1621 key.storage = KEY_STORAGE_INCORE;
1622 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1623 memcpy(data->attrdata + data->attrdatalen, str, l);
1624 repodata_set(data, solvid, &key, data->attrdatalen);
1625 data->attrdatalen += l;
1629 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1632 Id *ida, *pp, **ppp;
1634 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1636 /* great! just append the new data */
1637 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1638 data->attriddatalen--; /* overwrite terminating 0 */
1639 data->lastdatalen += entrysize;
1642 ppp = repodata_get_attrp(data, handle);
1645 for (; *pp; pp += 2)
1646 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1650 /* not found. allocate new key */
1655 key.storage = KEY_STORAGE_INCORE;
1656 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1657 repodata_set(data, handle, &key, data->attriddatalen);
1658 data->lasthandle = 0; /* next time... */
1662 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1663 oldsize += entrysize;
1664 if (ida + 1 == data->attriddata + data->attriddatalen)
1666 /* this was the last entry, just append it */
1667 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1668 data->attriddatalen--; /* overwrite terminating 0 */
1672 /* too bad. move to back. */
1673 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1674 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1675 pp[1] = data->attriddatalen;
1676 data->attriddatalen += oldsize;
1678 data->lasthandle = handle;
1679 data->lastkey = *pp;
1680 data->lastdatalen = data->attriddatalen + entrysize + 1;
1684 checksumtype2len(Id type)
1688 case REPOKEY_TYPE_MD5:
1690 case REPOKEY_TYPE_SHA1:
1692 case REPOKEY_TYPE_SHA256:
1693 return SIZEOF_SHA256;
1700 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1701 const unsigned char *str)
1704 int l = checksumtype2len(type);
1711 key.storage = KEY_STORAGE_INCORE;
1712 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1713 memcpy(data->attrdata + data->attrdatalen, str, l);
1714 repodata_set(data, solvid, &key, data->attrdatalen);
1715 data->attrdatalen += l;
1719 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1722 for (i = 0; i < buflen; i++)
1724 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1725 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1726 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1737 buf[i] = (buf[i] << 4) | v;
1744 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1747 unsigned char buf[64];
1748 int l = checksumtype2len(type);
1752 if (hexstr2bytes(buf, str, l) != l)
1754 fprintf(stderr, "Invalid hex character in '%s'\n", str);
1757 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1761 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1766 l = checksumtype2len(type);
1769 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1770 for (i = 0; i < l; i++)
1772 unsigned char v = buf[i];
1773 unsigned char w = v >> 4;
1774 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1776 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1783 repodata_globalize_id(Repodata *data, Id id)
1785 if (!data || !data->localpool)
1787 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1791 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1795 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1797 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1798 data->attriddata[data->attriddatalen++] = dir;
1799 data->attriddata[data->attriddatalen++] = num;
1800 data->attriddata[data->attriddatalen++] = num2;
1801 data->attriddata[data->attriddatalen++] = 0;
1805 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1811 l = strlen(str) + 1;
1812 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1813 memcpy(data->attrdata + data->attrdatalen, str, l);
1814 stroff = data->attrdatalen;
1815 data->attrdatalen += l;
1818 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1820 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1821 data->attriddata[data->attriddatalen++] = dir;
1822 data->attriddata[data->attriddatalen++] = stroff;
1823 data->attriddata[data->attriddatalen++] = 0;
1827 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1830 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1832 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1833 data->attriddata[data->attriddatalen++] = id;
1834 data->attriddata[data->attriddatalen++] = 0;
1838 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1842 if (data->localpool)
1843 id = stringpool_str2id(&data->spool, str, 1);
1845 id = str2id(data->repo->pool, str, 1);
1846 repodata_add_idarray(data, solvid, keyname, id);
1850 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1852 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1853 data->attriddata[data->attriddatalen++] = ghandle;
1854 data->attriddata[data->attriddatalen++] = 0;
1858 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1860 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1861 data->attriddata[data->attriddatalen++] = ghandle;
1862 data->attriddata[data->attriddatalen++] = 0;
1866 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1869 if (dest == src || !(keyp = data->attrs[src]))
1871 for (; *keyp; keyp += 2)
1872 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1878 /**********************************************************************/
1880 /* unify with repo_write! */
1882 #define EXTDATA_BLOCK 1023
1890 data_addid(struct extdata *xd, Id x)
1893 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1894 dp = xd->buf + xd->len;
1899 *dp++ = (x >> 28) | 128;
1901 *dp++ = (x >> 21) | 128;
1902 *dp++ = (x >> 14) | 128;
1905 *dp++ = (x >> 7) | 128;
1907 xd->len = dp - xd->buf;
1911 data_addideof(struct extdata *xd, Id x, int eof)
1914 x = (x & 63) | ((x & ~63) << 1);
1915 data_addid(xd, (eof ? x: x | 64));
1919 data_addblob(struct extdata *xd, unsigned char *blob, int len)
1921 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
1922 memcpy(xd->buf + xd->len, blob, len);
1926 /*********************************/
1929 repodata_serialize_key(Repodata *data, struct extdata *newincore,
1930 struct extdata *newvincore,
1932 Repokey *key, Id val)
1934 /* Otherwise we have a new value. Parse it into the internal
1938 unsigned int oldvincorelen = 0;
1942 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1945 oldvincorelen = xd->len;
1949 case REPOKEY_TYPE_VOID:
1950 case REPOKEY_TYPE_CONSTANT:
1951 case REPOKEY_TYPE_CONSTANTID:
1953 case REPOKEY_TYPE_STR:
1954 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
1956 case REPOKEY_TYPE_MD5:
1957 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
1959 case REPOKEY_TYPE_SHA1:
1960 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
1962 case REPOKEY_TYPE_SHA256:
1963 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
1965 case REPOKEY_TYPE_ID:
1966 case REPOKEY_TYPE_NUM:
1967 case REPOKEY_TYPE_DIR:
1968 data_addid(xd, val);
1970 case REPOKEY_TYPE_IDARRAY:
1971 for (ida = data->attriddata + val; *ida; ida++)
1972 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
1974 case REPOKEY_TYPE_DIRNUMNUMARRAY:
1975 for (ida = data->attriddata + val; *ida; ida += 3)
1977 data_addid(xd, ida[0]);
1978 data_addid(xd, ida[1]);
1979 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
1982 case REPOKEY_TYPE_DIRSTRARRAY:
1983 for (ida = data->attriddata + val; *ida; ida += 2)
1985 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
1986 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
1989 case REPOKEY_TYPE_FIXARRAY:
1993 for (ida = data->attriddata + val; *ida; ida++)
1996 fprintf(stderr, "serialize struct %d\n", *ida);
1999 Id *kp = data->xattrs[-*ida];
2006 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2012 schemaid = repodata_schema2id(data, schema, 1);
2013 else if (schemaid != repodata_schema2id(data, schema, 0))
2015 fprintf(stderr, " not yet implemented: substructs with different schemas\n");
2019 fprintf(stderr, " schema %d\n", schemaid);
2024 data_addid(xd, num);
2025 data_addid(xd, schemaid);
2026 for (ida = data->attriddata + val; *ida; ida++)
2028 Id *kp = data->xattrs[-*ida];
2033 repodata_serialize_key(data, newincore, newvincore,
2034 schema, data->keys + *kp, kp[1]);
2039 case REPOKEY_TYPE_FLEXARRAY:
2042 for (ida = data->attriddata + val; *ida; ida++)
2044 data_addid(xd, num);
2045 for (ida = data->attriddata + val; *ida; ida++)
2047 Id *kp = data->xattrs[-*ida];
2050 data_addid(xd, 0); /* XXX */
2057 schemaid = repodata_schema2id(data, schema, 1);
2058 data_addid(xd, schemaid);
2059 kp = data->xattrs[-*ida];
2062 repodata_serialize_key(data, newincore, newvincore,
2063 schema, data->keys + *kp, kp[1]);
2069 fprintf(stderr, "don't know how to handle type %d\n", key->type);
2072 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2074 /* put offset/len in incore */
2075 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2076 oldvincorelen = xd->len - oldvincorelen;
2077 data_addid(newincore, oldvincorelen);
2082 repodata_internalize(Repodata *data)
2084 Repokey *key, solvkey;
2086 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2087 unsigned char *dp, *ndp;
2088 int newschema, oldcount;
2089 struct extdata newincore;
2090 struct extdata newvincore;
2093 if (!data->attrs && !data->xattrs)
2096 newvincore.buf = data->vincore;
2097 newvincore.len = data->vincorelen;
2099 /* find the solvables key, create if needed */
2100 memset(&solvkey, 0, sizeof(solvkey));
2101 solvkey.name = REPOSITORY_SOLVABLES;
2102 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2104 solvkey.storage = KEY_STORAGE_INCORE;
2105 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2107 schema = sat_malloc2(data->nkeys, sizeof(Id));
2108 seen = sat_malloc2(data->nkeys, sizeof(Id));
2110 /* Merge the data already existing (in data->schemata, ->incoredata and
2111 friends) with the new attributes in data->attrs[]. */
2112 nentry = data->end - data->start;
2113 memset(&newincore, 0, sizeof(newincore));
2114 data_addid(&newincore, 0); /* start data at offset 1 */
2116 data->mainschema = 0;
2117 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2119 /* join entry data */
2120 /* we start with the meta data, entry -1 */
2121 for (entry = -1; entry < nentry; entry++)
2123 memset(seen, 0, data->nkeys * sizeof(Id));
2125 dp = data->incoredata;
2128 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2129 dp = data_read_id(dp, &oldschema);
2132 fprintf(stderr, "oldschema %d\n", oldschema);
2133 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2134 fprintf(stderr, "schemadata %p\n", data->schemadata);
2136 /* seen: -1: old data 0: skipped >0: id + 1 */
2140 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2144 fprintf(stderr, "Inconsistent old data (key occured twice).\n");
2152 keyp = data->attrs ? data->attrs[entry] : 0;
2155 /* strip solvables key */
2157 for (sp = keyp = schema; *sp; sp++)
2158 if (*sp != solvkeyid)
2163 seen[solvkeyid] = 0;
2164 keyp = data->xattrs ? data->xattrs[1] : 0;
2167 for (; *keyp; keyp += 2)
2174 seen[*keyp] = keyp[1] + 1;
2176 if (entry < 0 && data->end != data->start)
2183 /* Ideally we'd like to sort the new schema here, to ensure
2184 schema equality independend of the ordering. We can't do that
2185 yet. For once see below (old ids need to come before new ids).
2186 An additional difficulty is that we also need to move
2187 the values with the keys. */
2188 schemaid = repodata_schema2id(data, schema, 1);
2190 schemaid = oldschema;
2193 /* Now create data blob. We walk through the (possibly new) schema
2194 and either copy over old data, or insert the new. */
2195 /* XXX Here we rely on the fact that the (new) schema has the form
2196 o1 o2 o3 o4 ... | n1 n2 n3 ...
2197 (oX being the old keyids (possibly overwritten), and nX being
2198 the new keyids). This rules out sorting the keyids in order
2199 to ensure a small schema count. */
2201 data->incoreoffset[entry] = newincore.len;
2202 data_addid(&newincore, schemaid);
2205 data->mainschema = schemaid;
2206 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2208 keypstart = data->schemadata + data->schemata[schemaid];
2209 for (keyp = keypstart; *keyp; keyp++)
2212 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2213 if (*keyp == solvkeyid)
2215 /* add flexarray entry count */
2216 data_addid(&newincore, data->end - data->start);
2219 key = data->keys + *keyp;
2221 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2226 /* Skip the data associated with this old key. */
2227 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2229 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2230 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2232 else if (key->storage == KEY_STORAGE_INCORE)
2233 ndp = data_skip_key(data, dp, key);
2236 if (seen[*keyp] == -1)
2238 /* If this key was an old one _and_ was not overwritten with
2239 a different value copy over the old value (we skipped it
2242 data_addblob(&newincore, dp, ndp - dp);
2245 else if (seen[*keyp])
2247 /* Otherwise we have a new value. Parse it into the internal
2249 repodata_serialize_key(data, &newincore, &newvincore,
2250 schema, key, seen[*keyp] - 1);
2254 if (entry >= 0 && data->attrs && data->attrs[entry])
2255 data->attrs[entry] = sat_free(data->attrs[entry]);
2257 /* free all xattrs */
2258 for (entry = 0; entry < data->nxattrs; entry++)
2259 if (data->xattrs[entry])
2260 sat_free(data->xattrs[entry]);
2261 data->xattrs = sat_free(data->xattrs);
2264 data->lasthandle = 0;
2266 data->lastdatalen = 0;
2269 repodata_free_schemahash(data);
2271 sat_free(data->incoredata);
2272 data->incoredata = newincore.buf;
2273 data->incoredatalen = newincore.len;
2274 data->incoredatafree = 0;
2276 sat_free(data->vincore);
2277 data->vincore = newvincore.buf;
2278 data->vincorelen = newvincore.len;
2280 data->attrs = sat_free(data->attrs);
2281 data->attrdata = sat_free(data->attrdata);
2282 data->attriddata = sat_free(data->attriddata);
2283 data->attrdatalen = 0;
2284 data->attriddatalen = 0;
2288 repodata_disable_paging(Repodata *data)
2290 if (maybe_load_repodata(data, 0))
2291 repopagestore_disable_paging(&data->store);
2295 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: