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));
961 if (!pool || (repo && repo->pool != pool))
969 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
976 di->keyname = keyname;
977 di->keynames[0] = keyname;
978 di->flags = flags & ~SEARCH_THISSOLVID;
987 dataiterator_jump_to_solvid(di, p);
990 di->repo = pool->repos[0];
991 di->state = di_enterrepo;
997 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1001 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1003 di->state = di_bye; /* sorry */
1006 for (i = di->nkeynames + 1; i > 0; i--)
1007 di->keynames[i] = di->keynames[i - 1];
1008 di->keynames[0] = di->keyname = keyname;
1013 dataiterator_free(Dataiterator *di)
1015 if (di->matcher.match)
1016 datamatcher_free(&di->matcher);
1019 static inline unsigned char *
1020 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1022 Id *keyp = di->keyp;
1023 Repokey *keys = di->data->keys;
1026 for (keyp = di->keyp; *keyp; keyp++)
1027 if (keys[*keyp].name == keyname)
1031 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1039 dataiterator_step(Dataiterator *di)
1047 case di_enterrepo: di_enterrepo:
1050 if (!(di->flags & SEARCH_THISSOLVID))
1052 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1053 goto di_nextsolvable;
1057 case di_entersolvable: di_entersolvable:
1058 if (di->repodataid >= 0)
1060 di->repodataid = 0; /* reset repodata iterator */
1061 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)))
1063 di->key = solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1065 goto di_entersolvablekey;
1070 case di_enterrepodata: di_enterrepodata:
1071 if (di->repodataid >= 0)
1073 if (di->repodataid >= di->repo->nrepodata)
1074 goto di_nextsolvable;
1075 di->data = di->repo->repodata + di->repodataid;
1077 if (!maybe_load_repodata(di->data, di->keyname))
1078 goto di_nextrepodata;
1079 di->dp = solvid2data(di->data, di->solvid, &schema);
1081 goto di_nextrepodata;
1082 /* reset key iterator */
1083 di->keyp = di->data->schemadata + di->data->schemata[schema];
1086 case di_enterschema: di_enterschema:
1088 di->dp = dataiterator_find_keyname(di, di->keyname);
1089 if (!di->dp || !*di->keyp)
1093 goto di_nextrepodata;
1097 case di_enterkey: di_enterkey:
1099 di->key = di->data->keys + *di->keyp;
1100 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1103 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1105 if (di->nparents < di->nkeynames)
1111 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1113 di->state = di_nextkey;
1115 di->state = di_nextattr;
1118 case di_nextkey: di_nextkey:
1119 if (!di->keyname && *++di->keyp)
1125 case di_nextrepodata: di_nextrepodata:
1126 if (di->repodataid >= 0 && ++di->repodataid < di->repo->nrepodata)
1127 goto di_enterrepodata;
1130 case di_nextsolvable: di_nextsolvable:
1131 if (!(di->flags & SEARCH_THISSOLVID))
1134 di->solvid = di->repo->start;
1137 for (; di->solvid < di->repo->end; di->solvid++)
1139 if (di->pool->solvables[di->solvid].repo == di->repo)
1140 goto di_entersolvable;
1146 if (di->repoid >= 0)
1149 if (di->repoid < di->pool->nrepos)
1151 di->repo = di->pool->repos[di->repoid];
1157 case di_bye: di_bye:
1161 case di_enterarray: di_enterarray:
1162 if (di->key->name == REPOSITORY_SOLVABLES)
1164 di->ddp = data_read_id(di->ddp, &di->kv.num);
1169 case di_nextarrayelement: di_nextarrayelement:
1172 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1173 if (di->kv.entry == di->kv.num)
1175 if (di->nparents < di->nkeynames)
1177 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1179 di->kv.str = (char *)di->ddp;
1181 di->state = di_nextkey;
1184 if (di->kv.entry == di->kv.num - 1)
1186 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1187 di->ddp = data_read_id(di->ddp, &di->kv.id);
1188 di->kv.str = (char *)di->ddp;
1189 if (di->nparents < di->nkeynames)
1191 if ((di->flags & SEARCH_SUB) != 0)
1192 di->state = di_entersub;
1194 di->state = di_nextarrayelement;
1197 case di_entersub: di_entersub:
1198 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1199 goto di_nextarrayelement; /* sorry, full */
1200 di->parents[di->nparents].kv = di->kv;
1201 di->parents[di->nparents].dp = di->dp;
1202 di->parents[di->nparents].keyp = di->keyp;
1203 di->dp = (unsigned char *)di->kv.str;
1204 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1205 memset(&di->kv, 0, sizeof(di->kv));
1206 di->kv.parent = &di->parents[di->nparents].kv;
1208 di->keyname = di->keynames[di->nparents];
1209 goto di_enterschema;
1211 case di_leavesub: di_leavesub:
1213 di->dp = di->parents[di->nparents].dp;
1214 di->kv = di->parents[di->nparents].kv;
1215 di->keyp = di->parents[di->nparents].keyp;
1216 di->key = di->data->keys + *di->keyp;
1217 di->ddp = (unsigned char *)di->kv.str;
1218 di->keyname = di->keynames[di->nparents];
1219 goto di_nextarrayelement;
1221 /* special solvable attr handling follows */
1223 case di_nextsolvableattr:
1224 di->kv.id = *di->idp++;
1229 di->state = di_nextsolvablekey;
1233 case di_nextsolvablekey: di_nextsolvablekey:
1234 if (di->keyname || di->key->name == RPM_RPMDBID)
1235 goto di_enterrepodata;
1239 case di_entersolvablekey: di_entersolvablekey:
1240 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1241 if (!di->idp || !di->idp[0])
1242 goto di_nextsolvablekey;
1243 di->kv.id = di->idp[0];
1244 di->kv.num = di->idp[0];
1245 if (!di->kv.eof && !di->idp[1])
1249 di->state = di_nextsolvablekey;
1251 di->state = di_nextsolvableattr;
1255 if (di->matcher.match)
1257 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1259 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1263 if (!datamatcher_match(&di->matcher, di->kv.str))
1266 /* found something! */
1272 dataiterator_entersub(Dataiterator *di)
1274 if (di->state == di_nextarrayelement)
1275 di->state = di_entersub;
1279 dataiterator_setpos(Dataiterator *di)
1283 pool_clear_pos(di->pool);
1286 di->pool->pos.solvid = di->solvid;
1287 di->pool->pos.repo = di->repo;
1288 di->pool->pos.repodataid = di->data - di->repo->repodata;
1289 di->pool->pos.schema = di->kv.id;
1290 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1294 dataiterator_setpos_parent(Dataiterator *di)
1298 pool_clear_pos(di->pool);
1301 di->pool->pos.solvid = di->solvid;
1302 di->pool->pos.repo = di->repo;
1303 di->pool->pos.repodataid = di->data - di->repo->repodata;
1304 di->pool->pos.schema = di->kv.parent->id;
1305 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1309 dataiterator_skip_attribute(Dataiterator *di)
1311 if (di->state == di_nextsolvableattr)
1312 di->state = di_nextsolvablekey;
1314 di->state = di_nextkey;
1318 dataiterator_skip_solvable(Dataiterator *di)
1320 di->state = di_nextsolvable;
1324 dataiterator_skip_repo(Dataiterator *di)
1326 di->state = di_nextrepo;
1330 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1333 if (solvid == SOLVID_POS)
1335 di->repo = di->pool->pos.repo;
1342 di->data = di->repo->repodata + di->pool->pos.repodataid;
1343 di->repodataid = -1;
1344 di->solvid = di->pool->pos.solvid;
1345 di->state = di_enterrepo;
1346 di->flags |= SEARCH_THISSOLVID;
1351 di->repo = di->pool->solvables[solvid].repo;
1354 else if (di->repoid >= 0)
1356 if (!di->pool->nrepos)
1361 di->repo = di->pool->repos[0];
1365 di->solvid = solvid;
1367 di->flags |= SEARCH_THISSOLVID;
1368 di->state = di_enterrepo;
1372 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1379 di->flags &= ~SEARCH_THISSOLVID;
1380 di->state = di_enterrepo;
1384 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1386 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1388 return datamatcher_match(ma, di->kv.str);
1392 dataiterator_match_obsolete(Dataiterator *di, int flags, const void *vmatch)
1394 Datamatcher matcher;
1396 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, flags))
1398 matcher = di->matcher;
1399 matcher.flags = flags;
1400 matcher.match = (void *)vmatch;
1401 return datamatcher_match(&matcher, di->kv.str);
1405 /************************************************************************
1406 * data modify functions
1409 /* extend repodata so that it includes solvables p */
1411 repodata_extend(Repodata *data, Id p)
1413 if (data->start == data->end)
1414 data->start = data->end = p;
1417 int old = data->end - data->start;
1418 int new = p - data->end + 1;
1421 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1422 memset(data->attrs + old, 0, new * sizeof(Id *));
1424 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1425 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1428 if (p < data->start)
1430 int old = data->end - data->start;
1431 int new = data->start - p;
1434 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1435 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1436 memset(data->attrs, 0, new * sizeof(Id *));
1438 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1439 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1440 memset(data->incoreoffset, 0, new * sizeof(Id));
1446 repodata_extend_block(Repodata *data, Id start, Id num)
1450 if (!data->incoreoffset)
1452 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1453 data->start = start;
1454 data->end = start + num;
1457 repodata_extend(data, start);
1459 repodata_extend(data, start + num - 1);
1462 /**********************************************************************/
1464 #define REPODATA_ATTRS_BLOCK 63
1465 #define REPODATA_ATTRDATA_BLOCK 1023
1466 #define REPODATA_ATTRIDDATA_BLOCK 63
1470 repodata_new_handle(Repodata *data)
1474 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1477 data->xattrs = sat_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1478 data->xattrs[data->nxattrs] = 0;
1479 return -(data->nxattrs++);
1483 repodata_get_attrp(Repodata *data, Id handle)
1485 if (handle == SOLVID_META)
1489 data->xattrs = sat_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1494 return data->xattrs - handle;
1495 if (handle < data->start || handle >= data->end)
1496 repodata_extend(data, handle);
1498 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1499 return data->attrs + (handle - data->start);
1503 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1509 app = repodata_get_attrp(data, handle);
1514 for (pp = ap; *pp; pp += 2)
1515 /* Determine equality based on the name only, allows us to change
1516 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1517 if (data->keys[*pp].name == data->keys[keyid].name)
1530 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1540 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1544 keyid = repodata_key2id(data, key, 1);
1545 repodata_insert_keyid(data, solvid, keyid, val, 1);
1549 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1553 key.type = REPOKEY_TYPE_ID;
1555 key.storage = KEY_STORAGE_INCORE;
1556 repodata_set(data, solvid, &key, id);
1560 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1564 key.type = REPOKEY_TYPE_NUM;
1566 key.storage = KEY_STORAGE_INCORE;
1567 repodata_set(data, solvid, &key, (Id)num);
1571 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
1575 if (data->localpool)
1576 id = stringpool_str2id(&data->spool, str, 1);
1578 id = str2id(data->repo->pool, str, 1);
1580 key.type = REPOKEY_TYPE_ID;
1582 key.storage = KEY_STORAGE_INCORE;
1583 repodata_set(data, solvid, &key, id);
1587 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
1591 key.type = REPOKEY_TYPE_CONSTANT;
1592 key.size = constant;
1593 key.storage = KEY_STORAGE_INCORE;
1594 repodata_set(data, solvid, &key, 0);
1598 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
1602 key.type = REPOKEY_TYPE_CONSTANTID;
1604 key.storage = KEY_STORAGE_INCORE;
1605 repodata_set(data, solvid, &key, 0);
1609 repodata_set_void(Repodata *data, Id solvid, Id keyname)
1613 key.type = REPOKEY_TYPE_VOID;
1615 key.storage = KEY_STORAGE_INCORE;
1616 repodata_set(data, solvid, &key, 0);
1620 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
1625 l = strlen(str) + 1;
1627 key.type = REPOKEY_TYPE_STR;
1629 key.storage = KEY_STORAGE_INCORE;
1630 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1631 memcpy(data->attrdata + data->attrdatalen, str, l);
1632 repodata_set(data, solvid, &key, data->attrdatalen);
1633 data->attrdatalen += l;
1637 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
1640 Id *ida, *pp, **ppp;
1642 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
1644 /* great! just append the new data */
1645 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1646 data->attriddatalen--; /* overwrite terminating 0 */
1647 data->lastdatalen += entrysize;
1650 ppp = repodata_get_attrp(data, handle);
1653 for (; *pp; pp += 2)
1654 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1658 /* not found. allocate new key */
1663 key.storage = KEY_STORAGE_INCORE;
1664 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1665 repodata_set(data, handle, &key, data->attriddatalen);
1666 data->lasthandle = 0; /* next time... */
1670 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1671 oldsize += entrysize;
1672 if (ida + 1 == data->attriddata + data->attriddatalen)
1674 /* this was the last entry, just append it */
1675 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1676 data->attriddatalen--; /* overwrite terminating 0 */
1680 /* too bad. move to back. */
1681 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1682 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1683 pp[1] = data->attriddatalen;
1684 data->attriddatalen += oldsize;
1686 data->lasthandle = handle;
1687 data->lastkey = *pp;
1688 data->lastdatalen = data->attriddatalen + entrysize + 1;
1692 checksumtype2len(Id type)
1696 case REPOKEY_TYPE_MD5:
1698 case REPOKEY_TYPE_SHA1:
1700 case REPOKEY_TYPE_SHA256:
1701 return SIZEOF_SHA256;
1708 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1709 const unsigned char *str)
1712 int l = checksumtype2len(type);
1719 key.storage = KEY_STORAGE_INCORE;
1720 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1721 memcpy(data->attrdata + data->attrdatalen, str, l);
1722 repodata_set(data, solvid, &key, data->attrdatalen);
1723 data->attrdatalen += l;
1727 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1730 for (i = 0; i < buflen; i++)
1732 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1733 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1734 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1745 buf[i] = (buf[i] << 4) | v;
1752 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
1755 unsigned char buf[64];
1756 int l = checksumtype2len(type);
1760 if (hexstr2bytes(buf, str, l) != l)
1762 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
1766 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1771 l = checksumtype2len(type);
1774 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1775 for (i = 0; i < l; i++)
1777 unsigned char v = buf[i];
1778 unsigned char w = v >> 4;
1779 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1781 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1788 repodata_globalize_id(Repodata *data, Id id)
1790 if (!data || !data->localpool)
1792 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1796 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
1800 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
1802 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1803 data->attriddata[data->attriddatalen++] = dir;
1804 data->attriddata[data->attriddatalen++] = num;
1805 data->attriddata[data->attriddatalen++] = num2;
1806 data->attriddata[data->attriddatalen++] = 0;
1810 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
1816 l = strlen(str) + 1;
1817 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1818 memcpy(data->attrdata + data->attrdatalen, str, l);
1819 stroff = data->attrdatalen;
1820 data->attrdatalen += l;
1823 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
1825 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1826 data->attriddata[data->attriddatalen++] = dir;
1827 data->attriddata[data->attriddatalen++] = stroff;
1828 data->attriddata[data->attriddatalen++] = 0;
1832 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
1835 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
1837 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
1838 data->attriddata[data->attriddatalen++] = id;
1839 data->attriddata[data->attriddatalen++] = 0;
1843 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
1847 if (data->localpool)
1848 id = stringpool_str2id(&data->spool, str, 1);
1850 id = str2id(data->repo->pool, str, 1);
1851 repodata_add_idarray(data, solvid, keyname, id);
1855 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1857 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
1858 data->attriddata[data->attriddatalen++] = ghandle;
1859 data->attriddata[data->attriddatalen++] = 0;
1863 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
1865 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
1866 data->attriddata[data->attriddatalen++] = ghandle;
1867 data->attriddata[data->attriddatalen++] = 0;
1871 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1874 if (dest == src || !(keyp = data->attrs[src]))
1876 for (; *keyp; keyp += 2)
1877 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1883 /**********************************************************************/
1885 /* unify with repo_write! */
1887 #define EXTDATA_BLOCK 1023
1895 data_addid(struct extdata *xd, Id x)
1898 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1899 dp = xd->buf + xd->len;
1904 *dp++ = (x >> 28) | 128;
1906 *dp++ = (x >> 21) | 128;
1907 *dp++ = (x >> 14) | 128;
1910 *dp++ = (x >> 7) | 128;
1912 xd->len = dp - xd->buf;
1916 data_addideof(struct extdata *xd, Id x, int eof)
1919 x = (x & 63) | ((x & ~63) << 1);
1920 data_addid(xd, (eof ? x: x | 64));
1924 data_addblob(struct extdata *xd, unsigned char *blob, int len)
1926 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
1927 memcpy(xd->buf + xd->len, blob, len);
1931 /*********************************/
1934 repodata_serialize_key(Repodata *data, struct extdata *newincore,
1935 struct extdata *newvincore,
1937 Repokey *key, Id val)
1939 /* Otherwise we have a new value. Parse it into the internal
1943 unsigned int oldvincorelen = 0;
1947 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1950 oldvincorelen = xd->len;
1954 case REPOKEY_TYPE_VOID:
1955 case REPOKEY_TYPE_CONSTANT:
1956 case REPOKEY_TYPE_CONSTANTID:
1958 case REPOKEY_TYPE_STR:
1959 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
1961 case REPOKEY_TYPE_MD5:
1962 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
1964 case REPOKEY_TYPE_SHA1:
1965 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
1967 case REPOKEY_TYPE_SHA256:
1968 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
1970 case REPOKEY_TYPE_ID:
1971 case REPOKEY_TYPE_NUM:
1972 case REPOKEY_TYPE_DIR:
1973 data_addid(xd, val);
1975 case REPOKEY_TYPE_IDARRAY:
1976 for (ida = data->attriddata + val; *ida; ida++)
1977 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
1979 case REPOKEY_TYPE_DIRNUMNUMARRAY:
1980 for (ida = data->attriddata + val; *ida; ida += 3)
1982 data_addid(xd, ida[0]);
1983 data_addid(xd, ida[1]);
1984 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
1987 case REPOKEY_TYPE_DIRSTRARRAY:
1988 for (ida = data->attriddata + val; *ida; ida += 2)
1990 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
1991 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
1994 case REPOKEY_TYPE_FIXARRAY:
1998 for (ida = data->attriddata + val; *ida; ida++)
2001 fprintf(stderr, "serialize struct %d\n", *ida);
2004 Id *kp = data->xattrs[-*ida];
2011 fprintf(stderr, " %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
2017 schemaid = repodata_schema2id(data, schema, 1);
2018 else if (schemaid != repodata_schema2id(data, schema, 0))
2020 pool_debug(data->repo->pool, SAT_FATAL, "substructs with different schemas\n");
2024 fprintf(stderr, " schema %d\n", schemaid);
2029 data_addid(xd, num);
2030 data_addid(xd, schemaid);
2031 for (ida = data->attriddata + val; *ida; ida++)
2033 Id *kp = data->xattrs[-*ida];
2038 repodata_serialize_key(data, newincore, newvincore,
2039 schema, data->keys + *kp, kp[1]);
2044 case REPOKEY_TYPE_FLEXARRAY:
2047 for (ida = data->attriddata + val; *ida; ida++)
2049 data_addid(xd, num);
2050 for (ida = data->attriddata + val; *ida; ida++)
2052 Id *kp = data->xattrs[-*ida];
2055 data_addid(xd, 0); /* XXX */
2062 schemaid = repodata_schema2id(data, schema, 1);
2063 data_addid(xd, schemaid);
2064 kp = data->xattrs[-*ida];
2067 repodata_serialize_key(data, newincore, newvincore,
2068 schema, data->keys + *kp, kp[1]);
2074 pool_debug(data->repo->pool, SAT_FATAL, "don't know how to handle type %d\n", key->type);
2077 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2079 /* put offset/len in incore */
2080 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2081 oldvincorelen = xd->len - oldvincorelen;
2082 data_addid(newincore, oldvincorelen);
2087 repodata_internalize(Repodata *data)
2089 Repokey *key, solvkey;
2091 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2092 unsigned char *dp, *ndp;
2093 int newschema, oldcount;
2094 struct extdata newincore;
2095 struct extdata newvincore;
2098 if (!data->attrs && !data->xattrs)
2101 newvincore.buf = data->vincore;
2102 newvincore.len = data->vincorelen;
2104 /* find the solvables key, create if needed */
2105 memset(&solvkey, 0, sizeof(solvkey));
2106 solvkey.name = REPOSITORY_SOLVABLES;
2107 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2109 solvkey.storage = KEY_STORAGE_INCORE;
2110 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2112 schema = sat_malloc2(data->nkeys, sizeof(Id));
2113 seen = sat_malloc2(data->nkeys, sizeof(Id));
2115 /* Merge the data already existing (in data->schemata, ->incoredata and
2116 friends) with the new attributes in data->attrs[]. */
2117 nentry = data->end - data->start;
2118 memset(&newincore, 0, sizeof(newincore));
2119 data_addid(&newincore, 0); /* start data at offset 1 */
2121 data->mainschema = 0;
2122 data->mainschemaoffsets = sat_free(data->mainschemaoffsets);
2124 /* join entry data */
2125 /* we start with the meta data, entry -1 */
2126 for (entry = -1; entry < nentry; entry++)
2128 memset(seen, 0, data->nkeys * sizeof(Id));
2130 dp = data->incoredata;
2133 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2134 dp = data_read_id(dp, &oldschema);
2137 fprintf(stderr, "oldschema %d\n", oldschema);
2138 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2139 fprintf(stderr, "schemadata %p\n", data->schemadata);
2141 /* seen: -1: old data 0: skipped >0: id + 1 */
2145 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2149 pool_debug(data->repo->pool, SAT_FATAL, "Inconsistent old data (key occured twice).\n");
2157 keyp = data->attrs ? data->attrs[entry] : 0;
2160 /* strip solvables key */
2162 for (sp = keyp = schema; *sp; sp++)
2163 if (*sp != solvkeyid)
2168 seen[solvkeyid] = 0;
2169 keyp = data->xattrs ? data->xattrs[1] : 0;
2172 for (; *keyp; keyp += 2)
2179 seen[*keyp] = keyp[1] + 1;
2181 if (entry < 0 && data->end != data->start)
2188 /* Ideally we'd like to sort the new schema here, to ensure
2189 schema equality independend of the ordering. We can't do that
2190 yet. For once see below (old ids need to come before new ids).
2191 An additional difficulty is that we also need to move
2192 the values with the keys. */
2193 schemaid = repodata_schema2id(data, schema, 1);
2195 schemaid = oldschema;
2198 /* Now create data blob. We walk through the (possibly new) schema
2199 and either copy over old data, or insert the new. */
2200 /* XXX Here we rely on the fact that the (new) schema has the form
2201 o1 o2 o3 o4 ... | n1 n2 n3 ...
2202 (oX being the old keyids (possibly overwritten), and nX being
2203 the new keyids). This rules out sorting the keyids in order
2204 to ensure a small schema count. */
2206 data->incoreoffset[entry] = newincore.len;
2207 data_addid(&newincore, schemaid);
2210 data->mainschema = schemaid;
2211 data->mainschemaoffsets = sat_calloc(sp - schema, sizeof(Id));
2213 keypstart = data->schemadata + data->schemata[schemaid];
2214 for (keyp = keypstart; *keyp; keyp++)
2217 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2218 if (*keyp == solvkeyid)
2220 /* add flexarray entry count */
2221 data_addid(&newincore, data->end - data->start);
2224 key = data->keys + *keyp;
2226 fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
2231 /* Skip the data associated with this old key. */
2232 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2234 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2235 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2237 else if (key->storage == KEY_STORAGE_INCORE)
2238 ndp = data_skip_key(data, dp, key);
2241 if (seen[*keyp] == -1)
2243 /* If this key was an old one _and_ was not overwritten with
2244 a different value copy over the old value (we skipped it
2247 data_addblob(&newincore, dp, ndp - dp);
2250 else if (seen[*keyp])
2252 /* Otherwise we have a new value. Parse it into the internal
2254 repodata_serialize_key(data, &newincore, &newvincore,
2255 schema, key, seen[*keyp] - 1);
2259 if (entry >= 0 && data->attrs && data->attrs[entry])
2260 data->attrs[entry] = sat_free(data->attrs[entry]);
2262 /* free all xattrs */
2263 for (entry = 0; entry < data->nxattrs; entry++)
2264 if (data->xattrs[entry])
2265 sat_free(data->xattrs[entry]);
2266 data->xattrs = sat_free(data->xattrs);
2269 data->lasthandle = 0;
2271 data->lastdatalen = 0;
2274 repodata_free_schemahash(data);
2276 sat_free(data->incoredata);
2277 data->incoredata = newincore.buf;
2278 data->incoredatalen = newincore.len;
2279 data->incoredatafree = 0;
2281 sat_free(data->vincore);
2282 data->vincore = newvincore.buf;
2283 data->vincorelen = newvincore.len;
2285 data->attrs = sat_free(data->attrs);
2286 data->attrdata = sat_free(data->attrdata);
2287 data->attriddata = sat_free(data->attriddata);
2288 data->attrdatalen = 0;
2289 data->attriddatalen = 0;
2293 repodata_disable_paging(Repodata *data)
2295 if (maybe_load_repodata(data, 0))
2296 repopagestore_disable_paging(&data->store);
2300 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: