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))
955 /* see repo.h for documentation */
957 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
959 memset(di, 0, sizeof(*di));
963 fprintf(stderr, "dataiterator_init: no Pool given\n");
969 if (repo->pool != pool)
971 fprintf(stderr, "dataiterator_init: repo from different pool\n");
980 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
987 di->keyname = keyname;
988 di->keynames[0] = keyname;
989 di->flags = flags & ~SEARCH_THISSOLVID;
998 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:
1059 if (!(di->flags & SEARCH_THISSOLVID))
1061 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1062 goto di_nextsolvable;
1066 case di_entersolvable: di_entersolvable:
1067 if (di->repodataid >= 0)
1069 di->repodataid = 0; /* reset repodata iterator */
1070 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1072 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1074 goto di_entersolvablekey;
1079 case di_enterrepodata: di_enterrepodata:
1080 if (di->repodataid >= 0)
1082 if (di->repodataid >= di->repo->nrepodata)
1083 goto di_nextsolvable;
1084 di->data = di->repo->repodata + di->repodataid;
1086 if (!maybe_load_repodata(di->data, di->keyname))
1087 goto di_nextrepodata;
1088 di->dp = solvid2data(di->data, di->solvid, &schema);
1090 goto di_nextrepodata;
1091 /* reset key iterator */
1092 di->keyp = di->data->schemadata + di->data->schemata[schema];
1095 case di_enterschema: di_enterschema:
1097 di->dp = dataiterator_find_keyname(di, di->keyname);
1098 if (!di->dp || !*di->keyp)
1102 goto di_nextrepodata;
1106 case di_enterkey: di_enterkey:
1108 di->key = di->data->keys + *di->keyp;
1109 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1112 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1114 if (di->nparents < di->nkeynames)
1120 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1122 di->state = di_nextkey;
1124 di->state = di_nextattr;
1127 case di_nextkey: di_nextkey:
1128 if (!di->keyname && *++di->keyp)
1134 case di_nextrepodata: di_nextrepodata:
1135 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1136 goto di_enterrepodata;
1139 case di_nextsolvable: di_nextsolvable:
1140 if (!(di->flags & SEARCH_THISSOLVID))
1143 di->solvid = di->repo->start;
1146 for (; di->solvid < di->repo->end; di->solvid++)
1148 if (di->pool->solvables[di->solvid].repo == di->repo)
1149 goto di_entersolvable;
1155 if (di->repoid >= 0)
1158 if (di->repoid < di->pool->nrepos)
1160 di->repo = di->pool->repos[di->repoid];
1170 case di_enterarray: di_enterarray:
1171 if (di->key->name == REPOSITORY_SOLVABLES)
1173 di->ddp = data_read_id(di->ddp, &di->kv.num);
1178 case di_nextarrayelement: di_nextarrayelement:
1181 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1182 if (di->kv.entry == di->kv.num)
1184 if (di->nparents < di->nkeynames)
1186 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1188 di->kv.str = (char *)di->ddp;
1190 di->state = di_nextkey;
1193 if (di->kv.entry == di->kv.num - 1)
1195 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1196 di->ddp = data_read_id(di->ddp, &di->kv.id);
1197 di->kv.str = (char *)di->ddp;
1198 if (di->nparents < di->nkeynames)
1200 if ((di->flags & SEARCH_SUB) != 0)
1201 di->state = di_entersub;
1203 di->state = di_nextarrayelement;
1206 case di_entersub: di_entersub:
1207 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1208 goto di_nextarrayelement; /* sorry, full */
1209 di->parents[di->nparents].kv = di->kv;
1210 di->parents[di->nparents].dp = di->dp;
1211 di->parents[di->nparents].keyp = di->keyp;
1212 di->dp = (unsigned char *)di->kv.str;
1213 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1214 memset(&di->kv, 0, sizeof(di->kv));
1215 di->kv.parent = &di->parents[di->nparents].kv;
1217 di->keyname = di->keynames[di->nparents];
1218 goto di_enterschema;
1220 case di_leavesub: di_leavesub:
1222 di->dp = di->parents[di->nparents].dp;
1223 di->kv = di->parents[di->nparents].kv;
1224 di->keyp = di->parents[di->nparents].keyp;
1225 di->key = di->data->keys + *di->keyp;
1226 di->ddp = (unsigned char *)di->kv.str;
1227 di->keyname = di->keynames[di->nparents];
1228 goto di_nextarrayelement;
1230 /* special solvable attr handling follows */
1232 case di_nextsolvableattr:
1233 di->kv.id = *di->idp++;
1238 di->state = di_nextsolvablekey;
1242 case di_nextsolvablekey: di_nextsolvablekey:
1243 if (di->keyname || di->key->name == RPM_RPMDBID)
1244 goto di_enterrepodata;
1248 case di_entersolvablekey: di_entersolvablekey:
1249 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1250 if (!di->idp || !di->idp[0])
1251 goto di_nextsolvablekey;
1252 di->kv.id = di->idp[0];
1253 di->kv.num = di->idp[0];
1254 if (!di->kv.eof && !di->idp[1])
1258 di->state = di_nextsolvablekey;
1260 di->state = di_nextsolvableattr;
1264 if (di->matcher.match)
1266 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1268 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1272 if (!datamatcher_match(&di->matcher, di->kv.str))
1275 /* found something! */
1281 dataiterator_entersub(Dataiterator *di)
1283 if (di->state == di_nextarrayelement)
1284 di->state = di_entersub;
1288 dataiterator_setpos(Dataiterator *di)
1292 pool_clear_pos(di->pool);
1295 di->pool->pos.solvid = di->solvid;
1296 di->pool->pos.repo = di->repo;
1297 di->pool->pos.repodataid = di->data - di->repo->repodata;
1298 di->pool->pos.schema = di->kv.id;
1299 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1303 dataiterator_setpos_parent(Dataiterator *di)
1307 pool_clear_pos(di->pool);
1310 di->pool->pos.solvid = di->solvid;
1311 di->pool->pos.repo = di->repo;
1312 di->pool->pos.repodataid = di->data - di->repo->repodata;
1313 di->pool->pos.schema = di->kv.parent->id;
1314 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1318 dataiterator_skip_attribute(Dataiterator *di)
1320 if (di->state == di_nextsolvableattr)
1321 di->state = di_nextsolvablekey;
1323 di->state = di_nextkey;
1327 dataiterator_skip_solvable(Dataiterator *di)
1329 di->state = di_nextsolvable;
1333 dataiterator_skip_repo(Dataiterator *di)
1335 di->state = di_nextrepo;
1339 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1342 if (solvid == SOLVID_POS)
1344 di->repo = di->pool->pos.repo;
1351 di->data = di->repo->repodata + di->pool->pos.repodataid;
1352 di->repodataid = -1;
1353 di->solvid = di->pool->pos.solvid;
1354 di->state = di_enterrepo;
1355 di->flags |= SEARCH_THISSOLVID;
1360 di->repo = di->pool->solvables[solvid].repo;
1363 else if (di->repoid >= 0)
1365 if (!di->pool->nrepos)
1370 di->repo = di->pool->repos[0];
1374 di->solvid = solvid;
1376 di->flags |= SEARCH_THISSOLVID;
1377 di->state = di_entersolvable;
1381 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1388 di->flags &= ~SEARCH_THISSOLVID;
1389 di->state = di_enterrepo;
1393 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1395 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1397 return datamatcher_match(ma, di->kv.str);
1401 dataiterator_match_obsolete(Dataiterator *di, int flags, const void *vmatch)
1403 Datamatcher matcher;
1405 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, flags))
1407 matcher = di->matcher;
1408 matcher.flags = flags;
1409 matcher.match = (void *)vmatch;
1410 return datamatcher_match(&matcher, di->kv.str);
1414 /************************************************************************
1415 * data modify functions
1418 /* extend repodata so that it includes solvables p */
1420 repodata_extend(Repodata *data, Id p)
1422 if (data->start == data->end)
1423 data->start = data->end = p;
1426 int old = data->end - data->start;
1427 int new = p - data->end + 1;
1430 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1431 memset(data->attrs + old, 0, new * sizeof(Id *));
1433 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1434 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1437 if (p < data->start)
1439 int old = data->end - data->start;
1440 int new = data->start - p;
1443 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1444 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1445 memset(data->attrs, 0, new * sizeof(Id *));
1447 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1448 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1449 memset(data->incoreoffset, 0, new * sizeof(Id));
1455 repodata_extend_block(Repodata *data, Id start, Id num)
1459 if (!data->incoreoffset)
1461 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1462 data->start = start;
1463 data->end = start + num;
1466 repodata_extend(data, start);
1468 repodata_extend(data, start + num - 1);
1471 /**********************************************************************/
1473 #define REPODATA_ATTRS_BLOCK 63
1474 #define REPODATA_ATTRDATA_BLOCK 1023
1475 #define REPODATA_ATTRIDDATA_BLOCK 63
1479 repodata_new_handle(Repodata *data)
1483 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1486 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1487 data->xattrs[data->nxattrs] = 0;
1488 return -(data->nxattrs++);
1492 repodata_get_attrp(Repodata *data, Id handle)
1494 if (handle == SOLVID_META)
1498 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1503 return data->xattrs - handle;
1504 if (handle < data->start || handle >= data->end)
1505 repodata_extend(data, handle);
1507 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1508 return data->attrs + (handle - data->start);
1512 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1518 app = repodata_get_attrp(data, handle);
1523 for (pp = ap; *pp; pp += 2)
1524 /* Determine equality based on the name only, allows us to change
1525 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1526 if (data->keys[*pp].name == data->keys[keyid].name)
1539 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1549 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1553 keyid = repodata_key2id(data, key, 1);
1554 repodata_insert_keyid(data, solvid, keyid, val, 1);
1558 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1562 key.type = REPOKEY_TYPE_ID;
1564 key.storage = KEY_STORAGE_INCORE;
1565 repodata_set(data, solvid, &key, id);
1569 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1573 key.type = REPOKEY_TYPE_NUM;
1575 key.storage = KEY_STORAGE_INCORE;
1576 repodata_set(data, solvid, &key, (Id)num);
1580 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1584 if (data->localpool)
1585 id = stringpool_str2id(&data->spool, str, 1);
1587 id = str2id(data->repo->pool, str, 1);
1589 key.type = REPOKEY_TYPE_ID;
1591 key.storage = KEY_STORAGE_INCORE;
1592 repodata_set(data, solvid, &key, id);
1596 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1600 key.type = REPOKEY_TYPE_CONSTANT;
1601 key.size = constant;
1602 key.storage = KEY_STORAGE_INCORE;
1603 repodata_set(data, solvid, &key, 0);
1607 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1611 key.type = REPOKEY_TYPE_CONSTANTID;
1613 key.storage = KEY_STORAGE_INCORE;
1614 repodata_set(data, solvid, &key, 0);
1618 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1622 key.type = REPOKEY_TYPE_VOID;
1624 key.storage = KEY_STORAGE_INCORE;
1625 repodata_set(data, solvid, &key, 0);
1629 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1634 l = strlen(str) + 1;
1636 key.type = REPOKEY_TYPE_STR;
1638 key.storage = KEY_STORAGE_INCORE;
1639 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1640 memcpy(data->attrdata + data->attrdatalen, str, l);
1641 repodata_set(data, solvid, &key, data->attrdatalen);
1642 data->attrdatalen += l;
1646 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1649 Id *ida, *pp, **ppp;
1651 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1653 /* great! just append the new data */
1654 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1655 data->attriddatalen--; /* overwrite terminating 0 */
1656 data->lastdatalen += entrysize;
1659 ppp = repodata_get_attrp(data, handle);
1662 for (; *pp; pp += 2)
1663 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1667 /* not found. allocate new key */
1672 key.storage = KEY_STORAGE_INCORE;
1673 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1674 repodata_set(data, handle, &key, data->attriddatalen);
1675 data->lasthandle = 0; /* next time... */
1679 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1680 oldsize += entrysize;
1681 if (ida + 1 == data->attriddata + data->attriddatalen)
1683 /* this was the last entry, just append it */
1684 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1685 data->attriddatalen--; /* overwrite terminating 0 */
1689 /* too bad. move to back. */
1690 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1691 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1692 pp[1] = data->attriddatalen;
1693 data->attriddatalen += oldsize;
1695 data->lasthandle = handle;
1696 data->lastkey = *pp;
1697 data->lastdatalen = data->attriddatalen + entrysize + 1;
1701 checksumtype2len(Id type)
1705 case REPOKEY_TYPE_MD5:
1707 case REPOKEY_TYPE_SHA1:
1709 case REPOKEY_TYPE_SHA256:
1710 return SIZEOF_SHA256;
1717 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1718 const unsigned char *str)
1721 int l = checksumtype2len(type);
1728 key.storage = KEY_STORAGE_INCORE;
1729 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1730 memcpy(data->attrdata + data->attrdatalen, str, l);
1731 repodata_set(data, solvid, &key, data->attrdatalen);
1732 data->attrdatalen += l;
1736 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1739 for (i = 0; i < buflen; i++)
1741 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1742 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1743 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1754 buf[i] = (buf[i] << 4) | v;
1761 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1764 unsigned char buf[64];
1765 int l = checksumtype2len(type);
1769 if (hexstr2bytes(buf, str, l) != l)
1771 fprintf(stderr, "Invalid hex character in '%s'\n", str);
1774 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1778 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1783 l = checksumtype2len(type);
1786 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1787 for (i = 0; i < l; i++)
1789 unsigned char v = buf[i];
1790 unsigned char w = v >> 4;
1791 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1793 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1800 repodata_globalize_id(Repodata *data, Id id)
1802 if (!data || !data->localpool)
1804 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1808 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1812 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1814 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1815 data->attriddata[data->attriddatalen++] = dir;
1816 data->attriddata[data->attriddatalen++] = num;
1817 data->attriddata[data->attriddatalen++] = num2;
1818 data->attriddata[data->attriddatalen++] = 0;
1822 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1828 l = strlen(str) + 1;
1829 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1830 memcpy(data->attrdata + data->attrdatalen, str, l);
1831 stroff = data->attrdatalen;
1832 data->attrdatalen += l;
1835 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1837 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1838 data->attriddata[data->attriddatalen++] = dir;
1839 data->attriddata[data->attriddatalen++] = stroff;
1840 data->attriddata[data->attriddatalen++] = 0;
1844 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1847 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1849 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1850 data->attriddata[data->attriddatalen++] = id;
1851 data->attriddata[data->attriddatalen++] = 0;
1855 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1859 if (data->localpool)
1860 id = stringpool_str2id(&data->spool, str, 1);
1862 id = str2id(data->repo->pool, str, 1);
1863 repodata_add_idarray(data, solvid, keyname, id);
1867 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1869 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1870 data->attriddata[data->attriddatalen++] = ghandle;
1871 data->attriddata[data->attriddatalen++] = 0;
1875 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1877 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1878 data->attriddata[data->attriddatalen++] = ghandle;
1879 data->attriddata[data->attriddatalen++] = 0;
1883 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1886 if (dest == src || !(keyp = data->attrs[src]))
1888 for (; *keyp; keyp += 2)
1889 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1895 /**********************************************************************/
1897 /* unify with repo_write! */
1899 #define EXTDATA_BLOCK 1023
1907 data_addid(struct extdata *xd, Id x)
1910 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1911 dp = xd->buf + xd->len;
1916 *dp++ = (x >> 28) | 128;
1918 *dp++ = (x >> 21) | 128;
1919 *dp++ = (x >> 14) | 128;
1922 *dp++ = (x >> 7) | 128;
1924 xd->len = dp - xd->buf;
1928 data_addideof(struct extdata *xd, Id x, int eof)
1931 x = (x & 63) | ((x & ~63) << 1);
1932 data_addid(xd, (eof ? x: x | 64));
1936 data_addblob(struct extdata *xd, unsigned char *blob, int len)
1938 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
1939 memcpy(xd->buf + xd->len, blob, len);
1943 /*********************************/
1946 repodata_serialize_key(Repodata *data, struct extdata *newincore,
1947 struct extdata *newvincore,
1949 Repokey *key, Id val)
1951 /* Otherwise we have a new value. Parse it into the internal
1955 unsigned int oldvincorelen = 0;
1959 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1962 oldvincorelen = xd->len;
1966 case REPOKEY_TYPE_VOID:
1967 case REPOKEY_TYPE_CONSTANT:
1968 case REPOKEY_TYPE_CONSTANTID:
1970 case REPOKEY_TYPE_STR:
1971 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
1973 case REPOKEY_TYPE_MD5:
1974 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
1976 case REPOKEY_TYPE_SHA1:
1977 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
1979 case REPOKEY_TYPE_SHA256:
1980 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
1982 case REPOKEY_TYPE_ID:
1983 case REPOKEY_TYPE_NUM:
1984 case REPOKEY_TYPE_DIR:
1985 data_addid(xd, val);
1987 case REPOKEY_TYPE_IDARRAY:
1988 for (ida = data->attriddata + val; *ida; ida++)
1989 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
1991 case REPOKEY_TYPE_DIRNUMNUMARRAY:
1992 for (ida = data->attriddata + val; *ida; ida += 3)
1994 data_addid(xd, ida[0]);
1995 data_addid(xd, ida[1]);
1996 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
1999 case REPOKEY_TYPE_DIRSTRARRAY:
2000 for (ida = data->attriddata + val; *ida; ida += 2)
2002 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2003 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2006 case REPOKEY_TYPE_FIXARRAY:
2010 for (ida = data->attriddata + val; *ida; ida++)
2013 fprintf(stderr, "serialize struct %d\n", *ida);
2016 Id *kp = data->xattrs[-*ida];
2023 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2029 schemaid = repodata_schema2id(data, schema, 1);
2030 else if (schemaid != repodata_schema2id(data, schema, 0))
2032 fprintf(stderr, " not yet implemented: substructs with different schemas\n");
2036 fprintf(stderr, " schema %d\n", schemaid);
2041 data_addid(xd, num);
2042 data_addid(xd, schemaid);
2043 for (ida = data->attriddata + val; *ida; ida++)
2045 Id *kp = data->xattrs[-*ida];
2050 repodata_serialize_key(data, newincore, newvincore,
2051 schema, data->keys + *kp, kp[1]);
2056 case REPOKEY_TYPE_FLEXARRAY:
2059 for (ida = data->attriddata + val; *ida; ida++)
2061 data_addid(xd, num);
2062 for (ida = data->attriddata + val; *ida; ida++)
2064 Id *kp = data->xattrs[-*ida];
2067 data_addid(xd, 0); /* XXX */
2074 schemaid = repodata_schema2id(data, schema, 1);
2075 data_addid(xd, schemaid);
2076 kp = data->xattrs[-*ida];
2079 repodata_serialize_key(data, newincore, newvincore,
2080 schema, data->keys + *kp, kp[1]);
2086 fprintf(stderr, "don't know how to handle type %d\n", key->type);
2089 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2091 /* put offset/len in incore */
2092 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2093 oldvincorelen = xd->len - oldvincorelen;
2094 data_addid(newincore, oldvincorelen);
2099 repodata_internalize(Repodata *data)
2101 Repokey *key, solvkey;
2103 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2104 unsigned char *dp, *ndp;
2105 int newschema, oldcount;
2106 struct extdata newincore;
2107 struct extdata newvincore;
2110 if (!data->attrs && !data->xattrs)
2113 newvincore.buf = data->vincore;
2114 newvincore.len = data->vincorelen;
2116 /* find the solvables key, create if needed */
2117 memset(&solvkey, 0, sizeof(solvkey));
2118 solvkey.name = REPOSITORY_SOLVABLES;
2119 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2121 solvkey.storage = KEY_STORAGE_INCORE;
2122 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2124 schema = sat_malloc2(data->nkeys, sizeof(Id));
2125 seen = sat_malloc2(data->nkeys, sizeof(Id));
2127 /* Merge the data already existing (in data->schemata, ->incoredata and
2128 friends) with the new attributes in data->attrs[]. */
2129 nentry = data->end - data->start;
2130 memset(&newincore, 0, sizeof(newincore));
2131 data_addid(&newincore, 0); /* start data at offset 1 */
2133 data->mainschema = 0;
2134 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2136 /* join entry data */
2137 /* we start with the meta data, entry -1 */
2138 for (entry = -1; entry < nentry; entry++)
2140 memset(seen, 0, data->nkeys * sizeof(Id));
2142 dp = data->incoredata;
2145 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2146 dp = data_read_id(dp, &oldschema);
2149 fprintf(stderr, "oldschema %d\n", oldschema);
2150 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2151 fprintf(stderr, "schemadata %p\n", data->schemadata);
2153 /* seen: -1: old data 0: skipped >0: id + 1 */
2157 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2161 fprintf(stderr, "Inconsistent old data (key occured twice).\n");
2169 keyp = data->attrs ? data->attrs[entry] : 0;
2172 /* strip solvables key */
2174 for (sp = keyp = schema; *sp; sp++)
2175 if (*sp != solvkeyid)
2180 seen[solvkeyid] = 0;
2181 keyp = data->xattrs ? data->xattrs[1] : 0;
2184 for (; *keyp; keyp += 2)
2191 seen[*keyp] = keyp[1] + 1;
2193 if (entry < 0 && data->end != data->start)
2200 /* Ideally we'd like to sort the new schema here, to ensure
2201 schema equality independend of the ordering. We can't do that
2202 yet. For once see below (old ids need to come before new ids).
2203 An additional difficulty is that we also need to move
2204 the values with the keys. */
2205 schemaid = repodata_schema2id(data, schema, 1);
2207 schemaid = oldschema;
2210 /* Now create data blob. We walk through the (possibly new) schema
2211 and either copy over old data, or insert the new. */
2212 /* XXX Here we rely on the fact that the (new) schema has the form
2213 o1 o2 o3 o4 ... | n1 n2 n3 ...
2214 (oX being the old keyids (possibly overwritten), and nX being
2215 the new keyids). This rules out sorting the keyids in order
2216 to ensure a small schema count. */
2218 data->incoreoffset[entry] = newincore.len;
2219 data_addid(&newincore, schemaid);
2222 data->mainschema = schemaid;
2223 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2225 keypstart = data->schemadata + data->schemata[schemaid];
2226 for (keyp = keypstart; *keyp; keyp++)
2229 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2230 if (*keyp == solvkeyid)
2232 /* add flexarray entry count */
2233 data_addid(&newincore, data->end - data->start);
2236 key = data->keys + *keyp;
2238 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2243 /* Skip the data associated with this old key. */
2244 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2246 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2247 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2249 else if (key->storage == KEY_STORAGE_INCORE)
2250 ndp = data_skip_key(data, dp, key);
2253 if (seen[*keyp] == -1)
2255 /* If this key was an old one _and_ was not overwritten with
2256 a different value copy over the old value (we skipped it
2259 data_addblob(&newincore, dp, ndp - dp);
2262 else if (seen[*keyp])
2264 /* Otherwise we have a new value. Parse it into the internal
2266 repodata_serialize_key(data, &newincore, &newvincore,
2267 schema, key, seen[*keyp] - 1);
2271 if (entry >= 0 && data->attrs && data->attrs[entry])
2272 data->attrs[entry] = sat_free(data->attrs[entry]);
2274 /* free all xattrs */
2275 for (entry = 0; entry < data->nxattrs; entry++)
2276 if (data->xattrs[entry])
2277 sat_free(data->xattrs[entry]);
2278 data->xattrs = sat_free(data->xattrs);
2281 data->lasthandle = 0;
2283 data->lastdatalen = 0;
2286 repodata_free_schemahash(data);
2288 sat_free(data->incoredata);
2289 data->incoredata = newincore.buf;
2290 data->incoredatalen = newincore.len;
2291 data->incoredatafree = 0;
2293 sat_free(data->vincore);
2294 data->vincore = newvincore.buf;
2295 data->vincorelen = newvincore.len;
2297 data->attrs = sat_free(data->attrs);
2298 data->attrdata = sat_free(data->attrdata);
2299 data->attriddata = sat_free(data->attriddata);
2300 data->attrdatalen = 0;
2301 data->attriddatalen = 0;
2305 repodata_disable_paging(Repodata *data)
2307 if (maybe_load_repodata(data, 0))
2308 repopagestore_disable_paging(&data->store);
2312 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: