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));
972 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
979 di->keyname = keyname;
980 di->keynames[0] = keyname;
981 di->flags = flags & ~SEARCH_THISSOLVID;
990 dataiterator_jump_to_solvid(di, p);
993 di->repo = pool->repos[0];
994 di->state = di_enterrepo;
1000 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1004 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1006 di->state = di_bye; /* sorry */
1009 for (i = di->nkeynames + 1; i > 0; i--)
1010 di->keynames[i] = di->keynames[i - 1];
1011 di->keynames[0] = di->keyname = keyname;
1016 dataiterator_free(Dataiterator *di)
1018 if (di->matcher.match)
1019 datamatcher_free(&di->matcher);
1022 static inline unsigned char *
1023 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1025 Id *keyp = di->keyp;
1026 Repokey *keys = di->data->keys;
1029 for (keyp = di->keyp; *keyp; keyp++)
1030 if (keys[*keyp].name == keyname)
1034 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1042 dataiterator_step(Dataiterator *di)
1050 case di_enterrepo: di_enterrepo:
1051 if (!(di->flags & SEARCH_THISSOLVID))
1053 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1054 goto di_nextsolvable;
1058 case di_entersolvable: di_entersolvable:
1059 if (di->repodataid >= 0)
1061 di->repodataid = 0; /* reset repodata iterator */
1062 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1064 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1066 goto di_entersolvablekey;
1071 case di_enterrepodata: di_enterrepodata:
1072 if (di->repodataid >= 0)
1074 if (di->repodataid >= di->repo->nrepodata)
1075 goto di_nextsolvable;
1076 di->data = di->repo->repodata + di->repodataid;
1078 if (!maybe_load_repodata(di->data, di->keyname))
1079 goto di_nextrepodata;
1080 di->dp = solvid2data(di->data, di->solvid, &schema);
1082 goto di_nextrepodata;
1083 /* reset key iterator */
1084 di->keyp = di->data->schemadata + di->data->schemata[schema];
1087 case di_enterschema: di_enterschema:
1089 di->dp = dataiterator_find_keyname(di, di->keyname);
1090 if (!di->dp || !*di->keyp)
1094 goto di_nextrepodata;
1098 case di_enterkey: di_enterkey:
1100 di->key = di->data->keys + *di->keyp;
1101 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1104 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1106 if (di->nparents < di->nkeynames)
1112 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1114 di->state = di_nextkey;
1116 di->state = di_nextattr;
1119 case di_nextkey: di_nextkey:
1120 if (!di->keyname && *++di->keyp)
1126 case di_nextrepodata: di_nextrepodata:
1127 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1128 goto di_enterrepodata;
1131 case di_nextsolvable: di_nextsolvable:
1132 if (!(di->flags & SEARCH_THISSOLVID))
1135 di->solvid = di->repo->start;
1138 for (; di->solvid < di->repo->end; di->solvid++)
1140 if (di->pool->solvables[di->solvid].repo == di->repo)
1141 goto di_entersolvable;
1147 if (di->repoid >= 0)
1150 if (di->repoid < di->pool->nrepos)
1152 di->repo = di->pool->repos[di->repoid];
1162 case di_enterarray: di_enterarray:
1163 if (di->key->name == REPOSITORY_SOLVABLES)
1165 di->ddp = data_read_id(di->ddp, &di->kv.num);
1170 case di_nextarrayelement: di_nextarrayelement:
1173 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1174 if (di->kv.entry == di->kv.num)
1176 if (di->nparents < di->nkeynames)
1178 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1180 di->kv.str = (char *)di->ddp;
1182 di->state = di_nextkey;
1185 if (di->kv.entry == di->kv.num - 1)
1187 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1188 di->ddp = data_read_id(di->ddp, &di->kv.id);
1189 di->kv.str = (char *)di->ddp;
1190 if (di->nparents < di->nkeynames)
1192 if ((di->flags & SEARCH_SUB) != 0)
1193 di->state = di_entersub;
1195 di->state = di_nextarrayelement;
1198 case di_entersub: di_entersub:
1199 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1200 goto di_nextarrayelement; /* sorry, full */
1201 di->parents[di->nparents].kv = di->kv;
1202 di->parents[di->nparents].dp = di->dp;
1203 di->parents[di->nparents].keyp = di->keyp;
1204 di->dp = (unsigned char *)di->kv.str;
1205 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1206 memset(&di->kv, 0, sizeof(di->kv));
1207 di->kv.parent = &di->parents[di->nparents].kv;
1209 di->keyname = di->keynames[di->nparents];
1210 goto di_enterschema;
1212 case di_leavesub: di_leavesub:
1214 di->dp = di->parents[di->nparents].dp;
1215 di->kv = di->parents[di->nparents].kv;
1216 di->keyp = di->parents[di->nparents].keyp;
1217 di->key = di->data->keys + *di->keyp;
1218 di->ddp = (unsigned char *)di->kv.str;
1219 di->keyname = di->keynames[di->nparents];
1220 goto di_nextarrayelement;
1222 /* special solvable attr handling follows */
1224 case di_nextsolvableattr:
1225 di->kv.id = *di->idp++;
1230 di->state = di_nextsolvablekey;
1234 case di_nextsolvablekey: di_nextsolvablekey:
1235 if (di->keyname || di->key->name == RPM_RPMDBID)
1236 goto di_enterrepodata;
1240 case di_entersolvablekey: di_entersolvablekey:
1241 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1242 if (!di->idp || !di->idp[0])
1243 goto di_nextsolvablekey;
1244 di->kv.id = di->idp[0];
1245 di->kv.num = di->idp[0];
1246 if (!di->kv.eof && !di->idp[1])
1250 di->state = di_nextsolvablekey;
1252 di->state = di_nextsolvableattr;
1256 if (di->matcher.match)
1258 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1260 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1264 if (!datamatcher_match(&di->matcher, di->kv.str))
1267 /* found something! */
1273 dataiterator_entersub(Dataiterator *di)
1275 if (di->state == di_nextarrayelement)
1276 di->state = di_entersub;
1280 dataiterator_setpos(Dataiterator *di)
1284 pool_clear_pos(di->pool);
1287 di->pool->pos.solvid = di->solvid;
1288 di->pool->pos.repo = di->repo;
1289 di->pool->pos.repodataid = di->data - di->repo->repodata;
1290 di->pool->pos.schema = di->kv.id;
1291 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1295 dataiterator_setpos_parent(Dataiterator *di)
1299 pool_clear_pos(di->pool);
1302 di->pool->pos.solvid = di->solvid;
1303 di->pool->pos.repo = di->repo;
1304 di->pool->pos.repodataid = di->data - di->repo->repodata;
1305 di->pool->pos.schema = di->kv.parent->id;
1306 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1310 dataiterator_skip_attribute(Dataiterator *di)
1312 if (di->state == di_nextsolvableattr)
1313 di->state = di_nextsolvablekey;
1315 di->state = di_nextkey;
1319 dataiterator_skip_solvable(Dataiterator *di)
1321 di->state = di_nextsolvable;
1325 dataiterator_skip_repo(Dataiterator *di)
1327 di->state = di_nextrepo;
1331 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1334 if (solvid == SOLVID_POS)
1336 di->repo = di->pool->pos.repo;
1343 di->data = di->repo->repodata + di->pool->pos.repodataid;
1344 di->repodataid = -1;
1345 di->solvid = di->pool->pos.solvid;
1346 di->state = di_enterrepo;
1347 di->flags |= SEARCH_THISSOLVID;
1352 di->repo = di->pool->solvables[solvid].repo;
1355 else if (di->repoid >= 0)
1357 if (!di->pool->nrepos)
1362 di->repo = di->pool->repos[0];
1366 di->solvid = solvid;
1368 di->flags |= SEARCH_THISSOLVID;
1369 di->state = di_entersolvable;
1373 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1380 di->flags &= ~SEARCH_THISSOLVID;
1381 di->state = di_enterrepo;
1385 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1387 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1389 return datamatcher_match(ma, di->kv.str);
1393 dataiterator_match_obsolete(Dataiterator *di, int flags, const void *vmatch)
1395 Datamatcher matcher;
1397 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, flags))
1399 matcher = di->matcher;
1400 matcher.flags = flags;
1401 matcher.match = (void *)vmatch;
1402 return datamatcher_match(&matcher, di->kv.str);
1406 /************************************************************************
1407 * data modify functions
1410 /* extend repodata so that it includes solvables p */
1412 repodata_extend(Repodata *data, Id p)
1414 if (data->start == data->end)
1415 data->start = data->end = p;
1418 int old = data->end - data->start;
1419 int new = p - data->end + 1;
1422 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1423 memset(data->attrs + old, 0, new * sizeof(Id *));
1425 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1426 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1429 if (p < data->start)
1431 int old = data->end - data->start;
1432 int new = data->start - p;
1435 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1436 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1437 memset(data->attrs, 0, new * sizeof(Id *));
1439 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1440 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1441 memset(data->incoreoffset, 0, new * sizeof(Id));
1447 repodata_extend_block(Repodata *data, Id start, Id num)
1451 if (!data->incoreoffset)
1453 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1454 data->start = start;
1455 data->end = start + num;
1458 repodata_extend(data, start);
1460 repodata_extend(data, start + num - 1);
1463 /**********************************************************************/
1465 #define REPODATA_ATTRS_BLOCK 63
1466 #define REPODATA_ATTRDATA_BLOCK 1023
1467 #define REPODATA_ATTRIDDATA_BLOCK 63
1471 repodata_new_handle(Repodata *data)
1475 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1478 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1479 data->xattrs[data->nxattrs] = 0;
1480 return -(data->nxattrs++);
1484 repodata_get_attrp(Repodata *data, Id handle)
1486 if (handle == SOLVID_META)
1490 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1495 return data->xattrs - handle;
1496 if (handle < data->start || handle >= data->end)
1497 repodata_extend(data, handle);
1499 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1500 return data->attrs + (handle - data->start);
1504 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1510 app = repodata_get_attrp(data, handle);
1515 for (pp = ap; *pp; pp += 2)
1516 /* Determine equality based on the name only, allows us to change
1517 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1518 if (data->keys[*pp].name == data->keys[keyid].name)
1531 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1541 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1545 keyid = repodata_key2id(data, key, 1);
1546 repodata_insert_keyid(data, solvid, keyid, val, 1);
1550 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1554 key.type = REPOKEY_TYPE_ID;
1556 key.storage = KEY_STORAGE_INCORE;
1557 repodata_set(data, solvid, &key, id);
1561 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1565 key.type = REPOKEY_TYPE_NUM;
1567 key.storage = KEY_STORAGE_INCORE;
1568 repodata_set(data, solvid, &key, (Id)num);
1572 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1576 if (data->localpool)
1577 id = stringpool_str2id(&data->spool, str, 1);
1579 id = str2id(data->repo->pool, str, 1);
1581 key.type = REPOKEY_TYPE_ID;
1583 key.storage = KEY_STORAGE_INCORE;
1584 repodata_set(data, solvid, &key, id);
1588 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1592 key.type = REPOKEY_TYPE_CONSTANT;
1593 key.size = constant;
1594 key.storage = KEY_STORAGE_INCORE;
1595 repodata_set(data, solvid, &key, 0);
1599 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1603 key.type = REPOKEY_TYPE_CONSTANTID;
1605 key.storage = KEY_STORAGE_INCORE;
1606 repodata_set(data, solvid, &key, 0);
1610 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1614 key.type = REPOKEY_TYPE_VOID;
1616 key.storage = KEY_STORAGE_INCORE;
1617 repodata_set(data, solvid, &key, 0);
1621 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1626 l = strlen(str) + 1;
1628 key.type = REPOKEY_TYPE_STR;
1630 key.storage = KEY_STORAGE_INCORE;
1631 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1632 memcpy(data->attrdata + data->attrdatalen, str, l);
1633 repodata_set(data, solvid, &key, data->attrdatalen);
1634 data->attrdatalen += l;
1638 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1641 Id *ida, *pp, **ppp;
1643 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1645 /* great! just append the new data */
1646 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1647 data->attriddatalen--; /* overwrite terminating 0 */
1648 data->lastdatalen += entrysize;
1651 ppp = repodata_get_attrp(data, handle);
1654 for (; *pp; pp += 2)
1655 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1659 /* not found. allocate new key */
1664 key.storage = KEY_STORAGE_INCORE;
1665 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1666 repodata_set(data, handle, &key, data->attriddatalen);
1667 data->lasthandle = 0; /* next time... */
1671 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1672 oldsize += entrysize;
1673 if (ida + 1 == data->attriddata + data->attriddatalen)
1675 /* this was the last entry, just append it */
1676 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1677 data->attriddatalen--; /* overwrite terminating 0 */
1681 /* too bad. move to back. */
1682 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1683 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1684 pp[1] = data->attriddatalen;
1685 data->attriddatalen += oldsize;
1687 data->lasthandle = handle;
1688 data->lastkey = *pp;
1689 data->lastdatalen = data->attriddatalen + entrysize + 1;
1693 checksumtype2len(Id type)
1697 case REPOKEY_TYPE_MD5:
1699 case REPOKEY_TYPE_SHA1:
1701 case REPOKEY_TYPE_SHA256:
1702 return SIZEOF_SHA256;
1709 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1710 const unsigned char *str)
1713 int l = checksumtype2len(type);
1720 key.storage = KEY_STORAGE_INCORE;
1721 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1722 memcpy(data->attrdata + data->attrdatalen, str, l);
1723 repodata_set(data, solvid, &key, data->attrdatalen);
1724 data->attrdatalen += l;
1728 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1731 for (i = 0; i < buflen; i++)
1733 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1734 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1735 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1746 buf[i] = (buf[i] << 4) | v;
1753 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1756 unsigned char buf[64];
1757 int l = checksumtype2len(type);
1761 if (hexstr2bytes(buf, str, l) != l)
1763 fprintf(stderr, "Invalid hex character in '%s'\n", str);
1766 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1770 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1775 l = checksumtype2len(type);
1778 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1779 for (i = 0; i < l; i++)
1781 unsigned char v = buf[i];
1782 unsigned char w = v >> 4;
1783 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1785 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1792 repodata_globalize_id(Repodata *data, Id id)
1794 if (!data || !data->localpool)
1796 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1800 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1804 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1806 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1807 data->attriddata[data->attriddatalen++] = dir;
1808 data->attriddata[data->attriddatalen++] = num;
1809 data->attriddata[data->attriddatalen++] = num2;
1810 data->attriddata[data->attriddatalen++] = 0;
1814 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1820 l = strlen(str) + 1;
1821 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1822 memcpy(data->attrdata + data->attrdatalen, str, l);
1823 stroff = data->attrdatalen;
1824 data->attrdatalen += l;
1827 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1829 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1830 data->attriddata[data->attriddatalen++] = dir;
1831 data->attriddata[data->attriddatalen++] = stroff;
1832 data->attriddata[data->attriddatalen++] = 0;
1836 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1839 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1841 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1842 data->attriddata[data->attriddatalen++] = id;
1843 data->attriddata[data->attriddatalen++] = 0;
1847 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1851 if (data->localpool)
1852 id = stringpool_str2id(&data->spool, str, 1);
1854 id = str2id(data->repo->pool, str, 1);
1855 repodata_add_idarray(data, solvid, keyname, id);
1859 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1861 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1862 data->attriddata[data->attriddatalen++] = ghandle;
1863 data->attriddata[data->attriddatalen++] = 0;
1867 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1869 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1870 data->attriddata[data->attriddatalen++] = ghandle;
1871 data->attriddata[data->attriddatalen++] = 0;
1875 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1878 if (dest == src || !(keyp = data->attrs[src]))
1880 for (; *keyp; keyp += 2)
1881 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1887 /**********************************************************************/
1889 /* unify with repo_write! */
1891 #define EXTDATA_BLOCK 1023
1899 data_addid(struct extdata *xd, Id x)
1902 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1903 dp = xd->buf + xd->len;
1908 *dp++ = (x >> 28) | 128;
1910 *dp++ = (x >> 21) | 128;
1911 *dp++ = (x >> 14) | 128;
1914 *dp++ = (x >> 7) | 128;
1916 xd->len = dp - xd->buf;
1920 data_addideof(struct extdata *xd, Id x, int eof)
1923 x = (x & 63) | ((x & ~63) << 1);
1924 data_addid(xd, (eof ? x: x | 64));
1928 data_addblob(struct extdata *xd, unsigned char *blob, int len)
1930 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
1931 memcpy(xd->buf + xd->len, blob, len);
1935 /*********************************/
1938 repodata_serialize_key(Repodata *data, struct extdata *newincore,
1939 struct extdata *newvincore,
1941 Repokey *key, Id val)
1943 /* Otherwise we have a new value. Parse it into the internal
1947 unsigned int oldvincorelen = 0;
1951 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1954 oldvincorelen = xd->len;
1958 case REPOKEY_TYPE_VOID:
1959 case REPOKEY_TYPE_CONSTANT:
1960 case REPOKEY_TYPE_CONSTANTID:
1962 case REPOKEY_TYPE_STR:
1963 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
1965 case REPOKEY_TYPE_MD5:
1966 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
1968 case REPOKEY_TYPE_SHA1:
1969 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
1971 case REPOKEY_TYPE_SHA256:
1972 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
1974 case REPOKEY_TYPE_ID:
1975 case REPOKEY_TYPE_NUM:
1976 case REPOKEY_TYPE_DIR:
1977 data_addid(xd, val);
1979 case REPOKEY_TYPE_IDARRAY:
1980 for (ida = data->attriddata + val; *ida; ida++)
1981 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
1983 case REPOKEY_TYPE_DIRNUMNUMARRAY:
1984 for (ida = data->attriddata + val; *ida; ida += 3)
1986 data_addid(xd, ida[0]);
1987 data_addid(xd, ida[1]);
1988 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
1991 case REPOKEY_TYPE_DIRSTRARRAY:
1992 for (ida = data->attriddata + val; *ida; ida += 2)
1994 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
1995 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
1998 case REPOKEY_TYPE_FIXARRAY:
2002 for (ida = data->attriddata + val; *ida; ida++)
2005 fprintf(stderr, "serialize struct %d\n", *ida);
2008 Id *kp = data->xattrs[-*ida];
2015 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2021 schemaid = repodata_schema2id(data, schema, 1);
2022 else if (schemaid != repodata_schema2id(data, schema, 0))
2024 fprintf(stderr, " not yet implemented: substructs with different schemas\n");
2028 fprintf(stderr, " schema %d\n", schemaid);
2033 data_addid(xd, num);
2034 data_addid(xd, schemaid);
2035 for (ida = data->attriddata + val; *ida; ida++)
2037 Id *kp = data->xattrs[-*ida];
2042 repodata_serialize_key(data, newincore, newvincore,
2043 schema, data->keys + *kp, kp[1]);
2048 case REPOKEY_TYPE_FLEXARRAY:
2051 for (ida = data->attriddata + val; *ida; ida++)
2053 data_addid(xd, num);
2054 for (ida = data->attriddata + val; *ida; ida++)
2056 Id *kp = data->xattrs[-*ida];
2059 data_addid(xd, 0); /* XXX */
2066 schemaid = repodata_schema2id(data, schema, 1);
2067 data_addid(xd, schemaid);
2068 kp = data->xattrs[-*ida];
2071 repodata_serialize_key(data, newincore, newvincore,
2072 schema, data->keys + *kp, kp[1]);
2078 fprintf(stderr, "don't know how to handle type %d\n", key->type);
2081 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2083 /* put offset/len in incore */
2084 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2085 oldvincorelen = xd->len - oldvincorelen;
2086 data_addid(newincore, oldvincorelen);
2091 repodata_internalize(Repodata *data)
2093 Repokey *key, solvkey;
2095 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2096 unsigned char *dp, *ndp;
2097 int newschema, oldcount;
2098 struct extdata newincore;
2099 struct extdata newvincore;
2102 if (!data->attrs && !data->xattrs)
2105 newvincore.buf = data->vincore;
2106 newvincore.len = data->vincorelen;
2108 /* find the solvables key, create if needed */
2109 memset(&solvkey, 0, sizeof(solvkey));
2110 solvkey.name = REPOSITORY_SOLVABLES;
2111 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2113 solvkey.storage = KEY_STORAGE_INCORE;
2114 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2116 schema = sat_malloc2(data->nkeys, sizeof(Id));
2117 seen = sat_malloc2(data->nkeys, sizeof(Id));
2119 /* Merge the data already existing (in data->schemata, ->incoredata and
2120 friends) with the new attributes in data->attrs[]. */
2121 nentry = data->end - data->start;
2122 memset(&newincore, 0, sizeof(newincore));
2123 data_addid(&newincore, 0); /* start data at offset 1 */
2125 data->mainschema = 0;
2126 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2128 /* join entry data */
2129 /* we start with the meta data, entry -1 */
2130 for (entry = -1; entry < nentry; entry++)
2132 memset(seen, 0, data->nkeys * sizeof(Id));
2134 dp = data->incoredata;
2137 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2138 dp = data_read_id(dp, &oldschema);
2141 fprintf(stderr, "oldschema %d\n", oldschema);
2142 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2143 fprintf(stderr, "schemadata %p\n", data->schemadata);
2145 /* seen: -1: old data 0: skipped >0: id + 1 */
2149 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2153 fprintf(stderr, "Inconsistent old data (key occured twice).\n");
2161 keyp = data->attrs ? data->attrs[entry] : 0;
2164 /* strip solvables key */
2166 for (sp = keyp = schema; *sp; sp++)
2167 if (*sp != solvkeyid)
2172 seen[solvkeyid] = 0;
2173 keyp = data->xattrs ? data->xattrs[1] : 0;
2176 for (; *keyp; keyp += 2)
2183 seen[*keyp] = keyp[1] + 1;
2185 if (entry < 0 && data->end != data->start)
2192 /* Ideally we'd like to sort the new schema here, to ensure
2193 schema equality independend of the ordering. We can't do that
2194 yet. For once see below (old ids need to come before new ids).
2195 An additional difficulty is that we also need to move
2196 the values with the keys. */
2197 schemaid = repodata_schema2id(data, schema, 1);
2199 schemaid = oldschema;
2202 /* Now create data blob. We walk through the (possibly new) schema
2203 and either copy over old data, or insert the new. */
2204 /* XXX Here we rely on the fact that the (new) schema has the form
2205 o1 o2 o3 o4 ... | n1 n2 n3 ...
2206 (oX being the old keyids (possibly overwritten), and nX being
2207 the new keyids). This rules out sorting the keyids in order
2208 to ensure a small schema count. */
2210 data->incoreoffset[entry] = newincore.len;
2211 data_addid(&newincore, schemaid);
2214 data->mainschema = schemaid;
2215 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2217 keypstart = data->schemadata + data->schemata[schemaid];
2218 for (keyp = keypstart; *keyp; keyp++)
2221 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2222 if (*keyp == solvkeyid)
2224 /* add flexarray entry count */
2225 data_addid(&newincore, data->end - data->start);
2228 key = data->keys + *keyp;
2230 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2235 /* Skip the data associated with this old key. */
2236 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2238 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2239 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2241 else if (key->storage == KEY_STORAGE_INCORE)
2242 ndp = data_skip_key(data, dp, key);
2245 if (seen[*keyp] == -1)
2247 /* If this key was an old one _and_ was not overwritten with
2248 a different value copy over the old value (we skipped it
2251 data_addblob(&newincore, dp, ndp - dp);
2254 else if (seen[*keyp])
2256 /* Otherwise we have a new value. Parse it into the internal
2258 repodata_serialize_key(data, &newincore, &newvincore,
2259 schema, key, seen[*keyp] - 1);
2263 if (entry >= 0 && data->attrs && data->attrs[entry])
2264 data->attrs[entry] = sat_free(data->attrs[entry]);
2266 /* free all xattrs */
2267 for (entry = 0; entry < data->nxattrs; entry++)
2268 if (data->xattrs[entry])
2269 sat_free(data->xattrs[entry]);
2270 data->xattrs = sat_free(data->xattrs);
2273 data->lasthandle = 0;
2275 data->lastdatalen = 0;
2278 repodata_free_schemahash(data);
2280 sat_free(data->incoredata);
2281 data->incoredata = newincore.buf;
2282 data->incoredatalen = newincore.len;
2283 data->incoredatafree = 0;
2285 sat_free(data->vincore);
2286 data->vincore = newvincore.buf;
2287 data->vincorelen = newvincore.len;
2289 data->attrs = sat_free(data->attrs);
2290 data->attrdata = sat_free(data->attrdata);
2291 data->attriddata = sat_free(data->attriddata);
2292 data->attrdatalen = 0;
2293 data->attriddatalen = 0;
2297 repodata_disable_paging(Repodata *data)
2299 if (maybe_load_repodata(data, 0))
2300 repopagestore_disable_paging(&data->store);
2304 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: