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 : 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_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2303 key.type = REPOKEY_TYPE_IDARRAY;
2305 key.storage = KEY_STORAGE_INCORE;
2306 repodata_set(data, solvid, &key, data->attriddatalen);
2307 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2308 for (i = 0; i < q->count; i++)
2309 data->attriddata[data->attriddatalen++] = q->elements[i];
2310 data->attriddata[data->attriddatalen++] = 0;
2314 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2318 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2320 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2321 data->attriddata[data->attriddatalen++] = dir;
2322 data->attriddata[data->attriddatalen++] = num;
2323 data->attriddata[data->attriddatalen++] = num2;
2324 data->attriddata[data->attriddatalen++] = 0;
2328 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2334 l = strlen(str) + 1;
2335 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2336 memcpy(data->attrdata + data->attrdatalen, str, l);
2337 stroff = data->attrdatalen;
2338 data->attrdatalen += l;
2341 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2343 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2344 data->attriddata[data->attriddatalen++] = dir;
2345 data->attriddata[data->attriddatalen++] = stroff;
2346 data->attriddata[data->attriddatalen++] = 0;
2350 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2353 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2355 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2356 data->attriddata[data->attriddatalen++] = id;
2357 data->attriddata[data->attriddatalen++] = 0;
2361 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2365 if (data->localpool)
2366 id = stringpool_str2id(&data->spool, str, 1);
2368 id = pool_str2id(data->repo->pool, str, 1);
2369 repodata_add_idarray(data, solvid, keyname, id);
2373 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2375 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2376 data->attriddata[data->attriddatalen++] = ghandle;
2377 data->attriddata[data->attriddatalen++] = 0;
2381 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2383 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2384 data->attriddata[data->attriddatalen++] = ghandle;
2385 data->attriddata[data->attriddatalen++] = 0;
2389 repodata_delete_uninternalized(Repodata *data, Id solvid, Id keyname)
2392 app = repodata_get_attrp(data, solvid);
2396 for (; *ap; ap += 2)
2397 if (data->keys[*ap].name == keyname)
2403 for (; *ap; ap += 2)
2405 if (data->keys[*ap].name == keyname)
2413 /* XXX: does not work correctly, needs fix in iterators! */
2415 repodata_delete(Repodata *data, Id solvid, Id keyname)
2419 key.type = REPOKEY_TYPE_DELETED;
2421 key.storage = KEY_STORAGE_INCORE;
2422 repodata_set(data, solvid, &key, 0);
2425 /* add all (uninternalized) attrs from src to dest */
2427 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2430 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2432 for (; *keyp; keyp += 2)
2433 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2436 /* add some (uninternalized) attrs from src to dest */
2438 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2441 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2443 for (; *keyp; keyp += 2)
2444 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2445 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2448 /* swap (uninternalized) attrs from src and dest */
2450 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2453 if (!data->attrs || dest == src)
2455 tmpattrs = data->attrs[dest - data->start];
2456 data->attrs[dest - data->start] = data->attrs[src - data->start];
2457 data->attrs[src - data->start] = tmpattrs;
2461 /**********************************************************************/
2463 /* TODO: unify with repo_write and repo_solv! */
2465 #define EXTDATA_BLOCK 1023
2473 data_addid(struct extdata *xd, Id sx)
2475 unsigned int x = (unsigned int)sx;
2478 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2479 dp = xd->buf + xd->len;
2484 *dp++ = (x >> 28) | 128;
2486 *dp++ = (x >> 21) | 128;
2487 *dp++ = (x >> 14) | 128;
2490 *dp++ = (x >> 7) | 128;
2492 xd->len = dp - xd->buf;
2496 data_addid64(struct extdata *xd, unsigned long long x)
2498 if (x >= 0x100000000)
2502 data_addid(xd, (Id)(x >> 35));
2503 xd->buf[xd->len - 1] |= 128;
2505 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2506 xd->buf[xd->len - 5] = (x >> 28) | 128;
2509 data_addid(xd, (Id)x);
2513 data_addideof(struct extdata *xd, Id sx, int eof)
2515 unsigned int x = (unsigned int)sx;
2518 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2519 dp = xd->buf + xd->len;
2524 *dp++ = (x >> 27) | 128;
2526 *dp++ = (x >> 20) | 128;
2527 *dp++ = (x >> 13) | 128;
2530 *dp++ = (x >> 6) | 128;
2531 *dp++ = eof ? (x & 63) : (x & 63) | 64;
2532 xd->len = dp - xd->buf;
2536 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2538 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2539 memcpy(xd->buf + xd->len, blob, len);
2543 /*********************************/
2545 /* internalalize some key into incore/vincore data */
2548 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2549 struct extdata *newvincore,
2551 Repokey *key, Id val)
2555 unsigned int oldvincorelen = 0;
2559 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2562 oldvincorelen = xd->len;
2566 case REPOKEY_TYPE_VOID:
2567 case REPOKEY_TYPE_CONSTANT:
2568 case REPOKEY_TYPE_CONSTANTID:
2570 case REPOKEY_TYPE_STR:
2571 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2573 case REPOKEY_TYPE_MD5:
2574 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2576 case REPOKEY_TYPE_SHA1:
2577 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2579 case REPOKEY_TYPE_SHA256:
2580 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2582 case REPOKEY_TYPE_NUM:
2583 if (val & 0x80000000)
2585 data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
2589 case REPOKEY_TYPE_ID:
2590 case REPOKEY_TYPE_DIR:
2591 data_addid(xd, val);
2593 case REPOKEY_TYPE_BINARY:
2596 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2597 dp += (unsigned int)len;
2598 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2601 case REPOKEY_TYPE_IDARRAY:
2602 for (ida = data->attriddata + val; *ida; ida++)
2603 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2605 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2606 for (ida = data->attriddata + val; *ida; ida += 3)
2608 data_addid(xd, ida[0]);
2609 data_addid(xd, ida[1]);
2610 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2613 case REPOKEY_TYPE_DIRSTRARRAY:
2614 for (ida = data->attriddata + val; *ida; ida += 2)
2616 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2617 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2620 case REPOKEY_TYPE_FIXARRAY:
2624 for (ida = data->attriddata + val; *ida; ida++)
2628 kp = data->xattrs[-*ida];
2636 schemaid = repodata_schema2id(data, schema, 1);
2637 else if (schemaid != repodata_schema2id(data, schema, 0))
2639 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2645 data_addid(xd, num);
2646 data_addid(xd, schemaid);
2647 for (ida = data->attriddata + val; *ida; ida++)
2649 Id *kp = data->xattrs[-*ida];
2653 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2657 case REPOKEY_TYPE_FLEXARRAY:
2660 for (ida = data->attriddata + val; *ida; ida++)
2662 data_addid(xd, num);
2663 for (ida = data->attriddata + val; *ida; ida++)
2665 Id *kp = data->xattrs[-*ida];
2668 data_addid(xd, 0); /* XXX */
2675 schemaid = repodata_schema2id(data, schema, 1);
2676 data_addid(xd, schemaid);
2677 kp = data->xattrs[-*ida];
2679 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2684 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2687 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2689 /* put offset/len in incore */
2690 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2691 oldvincorelen = xd->len - oldvincorelen;
2692 data_addid(newincore, oldvincorelen);
2697 repodata_internalize(Repodata *data)
2699 Repokey *key, solvkey;
2701 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2702 unsigned char *dp, *ndp;
2703 int newschema, oldcount;
2704 struct extdata newincore;
2705 struct extdata newvincore;
2708 if (!data->attrs && !data->xattrs)
2711 newvincore.buf = data->vincore;
2712 newvincore.len = data->vincorelen;
2714 /* find the solvables key, create if needed */
2715 memset(&solvkey, 0, sizeof(solvkey));
2716 solvkey.name = REPOSITORY_SOLVABLES;
2717 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2719 solvkey.storage = KEY_STORAGE_INCORE;
2720 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2722 schema = solv_malloc2(data->nkeys, sizeof(Id));
2723 seen = solv_malloc2(data->nkeys, sizeof(Id));
2725 /* Merge the data already existing (in data->schemata, ->incoredata and
2726 friends) with the new attributes in data->attrs[]. */
2727 nentry = data->end - data->start;
2728 memset(&newincore, 0, sizeof(newincore));
2729 data_addid(&newincore, 0); /* start data at offset 1 */
2731 data->mainschema = 0;
2732 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2734 /* join entry data */
2735 /* we start with the meta data, entry -1 */
2736 for (entry = -1; entry < nentry; entry++)
2738 memset(seen, 0, data->nkeys * sizeof(Id));
2740 dp = data->incoredata;
2743 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2744 dp = data_read_id(dp, &oldschema);
2747 fprintf(stderr, "oldschema %d\n", oldschema);
2748 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2749 fprintf(stderr, "schemadata %p\n", data->schemadata);
2751 /* seen: -1: old data 0: skipped >0: id + 1 */
2755 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2759 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2767 keyp = data->attrs ? data->attrs[entry] : 0;
2770 /* strip solvables key */
2772 for (sp = keyp = schema; *sp; sp++)
2773 if (*sp != solvkeyid)
2778 seen[solvkeyid] = 0;
2779 keyp = data->xattrs ? data->xattrs[1] : 0;
2782 for (; *keyp; keyp += 2)
2789 seen[*keyp] = keyp[1] + 1;
2791 if (entry < 0 && data->end != data->start)
2798 /* Ideally we'd like to sort the new schema here, to ensure
2799 schema equality independend of the ordering. We can't do that
2800 yet. For once see below (old ids need to come before new ids).
2801 An additional difficulty is that we also need to move
2802 the values with the keys. */
2803 schemaid = repodata_schema2id(data, schema, 1);
2805 schemaid = oldschema;
2808 /* Now create data blob. We walk through the (possibly new) schema
2809 and either copy over old data, or insert the new. */
2810 /* XXX Here we rely on the fact that the (new) schema has the form
2811 o1 o2 o3 o4 ... | n1 n2 n3 ...
2812 (oX being the old keyids (possibly overwritten), and nX being
2813 the new keyids). This rules out sorting the keyids in order
2814 to ensure a small schema count. */
2816 data->incoreoffset[entry] = newincore.len;
2817 data_addid(&newincore, schemaid);
2820 data->mainschema = schemaid;
2821 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2823 keypstart = data->schemadata + data->schemata[schemaid];
2824 for (keyp = keypstart; *keyp; keyp++)
2827 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2828 if (*keyp == solvkeyid)
2830 /* add flexarray entry count */
2831 data_addid(&newincore, data->end - data->start);
2834 key = data->keys + *keyp;
2836 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));
2841 /* Skip the data associated with this old key. */
2842 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2844 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2845 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2847 else if (key->storage == KEY_STORAGE_INCORE)
2848 ndp = data_skip_key(data, dp, key);
2851 if (seen[*keyp] == -1)
2853 /* If this key was an old one _and_ was not overwritten with
2854 a different value copy over the old value (we skipped it
2857 data_addblob(&newincore, dp, ndp - dp);
2860 else if (seen[*keyp])
2862 /* Otherwise we have a new value. Parse it into the internal
2864 repodata_serialize_key(data, &newincore, &newvincore,
2865 schema, key, seen[*keyp] - 1);
2869 if (entry >= 0 && data->attrs && data->attrs[entry])
2870 data->attrs[entry] = solv_free(data->attrs[entry]);
2872 /* free all xattrs */
2873 for (entry = 0; entry < data->nxattrs; entry++)
2874 if (data->xattrs[entry])
2875 solv_free(data->xattrs[entry]);
2876 data->xattrs = solv_free(data->xattrs);
2879 data->lasthandle = 0;
2881 data->lastdatalen = 0;
2884 repodata_free_schemahash(data);
2886 solv_free(data->incoredata);
2887 data->incoredata = newincore.buf;
2888 data->incoredatalen = newincore.len;
2889 data->incoredatafree = 0;
2891 solv_free(data->vincore);
2892 data->vincore = newvincore.buf;
2893 data->vincorelen = newvincore.len;
2895 data->attrs = solv_free(data->attrs);
2896 data->attrdata = solv_free(data->attrdata);
2897 data->attriddata = solv_free(data->attriddata);
2898 data->attrnum64data = solv_free(data->attrnum64data);
2899 data->attrdatalen = 0;
2900 data->attriddatalen = 0;
2901 data->attrnum64datalen = 0;
2905 repodata_disable_paging(Repodata *data)
2907 if (maybe_load_repodata(data, 0))
2908 repopagestore_disable_paging(&data->store);
2912 repodata_load_stub(Repodata *data)
2914 Repo *repo = data->repo;
2915 Pool *pool = repo->pool;
2917 struct _Pool_tmpspace oldtmpspace;
2919 if (!pool->loadcallback)
2921 data->state = REPODATA_ERROR;
2924 data->state = REPODATA_LOADING;
2926 /* save tmp space */
2927 oldtmpspace = pool->tmpspace;
2928 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2930 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2932 /* restore tmp space */
2933 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2934 solv_free(pool->tmpspace.buf[i]);
2935 pool->tmpspace = oldtmpspace;
2937 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
2941 repodata_create_stubs(Repodata *data)
2943 Repo *repo = data->repo;
2944 Pool *pool = repo->pool;
2951 int datastart, dataend;
2953 repodataid = data - repo->repodata;
2954 datastart = data->start;
2955 dataend = data->end;
2956 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2957 while (dataiterator_step(&di))
2959 if (di.data - repo->repodata != repodataid)
2963 dataiterator_free(&di);
2966 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
2967 for (i = 0; i < cnt; i++)
2969 sdata = repo_add_repodata(repo, 0);
2970 if (dataend > datastart)
2971 repodata_extend_block(sdata, datastart, dataend - datastart);
2972 stubdataids[i] = sdata - repo->repodata;
2973 sdata->state = REPODATA_STUB;
2974 sdata->loadcallback = repodata_load_stub;
2977 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
2979 while (dataiterator_step(&di))
2981 if (di.data - repo->repodata != repodataid)
2983 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
2985 dataiterator_entersub(&di);
2986 sdata = repo->repodata + stubdataids[i++];
2990 switch (di.key->type)
2992 case REPOKEY_TYPE_ID:
2993 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
2995 case REPOKEY_TYPE_CONSTANTID:
2996 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
2998 case REPOKEY_TYPE_STR:
2999 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
3001 case REPOKEY_TYPE_VOID:
3002 repodata_set_void(sdata, SOLVID_META, di.key->name);
3004 case REPOKEY_TYPE_NUM:
3005 repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv));
3007 case REPOKEY_TYPE_MD5:
3008 case REPOKEY_TYPE_SHA1:
3009 case REPOKEY_TYPE_SHA256:
3010 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
3012 case REPOKEY_TYPE_IDARRAY:
3013 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
3014 if (di.key->name == REPOSITORY_KEYS)
3021 xkeyname = di.kv.id;
3024 xkey.name = xkeyname;
3025 xkey.type = di.kv.id;
3026 xkey.storage = KEY_STORAGE_INCORE;
3028 repodata_key2id(sdata, &xkey, 1);
3035 dataiterator_free(&di);
3036 for (i = 0; i < cnt; i++)
3037 repodata_internalize(repo->repodata + stubdataids[i]);
3038 solv_free(stubdataids);
3042 repodata_memused(Repodata *data)
3044 return data->incoredatalen + data->vincorelen;
3048 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: