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 int *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)
696 dp = data_fetch(dp, &kv, key);
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);
736 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
744 dp = find_key_data(data, solvid, keyname, &key);
747 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
751 dp = data_read_ideof(dp, &id, &eof);
760 repodata_globalize_id(Repodata *data, Id id, int create)
762 if (!id || !data || !data->localpool)
764 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
768 repodata_localize_id(Repodata *data, Id id, int create)
770 if (!id || !data || !data->localpool)
772 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
776 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
781 ap = data->attrs[solvid - data->start];
786 if (data->keys[*ap].name != keyname)
788 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
790 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
798 /************************************************************************
804 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
808 case REPOKEY_TYPE_ID:
809 case REPOKEY_TYPE_CONSTANTID:
810 case REPOKEY_TYPE_IDARRAY:
811 if (data && data->localpool)
812 kv->str = stringpool_id2str(&data->spool, kv->id);
814 kv->str = pool_id2str(pool, kv->id);
815 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
818 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
820 if (*s == ':' && s > kv->str)
824 case REPOKEY_TYPE_STR:
826 case REPOKEY_TYPE_DIRSTRARRAY:
827 if (!(flags & SEARCH_FILES))
828 return 1; /* match just the basename */
829 /* Put the full filename into kv->str. */
830 kv->str = repodata_dir2str(data, kv->id, kv->str);
831 /* And to compensate for that put the "empty" directory into
832 kv->id, so that later calls to repodata_dir2str on this data
833 come up with the same filename again. */
836 case REPOKEY_TYPE_MD5:
837 case REPOKEY_TYPE_SHA1:
838 case REPOKEY_TYPE_SHA256:
839 if (!(flags & SEARCH_CHECKSUMS))
840 return 0; /* skip em */
841 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
849 struct subschema_data {
855 /* search a specific repodata */
857 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
861 Id keyid, *kp, *keyp;
862 unsigned char *dp, *ddp;
868 if (!maybe_load_repodata(data, keyname))
870 if (solvid == SOLVID_SUBSCHEMA)
872 struct subschema_data *subd = cbdata;
873 cbdata = subd->cbdata;
875 schema = subd->parent->id;
876 dp = (unsigned char *)subd->parent->str;
877 kv.parent = subd->parent;
882 dp = solvid2data(data, solvid, &schema);
885 s = data->repo->pool->solvables + solvid;
888 keyp = data->schemadata + data->schemata[schema];
891 /* search for a specific key */
892 for (kp = keyp; *kp; kp++)
893 if (data->keys[*kp].name == keyname)
897 dp = forward_to_key(data, *kp, keyp, dp);
903 while ((keyid = *keyp++) != 0)
906 key = data->keys + keyid;
907 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
909 if (key->type == REPOKEY_TYPE_DELETED)
911 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
913 struct subschema_data subd;
917 subd.cbdata = cbdata;
920 ddp = data_read_id(ddp, &nentries);
924 while (ddp && nentries > 0)
928 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
929 ddp = data_read_id(ddp, &schema);
931 kv.str = (char *)ddp;
932 stop = callback(cbdata, s, data, key, &kv);
933 if (stop > SEARCH_NEXT_KEY)
935 if (stop && stop != SEARCH_ENTERSUB)
937 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
938 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
939 ddp = data_skip_schema(data, ddp, schema);
942 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
946 kv.str = (char *)ddp;
947 stop = callback(cbdata, s, data, key, &kv);
948 if (stop > SEARCH_NEXT_KEY)
958 ddp = data_fetch(ddp, &kv, key);
961 stop = callback(cbdata, s, data, key, &kv);
964 while (!kv.eof && !stop);
965 if (onekey || stop > SEARCH_NEXT_KEY)
971 repodata_setpos_kv(Repodata *data, KeyValue *kv)
973 Pool *pool = data->repo->pool;
975 pool_clear_pos(pool);
978 pool->pos.repo = data->repo;
979 pool->pos.repodataid = data - data->repo->repodata;
980 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
981 pool->pos.schema = kv->id;
985 /************************************************************************
986 * data iterator functions
990 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1004 case SOLVABLE_VENDOR:
1007 case SOLVABLE_PROVIDES:
1009 return s->provides ? s->repo->idarraydata + s->provides : 0;
1010 case SOLVABLE_OBSOLETES:
1012 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1013 case SOLVABLE_CONFLICTS:
1015 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1016 case SOLVABLE_REQUIRES:
1018 return s->requires ? s->repo->idarraydata + s->requires : 0;
1019 case SOLVABLE_RECOMMENDS:
1021 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1022 case SOLVABLE_SUPPLEMENTS:
1024 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1025 case SOLVABLE_SUGGESTS:
1027 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1028 case SOLVABLE_ENHANCES:
1030 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1033 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1040 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1046 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1048 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1049 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1052 solv_free(ma->matchdata);
1053 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1060 datamatcher_free(Datamatcher *ma)
1062 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1064 regfree(ma->matchdata);
1065 ma->matchdata = solv_free(ma->matchdata);
1070 datamatcher_match(Datamatcher *ma, const char *str)
1073 switch ((ma->flags & SEARCH_STRINGMASK))
1075 case SEARCH_SUBSTRING:
1076 if (ma->flags & SEARCH_NOCASE)
1078 if (!strcasestr(str, ma->match))
1083 if (!strstr(str, ma->match))
1088 if (ma->flags & SEARCH_NOCASE)
1090 if (strcasecmp(ma->match, str))
1095 if (strcmp(ma->match, str))
1099 case SEARCH_STRINGSTART:
1100 if (ma->flags & SEARCH_NOCASE)
1102 if (strncasecmp(ma->match, str, strlen(ma->match)))
1107 if (strncmp(ma->match, str, strlen(ma->match)))
1111 case SEARCH_STRINGEND:
1112 l = strlen(str) - strlen(ma->match);
1115 if (ma->flags & SEARCH_NOCASE)
1117 if (strcasecmp(ma->match, str + l))
1122 if (strcmp(ma->match, str + l))
1127 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1131 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1141 repodata_filelistfilter_matches(Repodata *data, const char *str)
1143 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1144 /* for now hardcoded */
1145 if (strstr(str, "bin/"))
1147 if (!strncmp(str, "/etc/", 5))
1149 if (!strcmp(str, "/usr/lib/sendmail"))
1171 di_nextarrayelement,
1177 di_entersolvablekey,
1181 /* see dataiterator.h for documentation */
1183 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1185 memset(di, 0, sizeof(*di));
1187 di->flags = flags & ~SEARCH_THISSOLVID;
1188 if (!pool || (repo && repo->pool != pool))
1196 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1202 di->keyname = keyname;
1203 di->keynames[0] = keyname;
1204 dataiterator_set_search(di, repo, p);
1209 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1212 memset(&di->matcher, 0, sizeof(di->matcher));
1213 if (from->matcher.match)
1214 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1219 for (i = 1; i < di->nparents; i++)
1220 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1221 di->kv.parent = &di->parents[di->nparents - 1].kv;
1226 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1228 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1229 datamatcher_free(&di->matcher);
1230 memset(&di->matcher, 0, sizeof(di->matcher));
1234 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1244 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1248 di->flags &= ~SEARCH_THISSOLVID;
1252 if (!di->pool->urepos)
1260 di->repo = di->pool->repos[di->repoid];
1262 di->state = di_enterrepo;
1264 dataiterator_jump_to_solvid(di, p);
1268 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1271 di->keyname = keyname;
1272 di->keynames[0] = keyname;
1276 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1280 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1282 di->state = di_bye; /* sorry */
1285 for (i = di->nkeynames + 1; i > 0; i--)
1286 di->keynames[i] = di->keynames[i - 1];
1287 di->keynames[0] = di->keyname = keyname;
1292 dataiterator_free(Dataiterator *di)
1294 if (di->matcher.match)
1295 datamatcher_free(&di->matcher);
1298 static inline unsigned char *
1299 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1301 Id *keyp = di->keyp;
1302 Repokey *keys = di->data->keys;
1305 for (keyp = di->keyp; *keyp; keyp++)
1306 if (keys[*keyp].name == keyname)
1310 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1318 dataiterator_filelistcheck(Dataiterator *di)
1321 int needcomplete = 0;
1322 Repodata *data = di->data;
1324 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1325 if (!di->matcher.match
1326 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1327 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1328 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1330 if (data->state != REPODATA_AVAILABLE)
1331 return needcomplete ? 1 : 0;
1332 for (j = 1; j < data->nkeys; j++)
1333 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1335 return j == data->nkeys && !needcomplete ? 0 : 1;
1339 dataiterator_step(Dataiterator *di)
1347 case di_enterrepo: di_enterrepo:
1348 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1350 if (!(di->flags & SEARCH_THISSOLVID))
1352 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1353 goto di_nextsolvable;
1357 case di_entersolvable: di_entersolvable:
1360 di->repodataid = 1; /* reset repodata iterator */
1361 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)
1363 extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
1365 di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1367 goto di_entersolvablekey;
1372 case di_enterrepodata: di_enterrepodata:
1375 if (di->repodataid >= di->repo->nrepodata)
1376 goto di_nextsolvable;
1377 di->data = di->repo->repodata + di->repodataid;
1379 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1380 goto di_nextrepodata;
1381 if (!maybe_load_repodata(di->data, di->keyname))
1382 goto di_nextrepodata;
1383 di->dp = solvid2data(di->data, di->solvid, &schema);
1385 goto di_nextrepodata;
1386 if (di->solvid == SOLVID_POS)
1387 di->solvid = di->pool->pos.solvid;
1388 /* reset key iterator */
1389 di->keyp = di->data->schemadata + di->data->schemata[schema];
1392 case di_enterschema: di_enterschema:
1394 di->dp = dataiterator_find_keyname(di, di->keyname);
1395 if (!di->dp || !*di->keyp)
1399 goto di_nextrepodata;
1403 case di_enterkey: di_enterkey:
1405 di->key = di->data->keys + *di->keyp;
1406 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1409 if (di->key->type == REPOKEY_TYPE_DELETED)
1411 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1413 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1419 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1421 di->state = di_nextkey;
1423 di->state = di_nextattr;
1426 case di_nextkey: di_nextkey:
1427 if (!di->keyname && *++di->keyp)
1433 case di_nextrepodata: di_nextrepodata:
1434 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1435 goto di_enterrepodata;
1438 case di_nextsolvable: di_nextsolvable:
1439 if (!(di->flags & SEARCH_THISSOLVID))
1442 di->solvid = di->repo->start;
1445 for (; di->solvid < di->repo->end; di->solvid++)
1447 if (di->pool->solvables[di->solvid].repo == di->repo)
1448 goto di_entersolvable;
1453 case di_nextrepo: di_nextrepo:
1458 if (di->repoid < di->pool->nrepos)
1460 di->repo = di->pool->repos[di->repoid];
1466 case di_bye: di_bye:
1470 case di_enterarray: di_enterarray:
1471 if (di->key->name == REPOSITORY_SOLVABLES)
1473 di->ddp = data_read_id(di->ddp, &di->kv.num);
1478 case di_nextarrayelement: di_nextarrayelement:
1481 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1482 if (di->kv.entry == di->kv.num)
1484 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1486 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1488 di->kv.str = (char *)di->ddp;
1490 di->state = di_nextkey;
1493 if (di->kv.entry == di->kv.num - 1)
1495 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1496 di->ddp = data_read_id(di->ddp, &di->kv.id);
1497 di->kv.str = (char *)di->ddp;
1498 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1500 if ((di->flags & SEARCH_SUB) != 0)
1501 di->state = di_entersub;
1503 di->state = di_nextarrayelement;
1506 case di_entersub: di_entersub:
1507 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1508 goto di_nextarrayelement; /* sorry, full */
1509 di->parents[di->nparents].kv = di->kv;
1510 di->parents[di->nparents].dp = di->dp;
1511 di->parents[di->nparents].keyp = di->keyp;
1512 di->dp = (unsigned char *)di->kv.str;
1513 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1514 memset(&di->kv, 0, sizeof(di->kv));
1515 di->kv.parent = &di->parents[di->nparents].kv;
1517 di->keyname = di->keynames[di->nparents - di->rootlevel];
1518 goto di_enterschema;
1520 case di_leavesub: di_leavesub:
1521 if (di->nparents - 1 < di->rootlevel)
1524 di->dp = di->parents[di->nparents].dp;
1525 di->kv = di->parents[di->nparents].kv;
1526 di->keyp = di->parents[di->nparents].keyp;
1527 di->key = di->data->keys + *di->keyp;
1528 di->ddp = (unsigned char *)di->kv.str;
1529 di->keyname = di->keynames[di->nparents - di->rootlevel];
1530 goto di_nextarrayelement;
1532 /* special solvable attr handling follows */
1534 case di_nextsolvablekey: di_nextsolvablekey:
1535 if (di->keyname || di->key->name == RPM_RPMDBID)
1536 goto di_enterrepodata;
1540 case di_entersolvablekey: di_entersolvablekey:
1541 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1542 if (!di->idp || !*di->idp)
1543 goto di_nextsolvablekey;
1547 di->kv.id = *di->idp;
1548 di->kv.num = *di->idp; /* for rpmdbid */
1550 di->state = di_nextsolvablekey;
1556 case di_nextsolvableattr:
1557 di->state = di_nextsolvableattr;
1558 di->kv.id = *di->idp++;
1563 di->state = di_nextsolvablekey;
1569 if (di->matcher.match)
1571 /* simple pre-check so that we don't need to stringify */
1572 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))
1574 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1575 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1578 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1580 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1584 if (!datamatcher_match(&di->matcher, di->kv.str))
1587 /* found something! */
1593 dataiterator_entersub(Dataiterator *di)
1595 if (di->state == di_nextarrayelement)
1596 di->state = di_entersub;
1600 dataiterator_setpos(Dataiterator *di)
1602 if (di->kv.eof == 2)
1604 pool_clear_pos(di->pool);
1607 di->pool->pos.solvid = di->solvid;
1608 di->pool->pos.repo = di->repo;
1609 di->pool->pos.repodataid = di->data - di->repo->repodata;
1610 di->pool->pos.schema = di->kv.id;
1611 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1615 dataiterator_setpos_parent(Dataiterator *di)
1617 if (!di->kv.parent || di->kv.parent->eof == 2)
1619 pool_clear_pos(di->pool);
1622 di->pool->pos.solvid = di->solvid;
1623 di->pool->pos.repo = di->repo;
1624 di->pool->pos.repodataid = di->data - di->repo->repodata;
1625 di->pool->pos.schema = di->kv.parent->id;
1626 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1629 /* clones just the position, not the search keys/matcher */
1631 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1633 di->state = from->state;
1634 di->flags &= ~SEARCH_THISSOLVID;
1635 di->flags |= (from->flags & SEARCH_THISSOLVID);
1636 di->repo = from->repo;
1637 di->data = from->data;
1639 di->ddp = from->ddp;
1640 di->idp = from->idp;
1641 di->keyp = from->keyp;
1642 di->key = from->key;
1644 di->repodataid = from->repodataid;
1645 di->solvid = from->solvid;
1646 di->repoid = from->repoid;
1647 di->rootlevel = from->rootlevel;
1648 memcpy(di->parents, from->parents, sizeof(from->parents));
1649 di->nparents = from->nparents;
1653 for (i = 1; i < di->nparents; i++)
1654 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1655 di->kv.parent = &di->parents[di->nparents - 1].kv;
1660 dataiterator_seek(Dataiterator *di, int whence)
1662 if ((whence & DI_SEEK_STAY) != 0)
1663 di->rootlevel = di->nparents;
1664 switch (whence & ~DI_SEEK_STAY)
1667 if (di->state != di_nextarrayelement)
1669 if ((whence & DI_SEEK_STAY) != 0)
1670 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1671 di->state = di_entersub;
1673 case DI_SEEK_PARENT:
1680 if (di->rootlevel > di->nparents)
1681 di->rootlevel = di->nparents;
1682 di->dp = di->parents[di->nparents].dp;
1683 di->kv = di->parents[di->nparents].kv;
1684 di->keyp = di->parents[di->nparents].keyp;
1685 di->key = di->data->keys + *di->keyp;
1686 di->ddp = (unsigned char *)di->kv.str;
1687 di->keyname = di->keynames[di->nparents - di->rootlevel];
1688 di->state = di_nextarrayelement;
1690 case DI_SEEK_REWIND:
1696 di->dp = (unsigned char *)di->kv.parent->str;
1697 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1698 di->state = di_enterschema;
1706 dataiterator_skip_attribute(Dataiterator *di)
1708 if (di->state == di_nextsolvableattr)
1709 di->state = di_nextsolvablekey;
1711 di->state = di_nextkey;
1715 dataiterator_skip_solvable(Dataiterator *di)
1720 di->keyname = di->keynames[0];
1721 di->state = di_nextsolvable;
1725 dataiterator_skip_repo(Dataiterator *di)
1730 di->keyname = di->keynames[0];
1731 di->state = di_nextrepo;
1735 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1740 di->keyname = di->keynames[0];
1741 if (solvid == SOLVID_POS)
1743 di->repo = di->pool->pos.repo;
1750 di->data = di->repo->repodata + di->pool->pos.repodataid;
1752 di->solvid = solvid;
1753 di->state = di_enterrepo;
1754 di->flags |= SEARCH_THISSOLVID;
1759 di->repo = di->pool->solvables[solvid].repo;
1762 else if (di->repoid > 0)
1764 if (!di->pool->urepos)
1770 di->repo = di->pool->repos[di->repoid];
1773 di->solvid = solvid;
1775 di->flags |= SEARCH_THISSOLVID;
1776 di->state = di_enterrepo;
1780 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1786 di->repoid = 0; /* 0 means stay at repo */
1789 di->flags &= ~SEARCH_THISSOLVID;
1790 di->state = di_enterrepo;
1794 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1796 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1800 return datamatcher_match(ma, di->kv.str);
1803 /************************************************************************
1804 * data modify functions
1807 /* extend repodata so that it includes solvables p */
1809 repodata_extend(Repodata *data, Id p)
1811 if (data->start == data->end)
1812 data->start = data->end = p;
1815 int old = data->end - data->start;
1816 int new = p - data->end + 1;
1819 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1820 memset(data->attrs + old, 0, new * sizeof(Id *));
1822 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1823 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1826 if (p < data->start)
1828 int old = data->end - data->start;
1829 int new = data->start - p;
1832 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1833 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1834 memset(data->attrs, 0, new * sizeof(Id *));
1836 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1837 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1838 memset(data->incoreoffset, 0, new * sizeof(Id));
1843 /* shrink end of repodata */
1845 repodata_shrink(Repodata *data, int end)
1849 if (data->end <= end)
1851 if (data->start >= end)
1855 for (i = 0; i < data->end - data->start; i++)
1856 solv_free(data->attrs[i]);
1857 data->attrs = solv_free(data->attrs);
1859 data->incoreoffset = solv_free(data->incoreoffset);
1860 data->start = data->end = 0;
1865 for (i = end; i < data->end; i++)
1866 solv_free(data->attrs[i - data->start]);
1867 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1869 if (data->incoreoffset)
1870 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1874 /* extend repodata so that it includes solvables from start to start + num - 1 */
1876 repodata_extend_block(Repodata *data, Id start, Id num)
1880 if (!data->incoreoffset)
1882 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1883 data->start = start;
1884 data->end = start + num;
1887 repodata_extend(data, start);
1889 repodata_extend(data, start + num - 1);
1892 /**********************************************************************/
1895 #define REPODATA_ATTRS_BLOCK 31
1896 #define REPODATA_ATTRDATA_BLOCK 1023
1897 #define REPODATA_ATTRIDDATA_BLOCK 63
1898 #define REPODATA_ATTRNUM64DATA_BLOCK 15
1902 repodata_new_handle(Repodata *data)
1906 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1907 data->nxattrs = 2; /* -1: SOLVID_META */
1909 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1910 data->xattrs[data->nxattrs] = 0;
1911 return -(data->nxattrs++);
1915 repodata_get_attrp(Repodata *data, Id handle)
1919 if (handle == SOLVID_META && !data->xattrs)
1921 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1924 return data->xattrs - handle;
1926 if (handle < data->start || handle >= data->end)
1927 repodata_extend(data, handle);
1929 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1930 return data->attrs + (handle - data->start);
1934 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1940 app = repodata_get_attrp(data, handle);
1945 /* Determine equality based on the name only, allows us to change
1946 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1947 for (pp = ap; *pp; pp += 2)
1948 if (data->keys[*pp].name == data->keys[keyid].name)
1952 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1961 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1971 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1975 keyid = repodata_key2id(data, key, 1);
1976 repodata_insert_keyid(data, solvid, keyid, val, 1);
1980 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1984 key.type = REPOKEY_TYPE_ID;
1986 key.storage = KEY_STORAGE_INCORE;
1987 repodata_set(data, solvid, &key, id);
1991 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned int num)
1995 key.type = REPOKEY_TYPE_NUM;
1997 key.storage = KEY_STORAGE_INCORE;
1998 if (num >= 0x80000000)
2000 data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
2001 data->attrnum64data[data->attrnum64datalen] = num;
2002 num = 0x80000000 | data->attrnum64datalen++;
2004 repodata_set(data, solvid, &key, (Id)num);
2008 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2012 if (data->localpool)
2013 id = stringpool_str2id(&data->spool, str, 1);
2015 id = pool_str2id(data->repo->pool, str, 1);
2017 key.type = REPOKEY_TYPE_ID;
2019 key.storage = KEY_STORAGE_INCORE;
2020 repodata_set(data, solvid, &key, id);
2024 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2028 key.type = REPOKEY_TYPE_CONSTANT;
2029 key.size = constant;
2030 key.storage = KEY_STORAGE_INCORE;
2031 repodata_set(data, solvid, &key, 0);
2035 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2039 key.type = REPOKEY_TYPE_CONSTANTID;
2041 key.storage = KEY_STORAGE_INCORE;
2042 repodata_set(data, solvid, &key, 0);
2046 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2050 key.type = REPOKEY_TYPE_VOID;
2052 key.storage = KEY_STORAGE_INCORE;
2053 repodata_set(data, solvid, &key, 0);
2057 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2062 l = strlen(str) + 1;
2064 key.type = REPOKEY_TYPE_STR;
2066 key.storage = KEY_STORAGE_INCORE;
2067 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2068 memcpy(data->attrdata + data->attrdatalen, str, l);
2069 repodata_set(data, solvid, &key, data->attrdatalen);
2070 data->attrdatalen += l;
2074 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2082 key.type = REPOKEY_TYPE_BINARY;
2084 key.storage = KEY_STORAGE_INCORE;
2085 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2086 dp = data->attrdata + data->attrdatalen;
2087 if (len >= (1 << 14))
2089 if (len >= (1 << 28))
2090 *dp++ = (len >> 28) | 128;
2091 if (len >= (1 << 21))
2092 *dp++ = (len >> 21) | 128;
2093 *dp++ = (len >> 14) | 128;
2095 if (len >= (1 << 7))
2096 *dp++ = (len >> 7) | 128;
2099 memcpy(dp, buf, len);
2100 repodata_set(data, solvid, &key, data->attrdatalen);
2101 data->attrdatalen = dp + len - data->attrdata;
2104 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2105 * so that the caller can append entrysize new elements plus the termination zero there */
2107 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2110 Id *ida, *pp, **ppp;
2112 /* check if it is the same as last time, this speeds things up a lot */
2113 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2115 /* great! just append the new data */
2116 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2117 data->attriddatalen--; /* overwrite terminating 0 */
2118 data->lastdatalen += entrysize;
2122 ppp = repodata_get_attrp(data, handle);
2126 for (; *pp; pp += 2)
2127 if (data->keys[*pp].name == keyname)
2130 if (!pp || !*pp || data->keys[*pp].type != keytype)
2132 /* not found. allocate new key */
2138 key.storage = KEY_STORAGE_INCORE;
2139 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2140 keyid = repodata_key2id(data, &key, 1);
2141 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2142 data->lasthandle = handle;
2143 data->lastkey = keyid;
2144 data->lastdatalen = data->attriddatalen + entrysize + 1;
2148 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2149 oldsize += entrysize;
2150 if (ida + 1 == data->attriddata + data->attriddatalen)
2152 /* this was the last entry, just append it */
2153 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2154 data->attriddatalen--; /* overwrite terminating 0 */
2158 /* too bad. move to back. */
2159 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2160 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2161 pp[1] = data->attriddatalen;
2162 data->attriddatalen += oldsize;
2164 data->lasthandle = handle;
2165 data->lastkey = *pp;
2166 data->lastdatalen = data->attriddatalen + entrysize + 1;
2170 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2171 const unsigned char *str)
2176 if (!(l = solv_chksum_len(type)))
2181 key.storage = KEY_STORAGE_INCORE;
2182 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2183 memcpy(data->attrdata + data->attrdatalen, str, l);
2184 repodata_set(data, solvid, &key, data->attrdatalen);
2185 data->attrdatalen += l;
2189 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2192 unsigned char buf[64];
2195 if (!(l = solv_chksum_len(type)))
2197 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2199 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2203 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2207 if (!(l = solv_chksum_len(type)))
2209 return pool_bin2hex(data->repo->pool, buf, l);
2212 /* rpm filenames don't contain the epoch, so strip it */
2213 static inline const char *
2214 evrid2vrstr(Pool *pool, Id evrid)
2216 const char *p, *evr = pool_id2str(pool, evrid);
2219 for (p = evr; *p >= '0' && *p <= '9'; p++)
2221 return p != evr && *p == ':' ? p + 1 : evr;
2225 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2227 Pool *pool = data->repo->pool;
2229 const char *str, *fp;
2233 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2236 if ((dir = strrchr(file, '/')) != 0)
2247 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2252 if (l == 1 && dir[0] == '.')
2254 s = pool->solvables + solvid;
2257 str = pool_id2str(pool, s->arch);
2258 if (!strncmp(dir, str, l) && !str[l])
2259 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2261 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2264 char *dir2 = solv_strdup(dir);
2266 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2271 str = pool_id2str(pool, s->name);
2273 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2276 str = evrid2vrstr(pool, s->evr);
2278 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2281 str = pool_id2str(pool, s->arch);
2283 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2285 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2290 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2294 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2300 key.type = REPOKEY_TYPE_IDARRAY;
2302 key.storage = KEY_STORAGE_INCORE;
2303 repodata_set(data, solvid, &key, data->attriddatalen);
2304 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2305 for (i = 0; i < q->count; i++)
2306 data->attriddata[data->attriddatalen++] = q->elements[i];
2307 data->attriddata[data->attriddatalen++] = 0;
2311 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2315 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2317 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2318 data->attriddata[data->attriddatalen++] = dir;
2319 data->attriddata[data->attriddatalen++] = num;
2320 data->attriddata[data->attriddatalen++] = num2;
2321 data->attriddata[data->attriddatalen++] = 0;
2325 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2331 l = strlen(str) + 1;
2332 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2333 memcpy(data->attrdata + data->attrdatalen, str, l);
2334 stroff = data->attrdatalen;
2335 data->attrdatalen += l;
2338 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2340 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2341 data->attriddata[data->attriddatalen++] = dir;
2342 data->attriddata[data->attriddatalen++] = stroff;
2343 data->attriddata[data->attriddatalen++] = 0;
2347 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2350 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2352 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2353 data->attriddata[data->attriddatalen++] = id;
2354 data->attriddata[data->attriddatalen++] = 0;
2358 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2362 if (data->localpool)
2363 id = stringpool_str2id(&data->spool, str, 1);
2365 id = pool_str2id(data->repo->pool, str, 1);
2366 repodata_add_idarray(data, solvid, keyname, id);
2370 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2372 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2373 data->attriddata[data->attriddatalen++] = ghandle;
2374 data->attriddata[data->attriddatalen++] = 0;
2378 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2380 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2381 data->attriddata[data->attriddatalen++] = ghandle;
2382 data->attriddata[data->attriddatalen++] = 0;
2386 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2389 app = repodata_get_attrp(data, solvid);
2393 for (; *ap; ap += 2)
2394 if (data->keys[*ap].name == keyname)
2400 for (; *ap; ap += 2)
2402 if (data->keys[*ap].name == keyname)
2410 /* XXX: does not work correctly, needs fix in iterators! */
2412 repodata_delete(Repodata *data, Id solvid, Id keyname)
2416 key.type = REPOKEY_TYPE_DELETED;
2418 key.storage = KEY_STORAGE_INCORE;
2419 repodata_set(data, solvid, &key, 0);
2422 /* add all (uninternalized) attrs from src to dest */
2424 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2427 if (dest == src || data->attrs || !(keyp = data->attrs[src - data->start]))
2429 for (; *keyp; keyp += 2)
2430 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2433 /* add some (uninternalized) attrs from src to dest */
2435 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2438 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2440 for (; *keyp; keyp += 2)
2441 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2442 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2445 /* swap (uninternalized) attrs from src and dest */
2447 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2450 if (!data->attrs || dest == src)
2452 tmpattrs = data->attrs[dest - data->start];
2453 data->attrs[dest - data->start] = data->attrs[src - data->start];
2454 data->attrs[src - data->start] = tmpattrs;
2458 /**********************************************************************/
2460 /* TODO: unify with repo_write and repo_solv! */
2462 #define EXTDATA_BLOCK 1023
2470 data_addid(struct extdata *xd, Id sx)
2473 unsigned int x = (unsigned int)sx;
2475 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2476 dp = xd->buf + xd->len;
2481 *dp++ = (x >> 28) | 128;
2483 *dp++ = (x >> 21) | 128;
2484 *dp++ = (x >> 14) | 128;
2487 *dp++ = (x >> 7) | 128;
2489 xd->len = dp - xd->buf;
2493 data_addid64(struct extdata *xd, unsigned long long x)
2495 if (x >= 0x100000000)
2499 data_addid(xd, (Id)(x >> 35));
2500 xd->buf[xd->len - 1] |= 128;
2502 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2503 xd->buf[xd->len - 5] = (x >> 28) | 128;
2506 data_addid(xd, (Id)x);
2510 data_addideof(struct extdata *xd, Id x, int eof)
2513 abort(); /* XXX: not yet */
2515 x = (x & 63) | ((x & ~63) << 1);
2516 data_addid(xd, (eof ? x : x | 64));
2520 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2522 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2523 memcpy(xd->buf + xd->len, blob, len);
2527 /*********************************/
2529 /* internalalize some key into incore/vincore data */
2532 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2533 struct extdata *newvincore,
2535 Repokey *key, Id val)
2539 unsigned int oldvincorelen = 0;
2543 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2546 oldvincorelen = xd->len;
2550 case REPOKEY_TYPE_VOID:
2551 case REPOKEY_TYPE_CONSTANT:
2552 case REPOKEY_TYPE_CONSTANTID:
2554 case REPOKEY_TYPE_STR:
2555 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2557 case REPOKEY_TYPE_MD5:
2558 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2560 case REPOKEY_TYPE_SHA1:
2561 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2563 case REPOKEY_TYPE_SHA256:
2564 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2566 case REPOKEY_TYPE_NUM:
2567 if (val & 0x80000000)
2569 data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
2573 case REPOKEY_TYPE_ID:
2574 case REPOKEY_TYPE_DIR:
2575 data_addid(xd, val);
2577 case REPOKEY_TYPE_BINARY:
2580 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2582 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2585 case REPOKEY_TYPE_IDARRAY:
2586 for (ida = data->attriddata + val; *ida; ida++)
2587 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2589 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2590 for (ida = data->attriddata + val; *ida; ida += 3)
2592 data_addid(xd, ida[0]);
2593 data_addid(xd, ida[1]);
2594 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2597 case REPOKEY_TYPE_DIRSTRARRAY:
2598 for (ida = data->attriddata + val; *ida; ida += 2)
2600 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2601 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2604 case REPOKEY_TYPE_FIXARRAY:
2608 for (ida = data->attriddata + val; *ida; ida++)
2612 kp = data->xattrs[-*ida];
2620 schemaid = repodata_schema2id(data, schema, 1);
2621 else if (schemaid != repodata_schema2id(data, schema, 0))
2623 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2629 data_addid(xd, num);
2630 data_addid(xd, schemaid);
2631 for (ida = data->attriddata + val; *ida; ida++)
2633 Id *kp = data->xattrs[-*ida];
2637 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2641 case REPOKEY_TYPE_FLEXARRAY:
2644 for (ida = data->attriddata + val; *ida; ida++)
2646 data_addid(xd, num);
2647 for (ida = data->attriddata + val; *ida; ida++)
2649 Id *kp = data->xattrs[-*ida];
2652 data_addid(xd, 0); /* XXX */
2659 schemaid = repodata_schema2id(data, schema, 1);
2660 data_addid(xd, schemaid);
2661 kp = data->xattrs[-*ida];
2663 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2668 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2671 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2673 /* put offset/len in incore */
2674 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2675 oldvincorelen = xd->len - oldvincorelen;
2676 data_addid(newincore, oldvincorelen);
2681 repodata_internalize(Repodata *data)
2683 Repokey *key, solvkey;
2685 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2686 unsigned char *dp, *ndp;
2687 int newschema, oldcount;
2688 struct extdata newincore;
2689 struct extdata newvincore;
2692 if (!data->attrs && !data->xattrs)
2695 newvincore.buf = data->vincore;
2696 newvincore.len = data->vincorelen;
2698 /* find the solvables key, create if needed */
2699 memset(&solvkey, 0, sizeof(solvkey));
2700 solvkey.name = REPOSITORY_SOLVABLES;
2701 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2703 solvkey.storage = KEY_STORAGE_INCORE;
2704 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2706 schema = solv_malloc2(data->nkeys, sizeof(Id));
2707 seen = solv_malloc2(data->nkeys, sizeof(Id));
2709 /* Merge the data already existing (in data->schemata, ->incoredata and
2710 friends) with the new attributes in data->attrs[]. */
2711 nentry = data->end - data->start;
2712 memset(&newincore, 0, sizeof(newincore));
2713 data_addid(&newincore, 0); /* start data at offset 1 */
2715 data->mainschema = 0;
2716 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2718 /* join entry data */
2719 /* we start with the meta data, entry -1 */
2720 for (entry = -1; entry < nentry; entry++)
2722 memset(seen, 0, data->nkeys * sizeof(Id));
2724 dp = data->incoredata;
2727 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2728 dp = data_read_id(dp, &oldschema);
2731 fprintf(stderr, "oldschema %d\n", oldschema);
2732 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2733 fprintf(stderr, "schemadata %p\n", data->schemadata);
2735 /* seen: -1: old data 0: skipped >0: id + 1 */
2739 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2743 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2751 keyp = data->attrs ? data->attrs[entry] : 0;
2754 /* strip solvables key */
2756 for (sp = keyp = schema; *sp; sp++)
2757 if (*sp != solvkeyid)
2762 seen[solvkeyid] = 0;
2763 keyp = data->xattrs ? data->xattrs[1] : 0;
2766 for (; *keyp; keyp += 2)
2773 seen[*keyp] = keyp[1] + 1;
2775 if (entry < 0 && data->end != data->start)
2782 /* Ideally we'd like to sort the new schema here, to ensure
2783 schema equality independend of the ordering. We can't do that
2784 yet. For once see below (old ids need to come before new ids).
2785 An additional difficulty is that we also need to move
2786 the values with the keys. */
2787 schemaid = repodata_schema2id(data, schema, 1);
2789 schemaid = oldschema;
2792 /* Now create data blob. We walk through the (possibly new) schema
2793 and either copy over old data, or insert the new. */
2794 /* XXX Here we rely on the fact that the (new) schema has the form
2795 o1 o2 o3 o4 ... | n1 n2 n3 ...
2796 (oX being the old keyids (possibly overwritten), and nX being
2797 the new keyids). This rules out sorting the keyids in order
2798 to ensure a small schema count. */
2800 data->incoreoffset[entry] = newincore.len;
2801 data_addid(&newincore, schemaid);
2804 data->mainschema = schemaid;
2805 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2807 keypstart = data->schemadata + data->schemata[schemaid];
2808 for (keyp = keypstart; *keyp; keyp++)
2811 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2812 if (*keyp == solvkeyid)
2814 /* add flexarray entry count */
2815 data_addid(&newincore, data->end - data->start);
2818 key = data->keys + *keyp;
2820 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));
2825 /* Skip the data associated with this old key. */
2826 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2828 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2829 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2831 else if (key->storage == KEY_STORAGE_INCORE)
2832 ndp = data_skip_key(data, dp, key);
2835 if (seen[*keyp] == -1)
2837 /* If this key was an old one _and_ was not overwritten with
2838 a different value copy over the old value (we skipped it
2841 data_addblob(&newincore, dp, ndp - dp);
2844 else if (seen[*keyp])
2846 /* Otherwise we have a new value. Parse it into the internal
2848 repodata_serialize_key(data, &newincore, &newvincore,
2849 schema, key, seen[*keyp] - 1);
2853 if (entry >= 0 && data->attrs && data->attrs[entry])
2854 data->attrs[entry] = solv_free(data->attrs[entry]);
2856 /* free all xattrs */
2857 for (entry = 0; entry < data->nxattrs; entry++)
2858 if (data->xattrs[entry])
2859 solv_free(data->xattrs[entry]);
2860 data->xattrs = solv_free(data->xattrs);
2863 data->lasthandle = 0;
2865 data->lastdatalen = 0;
2868 repodata_free_schemahash(data);
2870 solv_free(data->incoredata);
2871 data->incoredata = newincore.buf;
2872 data->incoredatalen = newincore.len;
2873 data->incoredatafree = 0;
2875 solv_free(data->vincore);
2876 data->vincore = newvincore.buf;
2877 data->vincorelen = newvincore.len;
2879 data->attrs = solv_free(data->attrs);
2880 data->attrdata = solv_free(data->attrdata);
2881 data->attriddata = solv_free(data->attriddata);
2882 data->attrnum64data = solv_free(data->attrnum64data);
2883 data->attrdatalen = 0;
2884 data->attriddatalen = 0;
2885 data->attrnum64datalen = 0;
2889 repodata_disable_paging(Repodata *data)
2891 if (maybe_load_repodata(data, 0))
2892 repopagestore_disable_paging(&data->store);
2896 repodata_load_stub(Repodata *data)
2898 Repo *repo = data->repo;
2899 Pool *pool = repo->pool;
2901 struct _Pool_tmpspace oldtmpspace;
2903 if (!pool->loadcallback)
2905 data->state = REPODATA_ERROR;
2908 data->state = REPODATA_LOADING;
2910 /* save tmp space */
2911 oldtmpspace = pool->tmpspace;
2912 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2914 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2916 /* restore tmp space */
2917 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2918 solv_free(pool->tmpspace.buf[i]);
2919 pool->tmpspace = oldtmpspace;
2921 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2925 repodata_create_stubs(Repodata *data)
2927 Repo *repo = data->repo;
2928 Pool *pool = repo->pool;
2935 int datastart, dataend;
2937 repodataid = data - repo->repodata;
2938 datastart = data->start;
2939 dataend = data->end;
2940 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2941 while (dataiterator_step(&di))
2943 if (di.data - repo->repodata != repodataid)
2947 dataiterator_free(&di);
2950 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2951 for (i = 0; i < cnt; i++)
2953 sdata = repo_add_repodata(repo, 0);
2954 if (dataend > datastart)
2955 repodata_extend_block(sdata, datastart, dataend - datastart);
2956 stubdataids[i] = sdata - repo->repodata;
2957 sdata->state = REPODATA_STUB;
2958 sdata->loadcallback = repodata_load_stub;
2961 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2963 while (dataiterator_step(&di))
2965 if (di.data - repo->repodata != repodataid)
2967 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2969 dataiterator_entersub(&di);
2970 sdata = repo->repodata + stubdataids[i++];
2974 switch (di.key->type)
2976 case REPOKEY_TYPE_ID:
2977 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2979 case REPOKEY_TYPE_CONSTANTID:
2980 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2982 case REPOKEY_TYPE_STR:
2983 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
2985 case REPOKEY_TYPE_VOID:
2986 repodata_set_void(sdata, SOLVID_META, di.key->name);
2988 case REPOKEY_TYPE_NUM:
2989 repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num);
2991 case REPOKEY_TYPE_MD5:
2992 case REPOKEY_TYPE_SHA1:
2993 case REPOKEY_TYPE_SHA256:
2994 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
2996 case REPOKEY_TYPE_IDARRAY:
2997 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
2998 if (di.key->name == REPOSITORY_KEYS)
3005 xkeyname = di.kv.id;
3008 xkey.name = xkeyname;
3009 xkey.type = di.kv.id;
3010 xkey.storage = KEY_STORAGE_INCORE;
3012 repodata_key2id(sdata, &xkey, 1);
3019 dataiterator_free(&di);
3020 for (i = 0; i < cnt; i++)
3021 repodata_internalize(repo->repodata + stubdataids[i]);
3022 solv_free(stubdataids);
3026 repodata_memused(Repodata *data)
3028 return data->incoredatalen + data->vincorelen;
3032 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: