2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Manage data coming from one repository
13 * a repository can contain multiple repodata entries, consisting of
14 * different sets of keys and different sets of solvables
29 #include "poolid_private.h"
37 #define REPODATA_BLOCK 255
39 static unsigned char *data_skip_key(Repodata *data, unsigned char *dp, Repokey *key);
42 repodata_initdata(Repodata *data, Repo *repo, int localpool)
44 memset(data, 0, sizeof (*data));
45 data->repodataid = data - repo->repodata;
47 data->localpool = localpool;
49 stringpool_init_empty(&data->spool);
50 /* dirpool_init(&data->dirpool); just zeros out again */
51 data->keys = solv_calloc(1, sizeof(Repokey));
53 data->schemata = solv_calloc(1, sizeof(Id));
54 data->schemadata = solv_calloc(1, sizeof(Id));
56 data->schemadatalen = 1;
57 repopagestore_init(&data->store);
61 repodata_freedata(Repodata *data)
65 solv_free(data->keys);
67 solv_free(data->schemata);
68 solv_free(data->schemadata);
69 solv_free(data->schematahash);
71 stringpool_free(&data->spool);
72 dirpool_free(&data->dirpool);
74 solv_free(data->mainschemaoffsets);
75 solv_free(data->incoredata);
76 solv_free(data->incoreoffset);
77 solv_free(data->verticaloffset);
79 repopagestore_free(&data->store);
81 solv_free(data->vincore);
84 for (i = 0; i < data->end - data->start; i++)
85 solv_free(data->attrs[i]);
86 solv_free(data->attrs);
88 for (i = 0; i < data->nxattrs; i++)
89 solv_free(data->xattrs[i]);
90 solv_free(data->xattrs);
92 solv_free(data->attrdata);
93 solv_free(data->attriddata);
94 solv_free(data->attrnum64data);
96 solv_free(data->dircache);
100 repodata_free(Repodata *data)
102 Repo *repo = data->repo;
103 int i = data - repo->repodata;
106 repodata_freedata(data);
107 if (i < repo->nrepodata - 1)
109 /* whoa! this changes the repodataids! */
110 memmove(repo->repodata + i, repo->repodata + i + 1, (repo->nrepodata - 1 - i) * sizeof(Repodata));
111 for (; i < repo->nrepodata - 1; i++)
112 repo->repodata[i].repodataid = i;
115 if (repo->nrepodata == 1)
117 repo->repodata = solv_free(repo->repodata);
123 repodata_empty(Repodata *data, int localpool)
125 void (*loadcallback)(Repodata *) = data->loadcallback;
126 int state = data->state;
127 repodata_freedata(data);
128 repodata_initdata(data, data->repo, localpool);
130 data->loadcallback = loadcallback;
134 /***************************************************************
135 * key pool management
138 /* this is not so time critical that we need a hash, so we do a simple
141 repodata_key2id(Repodata *data, Repokey *key, int create)
145 for (keyid = 1; keyid < data->nkeys; keyid++)
146 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
148 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
152 if (keyid == data->nkeys)
156 /* allocate new key */
157 data->keys = solv_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
158 data->keys[data->nkeys++] = *key;
159 if (data->verticaloffset)
161 data->verticaloffset = solv_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
162 data->verticaloffset[data->nkeys - 1] = 0;
164 data->keybits[(key->name >> 3) & (sizeof(data->keybits) - 1)] |= 1 << (key->name & 7);
170 /***************************************************************
171 * schema pool management
174 #define SCHEMATA_BLOCK 31
175 #define SCHEMATADATA_BLOCK 255
178 repodata_schema2id(Repodata *data, Id *schema, int create)
185 return 0; /* XXX: allow empty schema? */
186 if ((schematahash = data->schematahash) == 0)
188 data->schematahash = schematahash = solv_calloc(256, sizeof(Id));
189 for (i = 1; i < data->nschemata; i++)
191 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
196 data->schemadata = solv_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
197 data->schemata = solv_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
200 for (sp = schema, len = 0, h = 0; *sp; len++)
205 cid = schematahash[h];
208 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
210 /* cache conflict, do a slow search */
211 for (cid = 1; cid < data->nschemata; cid++)
212 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
218 data->schemadata = solv_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
219 data->schemata = solv_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
221 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
222 data->schemata[data->nschemata] = data->schemadatalen;
223 data->schemadatalen += len;
224 schematahash[h] = data->nschemata;
226 fprintf(stderr, "schema2id: new schema\n");
228 return data->nschemata++;
232 repodata_free_schemahash(Repodata *data)
234 data->schematahash = solv_free(data->schematahash);
236 data->schemata = solv_realloc2(data->schemata, data->nschemata, sizeof(Id));
237 data->schemadata = solv_realloc2(data->schemadata, data->schemadatalen, sizeof(Id));
241 /***************************************************************
242 * dir pool management
245 #ifndef HAVE_STRCHRNUL
246 static inline const char *strchrnul(const char *str, char x)
248 const char *p = strchr(str, x);
249 return p ? p : str + strlen(str);
253 #define DIRCACHE_SIZE 41 /* < 1k */
257 Id ids[DIRCACHE_SIZE];
258 char str[(DIRCACHE_SIZE * (DIRCACHE_SIZE - 1)) / 2];
263 repodata_str2dir(Repodata *data, const char *dir, int create)
274 while (*dir == '/' && dir[1] == '/')
276 if (*dir == '/' && !dir[1])
278 if (data->dirpool.ndirs)
280 return dirpool_add_dir(&data->dirpool, 0, 1, create);
287 struct dircache *dircache = data->dircache;
291 if (l < DIRCACHE_SIZE && dircache->ids[l] && !memcmp(dircache->str + l * (l - 1) / 2, dir, l))
293 parent = dircache->ids[l];
309 dire = strchrnul(dir, '/');
311 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
313 id = pool_strn2id(data->repo->pool, dir, dire - dir, create);
316 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
321 data->dircache = solv_calloc(1, sizeof(struct dircache));
325 if (l < DIRCACHE_SIZE)
327 data->dircache->ids[l] = parent;
328 memcpy(data->dircache->str + l * (l - 1) / 2, dirs, l);
342 repodata_free_dircache(Repodata *data)
344 data->dircache = solv_free(data->dircache);
348 repodata_dir2str(Repodata *data, Id did, const char *suf)
350 Pool *pool = data->repo->pool;
357 return suf ? suf : "";
361 comp = dirpool_compid(&data->dirpool, parent);
362 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
364 parent = dirpool_parent(&data->dirpool, parent);
369 l += strlen(suf) + 1;
370 p = pool_alloctmpspace(pool, l + 1) + l;
381 comp = dirpool_compid(&data->dirpool, parent);
382 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
385 strncpy(p, comps, l);
386 parent = dirpool_parent(&data->dirpool, parent);
394 /***************************************************************
398 static inline unsigned char *
399 data_skip_schema(Repodata *data, unsigned char *dp, Id schema)
401 Id *keyp = data->schemadata + data->schemata[schema];
402 for (; *keyp; keyp++)
403 dp = data_skip_key(data, dp, data->keys + *keyp);
407 static unsigned char *
408 data_skip_key(Repodata *data, unsigned char *dp, Repokey *key)
410 int nentries, schema;
413 case REPOKEY_TYPE_FIXARRAY:
414 dp = data_read_id(dp, &nentries);
417 dp = data_read_id(dp, &schema);
419 dp = data_skip_schema(data, dp, schema);
421 case REPOKEY_TYPE_FLEXARRAY:
422 dp = data_read_id(dp, &nentries);
425 dp = data_read_id(dp, &schema);
426 dp = data_skip_schema(data, dp, schema);
430 if (key->storage == KEY_STORAGE_INCORE)
431 dp = data_skip(dp, key->type);
432 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
434 dp = data_skip(dp, REPOKEY_TYPE_ID);
435 dp = data_skip(dp, REPOKEY_TYPE_ID);
441 static unsigned char *
442 forward_to_key(Repodata *data, Id keyid, Id *keyp, unsigned char *dp)
448 if (data->mainschemaoffsets && dp == data->incoredata + data->mainschemaoffsets[0] && keyp == data->schemadata + data->schemata[data->mainschema])
451 for (i = 0; (k = *keyp++) != 0; i++)
453 return data->incoredata + data->mainschemaoffsets[i];
456 while ((k = *keyp++) != 0)
460 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
462 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip offset */
463 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip length */
466 if (data->keys[k].storage != KEY_STORAGE_INCORE)
468 dp = data_skip_key(data, dp, data->keys + k);
473 static unsigned char *
474 get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
479 if (off >= data->lastverticaloffset)
481 off -= data->lastverticaloffset;
482 if (off + len > data->vincorelen)
484 return data->vincore + off;
486 if (off + len > key->size)
488 /* we now have the offset, go into vertical */
489 off += data->verticaloffset[key - data->keys];
490 /* fprintf(stderr, "key %d page %d\n", key->name, off / REPOPAGE_BLOBSIZE); */
491 dp = repopagestore_load_page_range(&data->store, off / REPOPAGE_BLOBSIZE, (off + len - 1) / REPOPAGE_BLOBSIZE);
493 dp += off % REPOPAGE_BLOBSIZE;
497 static inline unsigned char *
498 get_data(Repodata *data, Repokey *key, unsigned char **dpp, int advance)
500 unsigned char *dp = *dpp;
504 if (key->storage == KEY_STORAGE_INCORE)
507 *dpp = data_skip_key(data, dp, key);
510 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
513 dp = data_read_id(dp, &off);
514 dp = data_read_id(dp, &len);
517 return get_vertical_data(data, key, off, len);
523 load_repodata(Repodata *data)
525 if (data->loadcallback)
527 data->loadcallback(data);
528 if (data->state == REPODATA_AVAILABLE)
531 data->state = REPODATA_ERROR;
536 maybe_load_repodata(Repodata *data, Id keyname)
538 if (keyname && !repodata_precheck_keyname(data, keyname))
539 return 0; /* do not bother... */
546 for (i = 1; i < data->nkeys; i++)
547 if (keyname == data->keys[i].name)
549 if (i == data->nkeys)
552 return load_repodata(data);
555 case REPODATA_AVAILABLE:
556 case REPODATA_LOADING:
559 data->state = REPODATA_ERROR;
564 static inline unsigned char *
565 solvid2data(Repodata *data, Id solvid, Id *schemap)
567 unsigned char *dp = data->incoredata;
570 if (solvid == SOLVID_META) /* META */
572 else if (solvid == SOLVID_POS) /* META */
574 Pool *pool = data->repo->pool;
575 if (data->repo != pool->pos.repo)
577 if (data != data->repo->repodata + pool->pos.repodataid)
579 *schemap = pool->pos.schema;
580 return data->incoredata + pool->pos.dp;
584 if (solvid < data->start || solvid >= data->end)
586 dp += data->incoreoffset[solvid - data->start];
588 return data_read_id(dp, schemap);
591 /************************************************************************
595 static inline unsigned char *
596 find_key_data(Repodata *data, Id solvid, Id keyname, Repokey **keypp)
599 Id schema, *keyp, *kp;
602 if (!maybe_load_repodata(data, keyname))
604 dp = solvid2data(data, solvid, &schema);
607 keyp = data->schemadata + data->schemata[schema];
608 for (kp = keyp; *kp; kp++)
609 if (data->keys[*kp].name == keyname)
613 *keypp = key = data->keys + *kp;
614 if (key->type == REPOKEY_TYPE_DELETED)
616 if (key->type == REPOKEY_TYPE_VOID || key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID)
617 return dp; /* no need to forward... */
618 dp = forward_to_key(data, *kp, keyp, dp);
621 return get_data(data, key, &dp, 0);
625 repodata_lookup_type(Repodata *data, Id solvid, Id keyname)
627 Id schema, *keyp, *kp;
628 if (!maybe_load_repodata(data, keyname))
630 if (!solvid2data(data, solvid, &schema))
632 keyp = data->schemadata + data->schemata[schema];
633 for (kp = keyp; *kp; kp++)
634 if (data->keys[*kp].name == keyname)
635 return data->keys[*kp].type;
640 repodata_lookup_id(Repodata *data, Id solvid, Id keyname)
646 dp = find_key_data(data, solvid, keyname, &key);
649 if (key->type == REPOKEY_TYPE_CONSTANTID)
651 if (key->type != REPOKEY_TYPE_ID)
653 dp = data_read_id(dp, &id);
658 repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
664 dp = find_key_data(data, solvid, keyname, &key);
667 if (key->type == REPOKEY_TYPE_STR)
668 return (const char *)dp;
669 if (key->type == REPOKEY_TYPE_CONSTANTID)
671 else if (key->type == REPOKEY_TYPE_ID)
672 dp = data_read_id(dp, &id);
676 return stringpool_id2str(&data->spool, id);
677 return pool_id2str(data->repo->pool, id);
681 repodata_lookup_num(Repodata *data, Id solvid, Id keyname, unsigned long long *value)
688 dp = find_key_data(data, solvid, keyname, &key);
691 if (key->type == REPOKEY_TYPE_NUM
692 || key->type == REPOKEY_TYPE_U32
693 || key->type == REPOKEY_TYPE_CONSTANT)
695 kv.num = kv.num2 = 0;
696 dp = data_fetch(dp, &kv, key);
697 *value = SOLV_KV_NUM64(&kv);
704 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
710 if (!maybe_load_repodata(data, keyname))
712 dp = solvid2data(data, solvid, &schema);
715 /* can't use find_key_data as we need to test the type */
716 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
717 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
722 const unsigned char *
723 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
728 dp = find_key_data(data, solvid, keyname, &key);
731 if (!(key->type == REPOKEY_TYPE_MD5 || key->type == REPOKEY_TYPE_SHA1 || key->type == REPOKEY_TYPE_SHA256))
738 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
746 dp = find_key_data(data, solvid, keyname, &key);
749 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
753 dp = data_read_ideof(dp, &id, &eof);
762 repodata_globalize_id(Repodata *data, Id id, int create)
764 if (!id || !data || !data->localpool)
766 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
770 repodata_localize_id(Repodata *data, Id id, int create)
772 if (!id || !data || !data->localpool)
774 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
778 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
783 ap = data->attrs[solvid - data->start];
788 if (data->keys[*ap].name != keyname)
790 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
792 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
800 /************************************************************************
806 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
810 case REPOKEY_TYPE_ID:
811 case REPOKEY_TYPE_CONSTANTID:
812 case REPOKEY_TYPE_IDARRAY:
813 if (data && data->localpool)
814 kv->str = stringpool_id2str(&data->spool, kv->id);
816 kv->str = pool_id2str(pool, kv->id);
817 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
820 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
822 if (*s == ':' && s > kv->str)
826 case REPOKEY_TYPE_STR:
828 case REPOKEY_TYPE_DIRSTRARRAY:
829 if (!(flags & SEARCH_FILES))
830 return 1; /* match just the basename */
831 /* Put the full filename into kv->str. */
832 kv->str = repodata_dir2str(data, kv->id, kv->str);
833 /* And to compensate for that put the "empty" directory into
834 kv->id, so that later calls to repodata_dir2str on this data
835 come up with the same filename again. */
838 case REPOKEY_TYPE_MD5:
839 case REPOKEY_TYPE_SHA1:
840 case REPOKEY_TYPE_SHA256:
841 if (!(flags & SEARCH_CHECKSUMS))
842 return 0; /* skip em */
843 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
851 struct subschema_data {
857 /* search a specific repodata */
859 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
863 Id keyid, *kp, *keyp;
864 unsigned char *dp, *ddp;
870 if (!maybe_load_repodata(data, keyname))
872 if (solvid == SOLVID_SUBSCHEMA)
874 struct subschema_data *subd = cbdata;
875 cbdata = subd->cbdata;
877 schema = subd->parent->id;
878 dp = (unsigned char *)subd->parent->str;
879 kv.parent = subd->parent;
884 dp = solvid2data(data, solvid, &schema);
887 s = data->repo->pool->solvables + solvid;
890 keyp = data->schemadata + data->schemata[schema];
893 /* search for a specific key */
894 for (kp = keyp; *kp; kp++)
895 if (data->keys[*kp].name == keyname)
899 dp = forward_to_key(data, *kp, keyp, dp);
905 while ((keyid = *keyp++) != 0)
908 key = data->keys + keyid;
909 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
911 if (key->type == REPOKEY_TYPE_DELETED)
913 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
915 struct subschema_data subd;
919 subd.cbdata = cbdata;
922 ddp = data_read_id(ddp, &nentries);
926 while (ddp && nentries > 0)
930 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
931 ddp = data_read_id(ddp, &schema);
933 kv.str = (char *)ddp;
934 stop = callback(cbdata, s, data, key, &kv);
935 if (stop > SEARCH_NEXT_KEY)
937 if (stop && stop != SEARCH_ENTERSUB)
939 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
940 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
941 ddp = data_skip_schema(data, ddp, schema);
944 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
948 kv.str = (char *)ddp;
949 stop = callback(cbdata, s, data, key, &kv);
950 if (stop > SEARCH_NEXT_KEY)
960 ddp = data_fetch(ddp, &kv, key);
963 stop = callback(cbdata, s, data, key, &kv);
966 while (!kv.eof && !stop);
967 if (onekey || stop > SEARCH_NEXT_KEY)
973 repodata_setpos_kv(Repodata *data, KeyValue *kv)
975 Pool *pool = data->repo->pool;
977 pool_clear_pos(pool);
980 pool->pos.repo = data->repo;
981 pool->pos.repodataid = data - data->repo->repodata;
982 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
983 pool->pos.schema = kv->id;
987 /************************************************************************
988 * data iterator functions
992 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1006 case SOLVABLE_VENDOR:
1009 case SOLVABLE_PROVIDES:
1011 return s->provides ? s->repo->idarraydata + s->provides : 0;
1012 case SOLVABLE_OBSOLETES:
1014 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1015 case SOLVABLE_CONFLICTS:
1017 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1018 case SOLVABLE_REQUIRES:
1020 return s->requires ? s->repo->idarraydata + s->requires : 0;
1021 case SOLVABLE_RECOMMENDS:
1023 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1024 case SOLVABLE_SUPPLEMENTS:
1026 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1027 case SOLVABLE_SUGGESTS:
1029 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1030 case SOLVABLE_ENHANCES:
1032 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1035 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1042 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1048 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1050 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1051 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1054 solv_free(ma->matchdata);
1055 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1062 datamatcher_free(Datamatcher *ma)
1064 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1066 regfree(ma->matchdata);
1067 ma->matchdata = solv_free(ma->matchdata);
1072 datamatcher_match(Datamatcher *ma, const char *str)
1075 switch ((ma->flags & SEARCH_STRINGMASK))
1077 case SEARCH_SUBSTRING:
1078 if (ma->flags & SEARCH_NOCASE)
1080 if (!strcasestr(str, ma->match))
1085 if (!strstr(str, ma->match))
1090 if (ma->flags & SEARCH_NOCASE)
1092 if (strcasecmp(ma->match, str))
1097 if (strcmp(ma->match, str))
1101 case SEARCH_STRINGSTART:
1102 if (ma->flags & SEARCH_NOCASE)
1104 if (strncasecmp(ma->match, str, strlen(ma->match)))
1109 if (strncmp(ma->match, str, strlen(ma->match)))
1113 case SEARCH_STRINGEND:
1114 l = strlen(str) - strlen(ma->match);
1117 if (ma->flags & SEARCH_NOCASE)
1119 if (strcasecmp(ma->match, str + l))
1124 if (strcmp(ma->match, str + l))
1129 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1133 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1143 repodata_filelistfilter_matches(Repodata *data, const char *str)
1145 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1146 /* for now hardcoded */
1147 if (strstr(str, "bin/"))
1149 if (!strncmp(str, "/etc/", 5))
1151 if (!strcmp(str, "/usr/lib/sendmail"))
1173 di_nextarrayelement,
1179 di_entersolvablekey,
1183 /* see dataiterator.h for documentation */
1185 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1187 memset(di, 0, sizeof(*di));
1189 di->flags = flags & ~SEARCH_THISSOLVID;
1190 if (!pool || (repo && repo->pool != pool))
1198 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1204 di->keyname = keyname;
1205 di->keynames[0] = keyname;
1206 dataiterator_set_search(di, repo, p);
1211 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1214 memset(&di->matcher, 0, sizeof(di->matcher));
1215 if (from->matcher.match)
1216 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1221 for (i = 1; i < di->nparents; i++)
1222 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1223 di->kv.parent = &di->parents[di->nparents - 1].kv;
1228 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1230 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1231 datamatcher_free(&di->matcher);
1232 memset(&di->matcher, 0, sizeof(di->matcher));
1236 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1246 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1250 di->flags &= ~SEARCH_THISSOLVID;
1254 if (!di->pool->urepos)
1262 di->repo = di->pool->repos[di->repoid];
1264 di->state = di_enterrepo;
1266 dataiterator_jump_to_solvid(di, p);
1270 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1273 di->keyname = keyname;
1274 di->keynames[0] = keyname;
1278 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1282 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1284 di->state = di_bye; /* sorry */
1287 for (i = di->nkeynames + 1; i > 0; i--)
1288 di->keynames[i] = di->keynames[i - 1];
1289 di->keynames[0] = di->keyname = keyname;
1294 dataiterator_free(Dataiterator *di)
1296 if (di->matcher.match)
1297 datamatcher_free(&di->matcher);
1300 static inline unsigned char *
1301 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1303 Id *keyp = di->keyp;
1304 Repokey *keys = di->data->keys;
1307 for (keyp = di->keyp; *keyp; keyp++)
1308 if (keys[*keyp].name == keyname)
1312 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1320 dataiterator_filelistcheck(Dataiterator *di)
1323 int needcomplete = 0;
1324 Repodata *data = di->data;
1326 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1327 if (!di->matcher.match
1328 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1329 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1330 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1332 if (data->state != REPODATA_AVAILABLE)
1333 return needcomplete ? 1 : 0;
1334 for (j = 1; j < data->nkeys; j++)
1335 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1337 return j == data->nkeys && !needcomplete ? 0 : 1;
1341 dataiterator_step(Dataiterator *di)
1349 case di_enterrepo: di_enterrepo:
1350 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1352 if (!(di->flags & SEARCH_THISSOLVID))
1354 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1355 goto di_nextsolvable;
1359 case di_entersolvable: di_entersolvable:
1362 di->repodataid = 1; /* reset repodata iterator */
1363 if (di->solvid > 0 && !(di->flags & SEARCH_NO_STORAGE_SOLVABLE) && (!di->keyname || (di->keyname >= SOLVABLE_NAME && di->keyname <= RPM_RPMDBID)) && di->nparents - di->rootlevel == di->nkeynames)
1365 extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
1367 di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1369 goto di_entersolvablekey;
1374 case di_enterrepodata: di_enterrepodata:
1377 if (di->repodataid >= di->repo->nrepodata)
1378 goto di_nextsolvable;
1379 di->data = di->repo->repodata + di->repodataid;
1381 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1382 goto di_nextrepodata;
1383 if (!maybe_load_repodata(di->data, di->keyname))
1384 goto di_nextrepodata;
1385 di->dp = solvid2data(di->data, di->solvid, &schema);
1387 goto di_nextrepodata;
1388 if (di->solvid == SOLVID_POS)
1389 di->solvid = di->pool->pos.solvid;
1390 /* reset key iterator */
1391 di->keyp = di->data->schemadata + di->data->schemata[schema];
1394 case di_enterschema: di_enterschema:
1396 di->dp = dataiterator_find_keyname(di, di->keyname);
1397 if (!di->dp || !*di->keyp)
1401 goto di_nextrepodata;
1405 case di_enterkey: di_enterkey:
1407 di->key = di->data->keys + *di->keyp;
1408 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1411 if (di->key->type == REPOKEY_TYPE_DELETED)
1413 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1415 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1421 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1423 di->state = di_nextkey;
1425 di->state = di_nextattr;
1428 case di_nextkey: di_nextkey:
1429 if (!di->keyname && *++di->keyp)
1435 case di_nextrepodata: di_nextrepodata:
1436 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1437 goto di_enterrepodata;
1440 case di_nextsolvable: di_nextsolvable:
1441 if (!(di->flags & SEARCH_THISSOLVID))
1444 di->solvid = di->repo->start;
1447 for (; di->solvid < di->repo->end; di->solvid++)
1449 if (di->pool->solvables[di->solvid].repo == di->repo)
1450 goto di_entersolvable;
1455 case di_nextrepo: di_nextrepo:
1460 if (di->repoid < di->pool->nrepos)
1462 di->repo = di->pool->repos[di->repoid];
1468 case di_bye: di_bye:
1472 case di_enterarray: di_enterarray:
1473 if (di->key->name == REPOSITORY_SOLVABLES)
1475 di->ddp = data_read_id(di->ddp, (Id *)&di->kv.num);
1480 case di_nextarrayelement: di_nextarrayelement:
1483 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1484 if (di->kv.entry == di->kv.num)
1486 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1488 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1490 di->kv.str = (char *)di->ddp;
1492 di->state = di_nextkey;
1495 if (di->kv.entry == di->kv.num - 1)
1497 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1498 di->ddp = data_read_id(di->ddp, &di->kv.id);
1499 di->kv.str = (char *)di->ddp;
1500 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1502 if ((di->flags & SEARCH_SUB) != 0)
1503 di->state = di_entersub;
1505 di->state = di_nextarrayelement;
1508 case di_entersub: di_entersub:
1509 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1510 goto di_nextarrayelement; /* sorry, full */
1511 di->parents[di->nparents].kv = di->kv;
1512 di->parents[di->nparents].dp = di->dp;
1513 di->parents[di->nparents].keyp = di->keyp;
1514 di->dp = (unsigned char *)di->kv.str;
1515 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1516 memset(&di->kv, 0, sizeof(di->kv));
1517 di->kv.parent = &di->parents[di->nparents].kv;
1519 di->keyname = di->keynames[di->nparents - di->rootlevel];
1520 goto di_enterschema;
1522 case di_leavesub: di_leavesub:
1523 if (di->nparents - 1 < di->rootlevel)
1526 di->dp = di->parents[di->nparents].dp;
1527 di->kv = di->parents[di->nparents].kv;
1528 di->keyp = di->parents[di->nparents].keyp;
1529 di->key = di->data->keys + *di->keyp;
1530 di->ddp = (unsigned char *)di->kv.str;
1531 di->keyname = di->keynames[di->nparents - di->rootlevel];
1532 goto di_nextarrayelement;
1534 /* special solvable attr handling follows */
1536 case di_nextsolvablekey: di_nextsolvablekey:
1537 if (di->keyname || di->key->name == RPM_RPMDBID)
1538 goto di_enterrepodata;
1542 case di_entersolvablekey: di_entersolvablekey:
1543 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1544 if (!di->idp || !*di->idp)
1545 goto di_nextsolvablekey;
1549 di->kv.id = *di->idp;
1550 di->kv.num = *di->idp; /* for rpmdbid */
1551 di->kv.num2 = 0; /* for rpmdbid */
1553 di->state = di_nextsolvablekey;
1559 case di_nextsolvableattr:
1560 di->state = di_nextsolvableattr;
1561 di->kv.id = *di->idp++;
1566 di->state = di_nextsolvablekey;
1572 if (di->matcher.match)
1574 /* simple pre-check so that we don't need to stringify */
1575 if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING))
1577 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1578 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1581 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1583 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1587 if (!datamatcher_match(&di->matcher, di->kv.str))
1590 /* found something! */
1596 dataiterator_entersub(Dataiterator *di)
1598 if (di->state == di_nextarrayelement)
1599 di->state = di_entersub;
1603 dataiterator_setpos(Dataiterator *di)
1605 if (di->kv.eof == 2)
1607 pool_clear_pos(di->pool);
1610 di->pool->pos.solvid = di->solvid;
1611 di->pool->pos.repo = di->repo;
1612 di->pool->pos.repodataid = di->data - di->repo->repodata;
1613 di->pool->pos.schema = di->kv.id;
1614 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1618 dataiterator_setpos_parent(Dataiterator *di)
1620 if (!di->kv.parent || di->kv.parent->eof == 2)
1622 pool_clear_pos(di->pool);
1625 di->pool->pos.solvid = di->solvid;
1626 di->pool->pos.repo = di->repo;
1627 di->pool->pos.repodataid = di->data - di->repo->repodata;
1628 di->pool->pos.schema = di->kv.parent->id;
1629 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1632 /* clones just the position, not the search keys/matcher */
1634 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1636 di->state = from->state;
1637 di->flags &= ~SEARCH_THISSOLVID;
1638 di->flags |= (from->flags & SEARCH_THISSOLVID);
1639 di->repo = from->repo;
1640 di->data = from->data;
1642 di->ddp = from->ddp;
1643 di->idp = from->idp;
1644 di->keyp = from->keyp;
1645 di->key = from->key;
1647 di->repodataid = from->repodataid;
1648 di->solvid = from->solvid;
1649 di->repoid = from->repoid;
1650 di->rootlevel = from->rootlevel;
1651 memcpy(di->parents, from->parents, sizeof(from->parents));
1652 di->nparents = from->nparents;
1656 for (i = 1; i < di->nparents; i++)
1657 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1658 di->kv.parent = &di->parents[di->nparents - 1].kv;
1663 dataiterator_seek(Dataiterator *di, int whence)
1665 if ((whence & DI_SEEK_STAY) != 0)
1666 di->rootlevel = di->nparents;
1667 switch (whence & ~DI_SEEK_STAY)
1670 if (di->state != di_nextarrayelement)
1672 if ((whence & DI_SEEK_STAY) != 0)
1673 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1674 di->state = di_entersub;
1676 case DI_SEEK_PARENT:
1683 if (di->rootlevel > di->nparents)
1684 di->rootlevel = di->nparents;
1685 di->dp = di->parents[di->nparents].dp;
1686 di->kv = di->parents[di->nparents].kv;
1687 di->keyp = di->parents[di->nparents].keyp;
1688 di->key = di->data->keys + *di->keyp;
1689 di->ddp = (unsigned char *)di->kv.str;
1690 di->keyname = di->keynames[di->nparents - di->rootlevel];
1691 di->state = di_nextarrayelement;
1693 case DI_SEEK_REWIND:
1699 di->dp = (unsigned char *)di->kv.parent->str;
1700 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1701 di->state = di_enterschema;
1709 dataiterator_skip_attribute(Dataiterator *di)
1711 if (di->state == di_nextsolvableattr)
1712 di->state = di_nextsolvablekey;
1714 di->state = di_nextkey;
1718 dataiterator_skip_solvable(Dataiterator *di)
1723 di->keyname = di->keynames[0];
1724 di->state = di_nextsolvable;
1728 dataiterator_skip_repo(Dataiterator *di)
1733 di->keyname = di->keynames[0];
1734 di->state = di_nextrepo;
1738 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1743 di->keyname = di->keynames[0];
1744 if (solvid == SOLVID_POS)
1746 di->repo = di->pool->pos.repo;
1753 di->data = di->repo->repodata + di->pool->pos.repodataid;
1755 di->solvid = solvid;
1756 di->state = di_enterrepo;
1757 di->flags |= SEARCH_THISSOLVID;
1762 di->repo = di->pool->solvables[solvid].repo;
1765 else if (di->repoid > 0)
1767 if (!di->pool->urepos)
1773 di->repo = di->pool->repos[di->repoid];
1776 di->solvid = solvid;
1778 di->flags |= SEARCH_THISSOLVID;
1779 di->state = di_enterrepo;
1783 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1789 di->repoid = 0; /* 0 means stay at repo */
1792 di->flags &= ~SEARCH_THISSOLVID;
1793 di->state = di_enterrepo;
1797 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1799 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1803 return datamatcher_match(ma, di->kv.str);
1806 /************************************************************************
1807 * data modify functions
1810 /* extend repodata so that it includes solvables p */
1812 repodata_extend(Repodata *data, Id p)
1814 if (data->start == data->end)
1815 data->start = data->end = p;
1818 int old = data->end - data->start;
1819 int new = p - data->end + 1;
1822 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1823 memset(data->attrs + old, 0, new * sizeof(Id *));
1825 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1826 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1829 if (p < data->start)
1831 int old = data->end - data->start;
1832 int new = data->start - p;
1835 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1836 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1837 memset(data->attrs, 0, new * sizeof(Id *));
1839 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1840 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1841 memset(data->incoreoffset, 0, new * sizeof(Id));
1846 /* shrink end of repodata */
1848 repodata_shrink(Repodata *data, int end)
1852 if (data->end <= end)
1854 if (data->start >= end)
1858 for (i = 0; i < data->end - data->start; i++)
1859 solv_free(data->attrs[i]);
1860 data->attrs = solv_free(data->attrs);
1862 data->incoreoffset = solv_free(data->incoreoffset);
1863 data->start = data->end = 0;
1868 for (i = end; i < data->end; i++)
1869 solv_free(data->attrs[i - data->start]);
1870 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1872 if (data->incoreoffset)
1873 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1877 /* extend repodata so that it includes solvables from start to start + num - 1 */
1879 repodata_extend_block(Repodata *data, Id start, Id num)
1883 if (!data->incoreoffset)
1885 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1886 data->start = start;
1887 data->end = start + num;
1890 repodata_extend(data, start);
1892 repodata_extend(data, start + num - 1);
1895 /**********************************************************************/
1898 #define REPODATA_ATTRS_BLOCK 31
1899 #define REPODATA_ATTRDATA_BLOCK 1023
1900 #define REPODATA_ATTRIDDATA_BLOCK 63
1901 #define REPODATA_ATTRNUM64DATA_BLOCK 15
1905 repodata_new_handle(Repodata *data)
1909 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1910 data->nxattrs = 2; /* -1: SOLVID_META */
1912 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1913 data->xattrs[data->nxattrs] = 0;
1914 return -(data->nxattrs++);
1918 repodata_get_attrp(Repodata *data, Id handle)
1922 if (handle == SOLVID_META && !data->xattrs)
1924 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1927 return data->xattrs - handle;
1929 if (handle < data->start || handle >= data->end)
1930 repodata_extend(data, handle);
1932 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1933 return data->attrs + (handle - data->start);
1937 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1943 app = repodata_get_attrp(data, handle);
1948 /* Determine equality based on the name only, allows us to change
1949 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1950 for (pp = ap; *pp; pp += 2)
1951 if (data->keys[*pp].name == data->keys[keyid].name)
1955 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1964 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1974 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1978 keyid = repodata_key2id(data, key, 1);
1979 repodata_insert_keyid(data, solvid, keyid, val, 1);
1983 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1987 key.type = REPOKEY_TYPE_ID;
1989 key.storage = KEY_STORAGE_INCORE;
1990 repodata_set(data, solvid, &key, id);
1994 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned long long num)
1998 key.type = REPOKEY_TYPE_NUM;
2000 key.storage = KEY_STORAGE_INCORE;
2001 if (num >= 0x80000000)
2003 data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
2004 data->attrnum64data[data->attrnum64datalen] = num;
2005 num = 0x80000000 | data->attrnum64datalen++;
2007 repodata_set(data, solvid, &key, (Id)num);
2011 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2015 if (data->localpool)
2016 id = stringpool_str2id(&data->spool, str, 1);
2018 id = pool_str2id(data->repo->pool, str, 1);
2020 key.type = REPOKEY_TYPE_ID;
2022 key.storage = KEY_STORAGE_INCORE;
2023 repodata_set(data, solvid, &key, id);
2027 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2031 key.type = REPOKEY_TYPE_CONSTANT;
2032 key.size = constant;
2033 key.storage = KEY_STORAGE_INCORE;
2034 repodata_set(data, solvid, &key, 0);
2038 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2042 key.type = REPOKEY_TYPE_CONSTANTID;
2044 key.storage = KEY_STORAGE_INCORE;
2045 repodata_set(data, solvid, &key, 0);
2049 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2053 key.type = REPOKEY_TYPE_VOID;
2055 key.storage = KEY_STORAGE_INCORE;
2056 repodata_set(data, solvid, &key, 0);
2060 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2065 l = strlen(str) + 1;
2067 key.type = REPOKEY_TYPE_STR;
2069 key.storage = KEY_STORAGE_INCORE;
2070 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2071 memcpy(data->attrdata + data->attrdatalen, str, l);
2072 repodata_set(data, solvid, &key, data->attrdatalen);
2073 data->attrdatalen += l;
2077 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2085 key.type = REPOKEY_TYPE_BINARY;
2087 key.storage = KEY_STORAGE_INCORE;
2088 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2089 dp = data->attrdata + data->attrdatalen;
2090 if (len >= (1 << 14))
2092 if (len >= (1 << 28))
2093 *dp++ = (len >> 28) | 128;
2094 if (len >= (1 << 21))
2095 *dp++ = (len >> 21) | 128;
2096 *dp++ = (len >> 14) | 128;
2098 if (len >= (1 << 7))
2099 *dp++ = (len >> 7) | 128;
2102 memcpy(dp, buf, len);
2103 repodata_set(data, solvid, &key, data->attrdatalen);
2104 data->attrdatalen = dp + len - data->attrdata;
2107 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2108 * so that the caller can append entrysize new elements plus the termination zero there */
2110 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2113 Id *ida, *pp, **ppp;
2115 /* check if it is the same as last time, this speeds things up a lot */
2116 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2118 /* great! just append the new data */
2119 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2120 data->attriddatalen--; /* overwrite terminating 0 */
2121 data->lastdatalen += entrysize;
2125 ppp = repodata_get_attrp(data, handle);
2129 for (; *pp; pp += 2)
2130 if (data->keys[*pp].name == keyname)
2133 if (!pp || !*pp || data->keys[*pp].type != keytype)
2135 /* not found. allocate new key */
2141 key.storage = KEY_STORAGE_INCORE;
2142 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2143 keyid = repodata_key2id(data, &key, 1);
2144 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2145 data->lasthandle = handle;
2146 data->lastkey = keyid;
2147 data->lastdatalen = data->attriddatalen + entrysize + 1;
2151 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2152 oldsize += entrysize;
2153 if (ida + 1 == data->attriddata + data->attriddatalen)
2155 /* this was the last entry, just append it */
2156 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2157 data->attriddatalen--; /* overwrite terminating 0 */
2161 /* too bad. move to back. */
2162 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2163 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2164 pp[1] = data->attriddatalen;
2165 data->attriddatalen += oldsize;
2167 data->lasthandle = handle;
2168 data->lastkey = *pp;
2169 data->lastdatalen = data->attriddatalen + entrysize + 1;
2173 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2174 const unsigned char *str)
2179 if (!(l = solv_chksum_len(type)))
2184 key.storage = KEY_STORAGE_INCORE;
2185 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2186 memcpy(data->attrdata + data->attrdatalen, str, l);
2187 repodata_set(data, solvid, &key, data->attrdatalen);
2188 data->attrdatalen += l;
2192 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2195 unsigned char buf[64];
2198 if (!(l = solv_chksum_len(type)))
2200 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2202 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2206 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2210 if (!(l = solv_chksum_len(type)))
2212 return pool_bin2hex(data->repo->pool, buf, l);
2215 /* rpm filenames don't contain the epoch, so strip it */
2216 static inline const char *
2217 evrid2vrstr(Pool *pool, Id evrid)
2219 const char *p, *evr = pool_id2str(pool, evrid);
2222 for (p = evr; *p >= '0' && *p <= '9'; p++)
2224 return p != evr && *p == ':' && p[1] ? p + 1 : evr;
2228 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2230 Pool *pool = data->repo->pool;
2232 const char *str, *fp;
2236 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2239 if ((dir = strrchr(file, '/')) != 0)
2250 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2255 if (l == 1 && dir[0] == '.')
2257 s = pool->solvables + solvid;
2260 str = pool_id2str(pool, s->arch);
2261 if (!strncmp(dir, str, l) && !str[l])
2262 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2264 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2267 char *dir2 = solv_strdup(dir);
2269 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2274 str = pool_id2str(pool, s->name);
2276 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2279 str = evrid2vrstr(pool, s->evr);
2281 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2284 str = pool_id2str(pool, s->arch);
2286 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2288 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2293 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2297 repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg)
2299 Pool *pool = data->repo->pool;
2300 Solvable *s = pool->solvables + solvid;
2301 const char *p, *sevr, *sarch, *name, *evr;
2303 p = strrchr(sourcepkg, '.');
2304 if (!p || strcmp(p, ".rpm") != 0)
2307 repodata_set_str(data, solvid, SOLVABLE_SOURCENAME, sourcepkg);
2311 while (p > sourcepkg && *p != '.')
2313 if (*p != '.' || p == sourcepkg)
2316 while (p > sourcepkg && *p != '-')
2318 if (*p != '-' || p == sourcepkg)
2321 while (p > sourcepkg && *p != '-')
2323 if (*p != '-' || p == sourcepkg)
2326 pool = s->repo->pool;
2328 name = pool_id2str(pool, s->name);
2329 if (name && !strncmp(sourcepkg, name, sevr - sourcepkg - 1) && name[sevr - sourcepkg - 1] == 0)
2330 repodata_set_void(data, solvid, SOLVABLE_SOURCENAME);
2332 repodata_set_id(data, solvid, SOLVABLE_SOURCENAME, pool_strn2id(pool, sourcepkg, sevr - sourcepkg - 1, 1));
2334 evr = evrid2vrstr(pool, s->evr);
2335 if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
2336 repodata_set_void(data, solvid, SOLVABLE_SOURCEEVR);
2338 repodata_set_id(data, solvid, SOLVABLE_SOURCEEVR, pool_strn2id(pool, sevr, sarch - sevr - 1, 1));
2340 if (!strcmp(sarch, "src.rpm"))
2341 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_SRC);
2342 else if (!strcmp(sarch, "nosrc.rpm"))
2343 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
2345 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, pool_strn2id(pool, sarch, strlen(sarch) - 4, 1));
2349 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2355 key.type = REPOKEY_TYPE_IDARRAY;
2357 key.storage = KEY_STORAGE_INCORE;
2358 repodata_set(data, solvid, &key, data->attriddatalen);
2359 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2360 for (i = 0; i < q->count; i++)
2361 data->attriddata[data->attriddatalen++] = q->elements[i];
2362 data->attriddata[data->attriddatalen++] = 0;
2366 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2370 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2372 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2373 data->attriddata[data->attriddatalen++] = dir;
2374 data->attriddata[data->attriddatalen++] = num;
2375 data->attriddata[data->attriddatalen++] = num2;
2376 data->attriddata[data->attriddatalen++] = 0;
2380 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2386 l = strlen(str) + 1;
2387 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2388 memcpy(data->attrdata + data->attrdatalen, str, l);
2389 stroff = data->attrdatalen;
2390 data->attrdatalen += l;
2393 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2395 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2396 data->attriddata[data->attriddatalen++] = dir;
2397 data->attriddata[data->attriddatalen++] = stroff;
2398 data->attriddata[data->attriddatalen++] = 0;
2402 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2405 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2407 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2408 data->attriddata[data->attriddatalen++] = id;
2409 data->attriddata[data->attriddatalen++] = 0;
2413 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2417 if (data->localpool)
2418 id = stringpool_str2id(&data->spool, str, 1);
2420 id = pool_str2id(data->repo->pool, str, 1);
2421 repodata_add_idarray(data, solvid, keyname, id);
2425 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2427 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2428 data->attriddata[data->attriddatalen++] = ghandle;
2429 data->attriddata[data->attriddatalen++] = 0;
2433 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2435 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2436 data->attriddata[data->attriddatalen++] = ghandle;
2437 data->attriddata[data->attriddatalen++] = 0;
2441 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2444 app = repodata_get_attrp(data, solvid);
2448 for (; *ap; ap += 2)
2449 if (data->keys[*ap].name == keyname)
2455 for (; *ap; ap += 2)
2457 if (data->keys[*ap].name == keyname)
2465 /* XXX: does not work correctly, needs fix in iterators! */
2467 repodata_delete(Repodata *data, Id solvid, Id keyname)
2471 key.type = REPOKEY_TYPE_DELETED;
2473 key.storage = KEY_STORAGE_INCORE;
2474 repodata_set(data, solvid, &key, 0);
2477 /* add all (uninternalized) attrs from src to dest */
2479 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2482 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2484 for (; *keyp; keyp += 2)
2485 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2488 /* add some (uninternalized) attrs from src to dest */
2490 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2493 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2495 for (; *keyp; keyp += 2)
2496 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2497 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2500 /* swap (uninternalized) attrs from src and dest */
2502 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2505 if (!data->attrs || dest == src)
2507 tmpattrs = data->attrs[dest - data->start];
2508 data->attrs[dest - data->start] = data->attrs[src - data->start];
2509 data->attrs[src - data->start] = tmpattrs;
2513 /**********************************************************************/
2515 /* TODO: unify with repo_write and repo_solv! */
2517 #define EXTDATA_BLOCK 1023
2525 data_addid(struct extdata *xd, Id sx)
2527 unsigned int x = (unsigned int)sx;
2530 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2531 dp = xd->buf + xd->len;
2536 *dp++ = (x >> 28) | 128;
2538 *dp++ = (x >> 21) | 128;
2539 *dp++ = (x >> 14) | 128;
2542 *dp++ = (x >> 7) | 128;
2544 xd->len = dp - xd->buf;
2548 data_addid64(struct extdata *xd, unsigned long long x)
2550 if (x >= 0x100000000)
2554 data_addid(xd, (Id)(x >> 35));
2555 xd->buf[xd->len - 1] |= 128;
2557 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2558 xd->buf[xd->len - 5] = (x >> 28) | 128;
2561 data_addid(xd, (Id)x);
2565 data_addideof(struct extdata *xd, Id sx, int eof)
2567 unsigned int x = (unsigned int)sx;
2570 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2571 dp = xd->buf + xd->len;
2576 *dp++ = (x >> 27) | 128;
2578 *dp++ = (x >> 20) | 128;
2579 *dp++ = (x >> 13) | 128;
2582 *dp++ = (x >> 6) | 128;
2583 *dp++ = eof ? (x & 63) : (x & 63) | 64;
2584 xd->len = dp - xd->buf;
2588 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2590 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2591 memcpy(xd->buf + xd->len, blob, len);
2595 /*********************************/
2597 /* internalalize some key into incore/vincore data */
2600 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2601 struct extdata *newvincore,
2603 Repokey *key, Id val)
2607 unsigned int oldvincorelen = 0;
2611 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2614 oldvincorelen = xd->len;
2618 case REPOKEY_TYPE_VOID:
2619 case REPOKEY_TYPE_CONSTANT:
2620 case REPOKEY_TYPE_CONSTANTID:
2622 case REPOKEY_TYPE_STR:
2623 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2625 case REPOKEY_TYPE_MD5:
2626 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2628 case REPOKEY_TYPE_SHA1:
2629 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2631 case REPOKEY_TYPE_SHA256:
2632 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2634 case REPOKEY_TYPE_NUM:
2635 if (val & 0x80000000)
2637 data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
2641 case REPOKEY_TYPE_ID:
2642 case REPOKEY_TYPE_DIR:
2643 data_addid(xd, val);
2645 case REPOKEY_TYPE_BINARY:
2648 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2649 dp += (unsigned int)len;
2650 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2653 case REPOKEY_TYPE_IDARRAY:
2654 for (ida = data->attriddata + val; *ida; ida++)
2655 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2657 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2658 for (ida = data->attriddata + val; *ida; ida += 3)
2660 data_addid(xd, ida[0]);
2661 data_addid(xd, ida[1]);
2662 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2665 case REPOKEY_TYPE_DIRSTRARRAY:
2666 for (ida = data->attriddata + val; *ida; ida += 2)
2668 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2669 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2672 case REPOKEY_TYPE_FIXARRAY:
2676 for (ida = data->attriddata + val; *ida; ida++)
2680 kp = data->xattrs[-*ida];
2688 schemaid = repodata_schema2id(data, schema, 1);
2689 else if (schemaid != repodata_schema2id(data, schema, 0))
2691 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2697 data_addid(xd, num);
2698 data_addid(xd, schemaid);
2699 for (ida = data->attriddata + val; *ida; ida++)
2701 Id *kp = data->xattrs[-*ida];
2705 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2709 case REPOKEY_TYPE_FLEXARRAY:
2712 for (ida = data->attriddata + val; *ida; ida++)
2714 data_addid(xd, num);
2715 for (ida = data->attriddata + val; *ida; ida++)
2717 Id *kp = data->xattrs[-*ida];
2720 data_addid(xd, 0); /* XXX */
2727 schemaid = repodata_schema2id(data, schema, 1);
2728 data_addid(xd, schemaid);
2729 kp = data->xattrs[-*ida];
2731 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2736 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2739 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2741 /* put offset/len in incore */
2742 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2743 oldvincorelen = xd->len - oldvincorelen;
2744 data_addid(newincore, oldvincorelen);
2749 repodata_internalize(Repodata *data)
2751 Repokey *key, solvkey;
2753 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2754 unsigned char *dp, *ndp;
2755 int newschema, oldcount;
2756 struct extdata newincore;
2757 struct extdata newvincore;
2760 if (!data->attrs && !data->xattrs)
2763 newvincore.buf = data->vincore;
2764 newvincore.len = data->vincorelen;
2766 /* find the solvables key, create if needed */
2767 memset(&solvkey, 0, sizeof(solvkey));
2768 solvkey.name = REPOSITORY_SOLVABLES;
2769 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2771 solvkey.storage = KEY_STORAGE_INCORE;
2772 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2774 schema = solv_malloc2(data->nkeys, sizeof(Id));
2775 seen = solv_malloc2(data->nkeys, sizeof(Id));
2777 /* Merge the data already existing (in data->schemata, ->incoredata and
2778 friends) with the new attributes in data->attrs[]. */
2779 nentry = data->end - data->start;
2780 memset(&newincore, 0, sizeof(newincore));
2781 data_addid(&newincore, 0); /* start data at offset 1 */
2783 data->mainschema = 0;
2784 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2786 /* join entry data */
2787 /* we start with the meta data, entry -1 */
2788 for (entry = -1; entry < nentry; entry++)
2790 memset(seen, 0, data->nkeys * sizeof(Id));
2792 dp = data->incoredata;
2795 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2796 dp = data_read_id(dp, &oldschema);
2799 fprintf(stderr, "oldschema %d\n", oldschema);
2800 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2801 fprintf(stderr, "schemadata %p\n", data->schemadata);
2803 /* seen: -1: old data 0: skipped >0: id + 1 */
2807 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2811 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2819 keyp = data->attrs ? data->attrs[entry] : 0;
2822 /* strip solvables key */
2824 for (sp = keyp = schema; *sp; sp++)
2825 if (*sp != solvkeyid)
2830 seen[solvkeyid] = 0;
2831 keyp = data->xattrs ? data->xattrs[1] : 0;
2834 for (; *keyp; keyp += 2)
2841 seen[*keyp] = keyp[1] + 1;
2843 if (entry < 0 && data->end != data->start)
2850 /* Ideally we'd like to sort the new schema here, to ensure
2851 schema equality independend of the ordering. We can't do that
2852 yet. For once see below (old ids need to come before new ids).
2853 An additional difficulty is that we also need to move
2854 the values with the keys. */
2855 schemaid = repodata_schema2id(data, schema, 1);
2857 schemaid = oldschema;
2860 /* Now create data blob. We walk through the (possibly new) schema
2861 and either copy over old data, or insert the new. */
2862 /* XXX Here we rely on the fact that the (new) schema has the form
2863 o1 o2 o3 o4 ... | n1 n2 n3 ...
2864 (oX being the old keyids (possibly overwritten), and nX being
2865 the new keyids). This rules out sorting the keyids in order
2866 to ensure a small schema count. */
2868 data->incoreoffset[entry] = newincore.len;
2869 data_addid(&newincore, schemaid);
2872 data->mainschema = schemaid;
2873 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2875 keypstart = data->schemadata + data->schemata[schemaid];
2876 for (keyp = keypstart; *keyp; keyp++)
2879 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2880 if (*keyp == solvkeyid)
2882 /* add flexarray entry count */
2883 data_addid(&newincore, data->end - data->start);
2886 key = data->keys + *keyp;
2888 fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, pool_id2str(data->repo->pool, key->name), pool_id2str(data->repo->pool, key->type));
2893 /* Skip the data associated with this old key. */
2894 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2896 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2897 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2899 else if (key->storage == KEY_STORAGE_INCORE)
2900 ndp = data_skip_key(data, dp, key);
2903 if (seen[*keyp] == -1)
2905 /* If this key was an old one _and_ was not overwritten with
2906 a different value copy over the old value (we skipped it
2909 data_addblob(&newincore, dp, ndp - dp);
2912 else if (seen[*keyp])
2914 /* Otherwise we have a new value. Parse it into the internal
2916 repodata_serialize_key(data, &newincore, &newvincore,
2917 schema, key, seen[*keyp] - 1);
2921 if (entry >= 0 && data->attrs && data->attrs[entry])
2922 data->attrs[entry] = solv_free(data->attrs[entry]);
2924 /* free all xattrs */
2925 for (entry = 0; entry < data->nxattrs; entry++)
2926 if (data->xattrs[entry])
2927 solv_free(data->xattrs[entry]);
2928 data->xattrs = solv_free(data->xattrs);
2931 data->lasthandle = 0;
2933 data->lastdatalen = 0;
2936 repodata_free_schemahash(data);
2938 solv_free(data->incoredata);
2939 data->incoredata = newincore.buf;
2940 data->incoredatalen = newincore.len;
2941 data->incoredatafree = 0;
2943 solv_free(data->vincore);
2944 data->vincore = newvincore.buf;
2945 data->vincorelen = newvincore.len;
2947 data->attrs = solv_free(data->attrs);
2948 data->attrdata = solv_free(data->attrdata);
2949 data->attriddata = solv_free(data->attriddata);
2950 data->attrnum64data = solv_free(data->attrnum64data);
2951 data->attrdatalen = 0;
2952 data->attriddatalen = 0;
2953 data->attrnum64datalen = 0;
2957 repodata_disable_paging(Repodata *data)
2959 if (maybe_load_repodata(data, 0))
2960 repopagestore_disable_paging(&data->store);
2964 repodata_load_stub(Repodata *data)
2966 Repo *repo = data->repo;
2967 Pool *pool = repo->pool;
2969 struct _Pool_tmpspace oldtmpspace;
2971 if (!pool->loadcallback)
2973 data->state = REPODATA_ERROR;
2976 data->state = REPODATA_LOADING;
2978 /* save tmp space */
2979 oldtmpspace = pool->tmpspace;
2980 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2982 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2984 /* restore tmp space */
2985 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2986 solv_free(pool->tmpspace.buf[i]);
2987 pool->tmpspace = oldtmpspace;
2989 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2993 repodata_create_stubs(Repodata *data)
2995 Repo *repo = data->repo;
2996 Pool *pool = repo->pool;
3003 int datastart, dataend;
3005 repodataid = data - repo->repodata;
3006 datastart = data->start;
3007 dataend = data->end;
3008 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
3009 while (dataiterator_step(&di))
3011 if (di.data - repo->repodata != repodataid)
3015 dataiterator_free(&di);
3018 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
3019 for (i = 0; i < cnt; i++)
3021 sdata = repo_add_repodata(repo, 0);
3022 if (dataend > datastart)
3023 repodata_extend_block(sdata, datastart, dataend - datastart);
3024 stubdataids[i] = sdata - repo->repodata;
3025 sdata->state = REPODATA_STUB;
3026 sdata->loadcallback = repodata_load_stub;
3029 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
3031 while (dataiterator_step(&di))
3033 if (di.data - repo->repodata != repodataid)
3035 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
3037 dataiterator_entersub(&di);
3038 sdata = repo->repodata + stubdataids[i++];
3042 switch (di.key->type)
3044 case REPOKEY_TYPE_ID:
3045 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
3047 case REPOKEY_TYPE_CONSTANTID:
3048 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
3050 case REPOKEY_TYPE_STR:
3051 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
3053 case REPOKEY_TYPE_VOID:
3054 repodata_set_void(sdata, SOLVID_META, di.key->name);
3056 case REPOKEY_TYPE_NUM:
3057 repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv));
3059 case REPOKEY_TYPE_MD5:
3060 case REPOKEY_TYPE_SHA1:
3061 case REPOKEY_TYPE_SHA256:
3062 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
3064 case REPOKEY_TYPE_IDARRAY:
3065 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
3066 if (di.key->name == REPOSITORY_KEYS)
3073 xkeyname = di.kv.id;
3076 xkey.name = xkeyname;
3077 xkey.type = di.kv.id;
3078 xkey.storage = KEY_STORAGE_INCORE;
3080 repodata_key2id(sdata, &xkey, 1);
3087 dataiterator_free(&di);
3088 for (i = 0; i < cnt; i++)
3089 repodata_internalize(repo->repodata + stubdataids[i]);
3090 solv_free(stubdataids);
3094 repodata_memused(Repodata *data)
3096 return data->incoredatalen + data->vincorelen;
3100 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: