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)
685 unsigned int high, low;
688 dp = find_key_data(data, solvid, keyname, &key);
693 case REPOKEY_TYPE_NUM:
694 data_read_num64(dp, &low, &high);
695 *value = (unsigned long long)high << 32 | low;
697 case REPOKEY_TYPE_U32:
698 data_read_u32(dp, &low);
701 case REPOKEY_TYPE_CONSTANT:
710 repodata_lookup_void(Repodata *data, Id solvid, Id keyname)
716 if (!maybe_load_repodata(data, keyname))
718 dp = solvid2data(data, solvid, &schema);
721 /* can't use find_key_data as we need to test the type */
722 for (keyp = data->schemadata + data->schemata[schema]; *keyp; keyp++)
723 if (data->keys[*keyp].name == keyname && data->keys[*keyp].type == REPOKEY_TYPE_VOID)
728 const unsigned char *
729 repodata_lookup_bin_checksum(Repodata *data, Id solvid, Id keyname, Id *typep)
734 dp = find_key_data(data, solvid, keyname, &key);
737 if (!(key->type == REPOKEY_TYPE_MD5 || key->type == REPOKEY_TYPE_SHA1 || key->type == REPOKEY_TYPE_SHA256))
744 repodata_lookup_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
752 dp = find_key_data(data, solvid, keyname, &key);
755 if (key->type != REPOKEY_TYPE_IDARRAY && key->type != REPOKEY_TYPE_REL_IDARRAY)
759 dp = data_read_ideof(dp, &id, &eof);
768 repodata_globalize_id(Repodata *data, Id id, int create)
770 if (!id || !data || !data->localpool)
772 return pool_str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
776 repodata_localize_id(Repodata *data, Id id, int create)
778 if (!id || !data || !data->localpool)
780 return stringpool_str2id(&data->spool, pool_id2str(data->repo->pool, id), create);
784 repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id voidid)
789 ap = data->attrs[solvid - data->start];
794 if (data->keys[*ap].name != keyname)
796 if (data->keys[*ap].type == REPOKEY_TYPE_VOID)
798 if (data->keys[*ap].type == REPOKEY_TYPE_ID)
806 /************************************************************************
812 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
816 case REPOKEY_TYPE_ID:
817 case REPOKEY_TYPE_CONSTANTID:
818 case REPOKEY_TYPE_IDARRAY:
819 if (data && data->localpool)
820 kv->str = stringpool_id2str(&data->spool, kv->id);
822 kv->str = pool_id2str(pool, kv->id);
823 if ((flags & SEARCH_SKIP_KIND) != 0 && key->storage == KEY_STORAGE_SOLVABLE)
826 for (s = kv->str; *s >= 'a' && *s <= 'z'; s++)
828 if (*s == ':' && s > kv->str)
832 case REPOKEY_TYPE_STR:
834 case REPOKEY_TYPE_DIRSTRARRAY:
835 if (!(flags & SEARCH_FILES))
836 return 1; /* match just the basename */
837 /* Put the full filename into kv->str. */
838 kv->str = repodata_dir2str(data, kv->id, kv->str);
839 /* And to compensate for that put the "empty" directory into
840 kv->id, so that later calls to repodata_dir2str on this data
841 come up with the same filename again. */
844 case REPOKEY_TYPE_MD5:
845 case REPOKEY_TYPE_SHA1:
846 case REPOKEY_TYPE_SHA256:
847 if (!(flags & SEARCH_CHECKSUMS))
848 return 0; /* skip em */
849 kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
857 struct subschema_data {
863 /* search a specific repodata */
865 repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
869 Id keyid, *kp, *keyp;
870 unsigned char *dp, *ddp;
876 if (!maybe_load_repodata(data, keyname))
878 if (solvid == SOLVID_SUBSCHEMA)
880 struct subschema_data *subd = cbdata;
881 cbdata = subd->cbdata;
883 schema = subd->parent->id;
884 dp = (unsigned char *)subd->parent->str;
885 kv.parent = subd->parent;
890 dp = solvid2data(data, solvid, &schema);
893 s = data->repo->pool->solvables + solvid;
896 keyp = data->schemadata + data->schemata[schema];
899 /* search for a specific key */
900 for (kp = keyp; *kp; kp++)
901 if (data->keys[*kp].name == keyname)
905 dp = forward_to_key(data, *kp, keyp, dp);
911 while ((keyid = *keyp++) != 0)
914 key = data->keys + keyid;
915 ddp = get_data(data, key, &dp, *keyp ? 1 : 0);
917 if (key->type == REPOKEY_TYPE_DELETED)
919 if (key->type == REPOKEY_TYPE_FLEXARRAY || key->type == REPOKEY_TYPE_FIXARRAY)
921 struct subschema_data subd;
925 subd.cbdata = cbdata;
928 ddp = data_read_id(ddp, &nentries);
932 while (ddp && nentries > 0)
936 if (key->type == REPOKEY_TYPE_FLEXARRAY || !kv.entry)
937 ddp = data_read_id(ddp, &schema);
939 kv.str = (char *)ddp;
940 stop = callback(cbdata, s, data, key, &kv);
941 if (stop > SEARCH_NEXT_KEY)
943 if (stop && stop != SEARCH_ENTERSUB)
945 if ((flags & SEARCH_SUB) != 0 || stop == SEARCH_ENTERSUB)
946 repodata_search(data, SOLVID_SUBSCHEMA, 0, flags, callback, &subd);
947 ddp = data_skip_schema(data, ddp, schema);
950 if (!nentries && (flags & SEARCH_ARRAYSENTINEL) != 0)
954 kv.str = (char *)ddp;
955 stop = callback(cbdata, s, data, key, &kv);
956 if (stop > SEARCH_NEXT_KEY)
966 ddp = data_fetch(ddp, &kv, key);
969 stop = callback(cbdata, s, data, key, &kv);
972 while (!kv.eof && !stop);
973 if (onekey || stop > SEARCH_NEXT_KEY)
979 repodata_setpos_kv(Repodata *data, KeyValue *kv)
981 Pool *pool = data->repo->pool;
983 pool_clear_pos(pool);
986 pool->pos.repo = data->repo;
987 pool->pos.repodataid = data - data->repo->repodata;
988 pool->pos.dp = (unsigned char *)kv->str - data->incoredata;
989 pool->pos.schema = kv->id;
993 /************************************************************************
994 * data iterator functions
998 solvabledata_fetch(Solvable *s, KeyValue *kv, Id keyname)
1012 case SOLVABLE_VENDOR:
1015 case SOLVABLE_PROVIDES:
1017 return s->provides ? s->repo->idarraydata + s->provides : 0;
1018 case SOLVABLE_OBSOLETES:
1020 return s->obsoletes ? s->repo->idarraydata + s->obsoletes : 0;
1021 case SOLVABLE_CONFLICTS:
1023 return s->conflicts ? s->repo->idarraydata + s->conflicts : 0;
1024 case SOLVABLE_REQUIRES:
1026 return s->requires ? s->repo->idarraydata + s->requires : 0;
1027 case SOLVABLE_RECOMMENDS:
1029 return s->recommends ? s->repo->idarraydata + s->recommends : 0;
1030 case SOLVABLE_SUPPLEMENTS:
1032 return s->supplements ? s->repo->idarraydata + s->supplements : 0;
1033 case SOLVABLE_SUGGESTS:
1035 return s->suggests ? s->repo->idarraydata + s->suggests : 0;
1036 case SOLVABLE_ENHANCES:
1038 return s->enhances ? s->repo->idarraydata + s->enhances : 0;
1041 return s->repo->rpmdbid ? s->repo->rpmdbid + (s - s->repo->pool->solvables - s->repo->start) : 0;
1048 datamatcher_init(Datamatcher *ma, const char *match, int flags)
1054 if ((flags & SEARCH_STRINGMASK) == SEARCH_REGEX)
1056 ma->matchdata = solv_calloc(1, sizeof(regex_t));
1057 ma->error = regcomp((regex_t *)ma->matchdata, match, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0));
1060 solv_free(ma->matchdata);
1061 ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
1068 datamatcher_free(Datamatcher *ma)
1070 if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
1072 regfree(ma->matchdata);
1073 ma->matchdata = solv_free(ma->matchdata);
1078 datamatcher_match(Datamatcher *ma, const char *str)
1081 switch ((ma->flags & SEARCH_STRINGMASK))
1083 case SEARCH_SUBSTRING:
1084 if (ma->flags & SEARCH_NOCASE)
1086 if (!strcasestr(str, ma->match))
1091 if (!strstr(str, ma->match))
1096 if (ma->flags & SEARCH_NOCASE)
1098 if (strcasecmp(ma->match, str))
1103 if (strcmp(ma->match, str))
1107 case SEARCH_STRINGSTART:
1108 if (ma->flags & SEARCH_NOCASE)
1110 if (strncasecmp(ma->match, str, strlen(ma->match)))
1115 if (strncmp(ma->match, str, strlen(ma->match)))
1119 case SEARCH_STRINGEND:
1120 l = strlen(str) - strlen(ma->match);
1123 if (ma->flags & SEARCH_NOCASE)
1125 if (strcasecmp(ma->match, str + l))
1130 if (strcmp(ma->match, str + l))
1135 if (fnmatch(ma->match, str, (ma->flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
1139 if (regexec((const regex_t *)ma->matchdata, str, 0, NULL, 0))
1149 repodata_filelistfilter_matches(Repodata *data, const char *str)
1151 /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */
1152 /* for now hardcoded */
1153 if (strstr(str, "bin/"))
1155 if (!strncmp(str, "/etc/", 5))
1157 if (!strcmp(str, "/usr/lib/sendmail"))
1179 di_nextarrayelement,
1185 di_entersolvablekey,
1189 /* see dataiterator.h for documentation */
1191 dataiterator_init(Dataiterator *di, Pool *pool, Repo *repo, Id p, Id keyname, const char *match, int flags)
1193 memset(di, 0, sizeof(*di));
1195 di->flags = flags & ~SEARCH_THISSOLVID;
1196 if (!pool || (repo && repo->pool != pool))
1204 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1210 di->keyname = keyname;
1211 di->keynames[0] = keyname;
1212 dataiterator_set_search(di, repo, p);
1217 dataiterator_init_clone(Dataiterator *di, Dataiterator *from)
1220 memset(&di->matcher, 0, sizeof(di->matcher));
1221 if (from->matcher.match)
1222 datamatcher_init(&di->matcher, from->matcher.match, from->matcher.flags);
1227 for (i = 1; i < di->nparents; i++)
1228 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1229 di->kv.parent = &di->parents[di->nparents - 1].kv;
1234 dataiterator_set_match(Dataiterator *di, const char *match, int flags)
1236 di->flags = (flags & ~SEARCH_THISSOLVID) | (di->flags & SEARCH_THISSOLVID);
1237 datamatcher_free(&di->matcher);
1238 memset(&di->matcher, 0, sizeof(di->matcher));
1242 if ((error = datamatcher_init(&di->matcher, match, flags)) != 0)
1252 dataiterator_set_search(Dataiterator *di, Repo *repo, Id p)
1256 di->flags &= ~SEARCH_THISSOLVID;
1260 if (!di->pool->urepos)
1268 di->repo = di->pool->repos[di->repoid];
1270 di->state = di_enterrepo;
1272 dataiterator_jump_to_solvid(di, p);
1276 dataiterator_set_keyname(Dataiterator *di, Id keyname)
1279 di->keyname = keyname;
1280 di->keynames[0] = keyname;
1284 dataiterator_prepend_keyname(Dataiterator *di, Id keyname)
1288 if (di->nkeynames >= sizeof(di->keynames)/sizeof(*di->keynames) - 2)
1290 di->state = di_bye; /* sorry */
1293 for (i = di->nkeynames + 1; i > 0; i--)
1294 di->keynames[i] = di->keynames[i - 1];
1295 di->keynames[0] = di->keyname = keyname;
1300 dataiterator_free(Dataiterator *di)
1302 if (di->matcher.match)
1303 datamatcher_free(&di->matcher);
1306 static inline unsigned char *
1307 dataiterator_find_keyname(Dataiterator *di, Id keyname)
1309 Id *keyp = di->keyp;
1310 Repokey *keys = di->data->keys;
1313 for (keyp = di->keyp; *keyp; keyp++)
1314 if (keys[*keyp].name == keyname)
1318 dp = forward_to_key(di->data, *keyp, di->keyp, di->dp);
1326 dataiterator_filelistcheck(Dataiterator *di)
1329 int needcomplete = 0;
1330 Repodata *data = di->data;
1332 if ((di->matcher.flags & SEARCH_COMPLETE_FILELIST) != 0)
1333 if (!di->matcher.match
1334 || ((di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_STRING
1335 && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) != SEARCH_GLOB)
1336 || !repodata_filelistfilter_matches(di->data, di->matcher.match))
1338 if (data->state != REPODATA_AVAILABLE)
1339 return needcomplete ? 1 : 0;
1340 for (j = 1; j < data->nkeys; j++)
1341 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
1343 return j == data->nkeys && !needcomplete ? 0 : 1;
1347 dataiterator_step(Dataiterator *di)
1355 case di_enterrepo: di_enterrepo:
1356 if (!di->repo || (di->repo->disabled && !(di->flags & SEARCH_DISABLED_REPOS)))
1358 if (!(di->flags & SEARCH_THISSOLVID))
1360 di->solvid = di->repo->start - 1; /* reset solvid iterator */
1361 goto di_nextsolvable;
1365 case di_entersolvable: di_entersolvable:
1368 di->repodataid = 1; /* reset repodata iterator */
1369 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)
1371 extern Repokey repo_solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1];
1373 di->key = repo_solvablekeys + (di->keyname ? di->keyname - SOLVABLE_NAME : 0);
1375 goto di_entersolvablekey;
1380 case di_enterrepodata: di_enterrepodata:
1383 if (di->repodataid >= di->repo->nrepodata)
1384 goto di_nextsolvable;
1385 di->data = di->repo->repodata + di->repodataid;
1387 if (di->repodataid && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di))
1388 goto di_nextrepodata;
1389 if (!maybe_load_repodata(di->data, di->keyname))
1390 goto di_nextrepodata;
1391 di->dp = solvid2data(di->data, di->solvid, &schema);
1393 goto di_nextrepodata;
1394 if (di->solvid == SOLVID_POS)
1395 di->solvid = di->pool->pos.solvid;
1396 /* reset key iterator */
1397 di->keyp = di->data->schemadata + di->data->schemata[schema];
1400 case di_enterschema: di_enterschema:
1402 di->dp = dataiterator_find_keyname(di, di->keyname);
1403 if (!di->dp || !*di->keyp)
1407 goto di_nextrepodata;
1411 case di_enterkey: di_enterkey:
1413 di->key = di->data->keys + *di->keyp;
1414 di->ddp = get_data(di->data, di->key, &di->dp, di->keyp[1] && (!di->keyname || (di->flags & SEARCH_SUB) != 0) ? 1 : 0);
1417 if (di->key->type == REPOKEY_TYPE_DELETED)
1419 if (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)
1421 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1427 di->ddp = data_fetch(di->ddp, &di->kv, di->key);
1429 di->state = di_nextkey;
1431 di->state = di_nextattr;
1434 case di_nextkey: di_nextkey:
1435 if (!di->keyname && *++di->keyp)
1441 case di_nextrepodata: di_nextrepodata:
1442 if (di->repodataid && ++di->repodataid < di->repo->nrepodata)
1443 goto di_enterrepodata;
1446 case di_nextsolvable: di_nextsolvable:
1447 if (!(di->flags & SEARCH_THISSOLVID))
1450 di->solvid = di->repo->start;
1453 for (; di->solvid < di->repo->end; di->solvid++)
1455 if (di->pool->solvables[di->solvid].repo == di->repo)
1456 goto di_entersolvable;
1461 case di_nextrepo: di_nextrepo:
1466 if (di->repoid < di->pool->nrepos)
1468 di->repo = di->pool->repos[di->repoid];
1474 case di_bye: di_bye:
1478 case di_enterarray: di_enterarray:
1479 if (di->key->name == REPOSITORY_SOLVABLES)
1481 di->ddp = data_read_id(di->ddp, (Id *)&di->kv.num);
1486 case di_nextarrayelement: di_nextarrayelement:
1489 di->ddp = data_skip_schema(di->data, di->ddp, di->kv.id);
1490 if (di->kv.entry == di->kv.num)
1492 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1494 if (!(di->flags & SEARCH_ARRAYSENTINEL))
1496 di->kv.str = (char *)di->ddp;
1498 di->state = di_nextkey;
1501 if (di->kv.entry == di->kv.num - 1)
1503 if (di->key->type == REPOKEY_TYPE_FLEXARRAY || !di->kv.entry)
1504 di->ddp = data_read_id(di->ddp, &di->kv.id);
1505 di->kv.str = (char *)di->ddp;
1506 if (di->nkeynames && di->nparents - di->rootlevel < di->nkeynames)
1508 if ((di->flags & SEARCH_SUB) != 0)
1509 di->state = di_entersub;
1511 di->state = di_nextarrayelement;
1514 case di_entersub: di_entersub:
1515 if (di->nparents == sizeof(di->parents)/sizeof(*di->parents) - 1)
1516 goto di_nextarrayelement; /* sorry, full */
1517 di->parents[di->nparents].kv = di->kv;
1518 di->parents[di->nparents].dp = di->dp;
1519 di->parents[di->nparents].keyp = di->keyp;
1520 di->dp = (unsigned char *)di->kv.str;
1521 di->keyp = di->data->schemadata + di->data->schemata[di->kv.id];
1522 memset(&di->kv, 0, sizeof(di->kv));
1523 di->kv.parent = &di->parents[di->nparents].kv;
1525 di->keyname = di->keynames[di->nparents - di->rootlevel];
1526 goto di_enterschema;
1528 case di_leavesub: di_leavesub:
1529 if (di->nparents - 1 < di->rootlevel)
1532 di->dp = di->parents[di->nparents].dp;
1533 di->kv = di->parents[di->nparents].kv;
1534 di->keyp = di->parents[di->nparents].keyp;
1535 di->key = di->data->keys + *di->keyp;
1536 di->ddp = (unsigned char *)di->kv.str;
1537 di->keyname = di->keynames[di->nparents - di->rootlevel];
1538 goto di_nextarrayelement;
1540 /* special solvable attr handling follows */
1542 case di_nextsolvablekey: di_nextsolvablekey:
1543 if (di->keyname || di->key->name == RPM_RPMDBID)
1544 goto di_enterrepodata;
1548 case di_entersolvablekey: di_entersolvablekey:
1549 di->idp = solvabledata_fetch(di->pool->solvables + di->solvid, &di->kv, di->key->name);
1550 if (!di->idp || !*di->idp)
1551 goto di_nextsolvablekey;
1555 di->kv.id = *di->idp;
1556 di->kv.num = *di->idp; /* for rpmdbid */
1557 di->kv.num2 = 0; /* for rpmdbid */
1559 di->state = di_nextsolvablekey;
1565 case di_nextsolvableattr:
1566 di->state = di_nextsolvableattr;
1567 di->kv.id = *di->idp++;
1572 di->state = di_nextsolvablekey;
1578 if (di->matcher.match)
1580 /* simple pre-check so that we don't need to stringify */
1581 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))
1583 int l = strlen(di->matcher.match) - strlen(di->kv.str);
1584 if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
1587 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1589 if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
1593 if (!datamatcher_match(&di->matcher, di->kv.str))
1598 if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->flags & SEARCH_FILES) != 0)
1599 repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags);
1601 /* found something! */
1607 dataiterator_entersub(Dataiterator *di)
1609 if (di->state == di_nextarrayelement)
1610 di->state = di_entersub;
1614 dataiterator_setpos(Dataiterator *di)
1616 if (di->kv.eof == 2)
1618 pool_clear_pos(di->pool);
1621 di->pool->pos.solvid = di->solvid;
1622 di->pool->pos.repo = di->repo;
1623 di->pool->pos.repodataid = di->data - di->repo->repodata;
1624 di->pool->pos.schema = di->kv.id;
1625 di->pool->pos.dp = (unsigned char *)di->kv.str - di->data->incoredata;
1629 dataiterator_setpos_parent(Dataiterator *di)
1631 if (!di->kv.parent || di->kv.parent->eof == 2)
1633 pool_clear_pos(di->pool);
1636 di->pool->pos.solvid = di->solvid;
1637 di->pool->pos.repo = di->repo;
1638 di->pool->pos.repodataid = di->data - di->repo->repodata;
1639 di->pool->pos.schema = di->kv.parent->id;
1640 di->pool->pos.dp = (unsigned char *)di->kv.parent->str - di->data->incoredata;
1643 /* clones just the position, not the search keys/matcher */
1645 dataiterator_clonepos(Dataiterator *di, Dataiterator *from)
1647 di->state = from->state;
1648 di->flags &= ~SEARCH_THISSOLVID;
1649 di->flags |= (from->flags & SEARCH_THISSOLVID);
1650 di->repo = from->repo;
1651 di->data = from->data;
1653 di->ddp = from->ddp;
1654 di->idp = from->idp;
1655 di->keyp = from->keyp;
1656 di->key = from->key;
1658 di->repodataid = from->repodataid;
1659 di->solvid = from->solvid;
1660 di->repoid = from->repoid;
1661 di->rootlevel = from->rootlevel;
1662 memcpy(di->parents, from->parents, sizeof(from->parents));
1663 di->nparents = from->nparents;
1667 for (i = 1; i < di->nparents; i++)
1668 di->parents[i].kv.parent = &di->parents[i - 1].kv;
1669 di->kv.parent = &di->parents[di->nparents - 1].kv;
1674 dataiterator_seek(Dataiterator *di, int whence)
1676 if ((whence & DI_SEEK_STAY) != 0)
1677 di->rootlevel = di->nparents;
1678 switch (whence & ~DI_SEEK_STAY)
1681 if (di->state != di_nextarrayelement)
1683 if ((whence & DI_SEEK_STAY) != 0)
1684 di->rootlevel = di->nparents + 1; /* XXX: dangerous! */
1685 di->state = di_entersub;
1687 case DI_SEEK_PARENT:
1694 if (di->rootlevel > di->nparents)
1695 di->rootlevel = di->nparents;
1696 di->dp = di->parents[di->nparents].dp;
1697 di->kv = di->parents[di->nparents].kv;
1698 di->keyp = di->parents[di->nparents].keyp;
1699 di->key = di->data->keys + *di->keyp;
1700 di->ddp = (unsigned char *)di->kv.str;
1701 di->keyname = di->keynames[di->nparents - di->rootlevel];
1702 di->state = di_nextarrayelement;
1704 case DI_SEEK_REWIND:
1710 di->dp = (unsigned char *)di->kv.parent->str;
1711 di->keyp = di->data->schemadata + di->data->schemata[di->kv.parent->id];
1712 di->state = di_enterschema;
1720 dataiterator_skip_attribute(Dataiterator *di)
1722 if (di->state == di_nextsolvableattr)
1723 di->state = di_nextsolvablekey;
1725 di->state = di_nextkey;
1729 dataiterator_skip_solvable(Dataiterator *di)
1734 di->keyname = di->keynames[0];
1735 di->state = di_nextsolvable;
1739 dataiterator_skip_repo(Dataiterator *di)
1744 di->keyname = di->keynames[0];
1745 di->state = di_nextrepo;
1749 dataiterator_jump_to_solvid(Dataiterator *di, Id solvid)
1754 di->keyname = di->keynames[0];
1755 if (solvid == SOLVID_POS)
1757 di->repo = di->pool->pos.repo;
1764 di->data = di->repo->repodata + di->pool->pos.repodataid;
1766 di->solvid = solvid;
1767 di->state = di_enterrepo;
1768 di->flags |= SEARCH_THISSOLVID;
1773 di->repo = di->pool->solvables[solvid].repo;
1776 else if (di->repoid > 0)
1778 if (!di->pool->urepos)
1784 di->repo = di->pool->repos[di->repoid];
1787 di->solvid = solvid;
1789 di->flags |= SEARCH_THISSOLVID;
1790 di->state = di_enterrepo;
1794 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1800 di->repoid = 0; /* 0 means stay at repo */
1803 di->flags &= ~SEARCH_THISSOLVID;
1804 di->state = di_enterrepo;
1808 dataiterator_match(Dataiterator *di, Datamatcher *ma)
1810 if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
1814 return datamatcher_match(ma, di->kv.str);
1817 /************************************************************************
1818 * data modify functions
1821 /* extend repodata so that it includes solvables p */
1823 repodata_extend(Repodata *data, Id p)
1825 if (data->start == data->end)
1826 data->start = data->end = p;
1829 int old = data->end - data->start;
1830 int new = p - data->end + 1;
1833 data->attrs = solv_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1834 memset(data->attrs + old, 0, new * sizeof(Id *));
1836 data->incoreoffset = solv_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1837 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1840 if (p < data->start)
1842 int old = data->end - data->start;
1843 int new = data->start - p;
1846 data->attrs = solv_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1847 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1848 memset(data->attrs, 0, new * sizeof(Id *));
1850 data->incoreoffset = solv_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1851 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1852 memset(data->incoreoffset, 0, new * sizeof(Id));
1857 /* shrink end of repodata */
1859 repodata_shrink(Repodata *data, int end)
1863 if (data->end <= end)
1865 if (data->start >= end)
1869 for (i = 0; i < data->end - data->start; i++)
1870 solv_free(data->attrs[i]);
1871 data->attrs = solv_free(data->attrs);
1873 data->incoreoffset = solv_free(data->incoreoffset);
1874 data->start = data->end = 0;
1879 for (i = end; i < data->end; i++)
1880 solv_free(data->attrs[i - data->start]);
1881 data->attrs = solv_extend_resize(data->attrs, end - data->start, sizeof(Id *), REPODATA_BLOCK);
1883 if (data->incoreoffset)
1884 data->incoreoffset = solv_extend_resize(data->incoreoffset, end - data->start, sizeof(Id), REPODATA_BLOCK);
1888 /* extend repodata so that it includes solvables from start to start + num - 1 */
1890 repodata_extend_block(Repodata *data, Id start, Id num)
1894 if (!data->incoreoffset)
1896 data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1897 data->start = start;
1898 data->end = start + num;
1901 repodata_extend(data, start);
1903 repodata_extend(data, start + num - 1);
1906 /**********************************************************************/
1909 #define REPODATA_ATTRS_BLOCK 31
1910 #define REPODATA_ATTRDATA_BLOCK 1023
1911 #define REPODATA_ATTRIDDATA_BLOCK 63
1912 #define REPODATA_ATTRNUM64DATA_BLOCK 15
1916 repodata_new_handle(Repodata *data)
1920 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1921 data->nxattrs = 2; /* -1: SOLVID_META */
1923 data->xattrs = solv_extend(data->xattrs, data->nxattrs, 1, sizeof(Id *), REPODATA_BLOCK);
1924 data->xattrs[data->nxattrs] = 0;
1925 return -(data->nxattrs++);
1929 repodata_get_attrp(Repodata *data, Id handle)
1933 if (handle == SOLVID_META && !data->xattrs)
1935 data->xattrs = solv_calloc_block(1, sizeof(Id *), REPODATA_BLOCK);
1938 return data->xattrs - handle;
1940 if (handle < data->start || handle >= data->end)
1941 repodata_extend(data, handle);
1943 data->attrs = solv_calloc_block(data->end - data->start, sizeof(Id *), REPODATA_BLOCK);
1944 return data->attrs + (handle - data->start);
1948 repodata_insert_keyid(Repodata *data, Id handle, Id keyid, Id val, int overwrite)
1954 app = repodata_get_attrp(data, handle);
1959 /* Determine equality based on the name only, allows us to change
1960 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1961 for (pp = ap; *pp; pp += 2)
1962 if (data->keys[*pp].name == data->keys[keyid].name)
1966 if (overwrite || data->keys[*pp].type == REPOKEY_TYPE_DELETED)
1975 ap = solv_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1985 repodata_set(Repodata *data, Id solvid, Repokey *key, Id val)
1989 keyid = repodata_key2id(data, key, 1);
1990 repodata_insert_keyid(data, solvid, keyid, val, 1);
1994 repodata_set_id(Repodata *data, Id solvid, Id keyname, Id id)
1998 key.type = REPOKEY_TYPE_ID;
2000 key.storage = KEY_STORAGE_INCORE;
2001 repodata_set(data, solvid, &key, id);
2005 repodata_set_num(Repodata *data, Id solvid, Id keyname, unsigned long long num)
2009 key.type = REPOKEY_TYPE_NUM;
2011 key.storage = KEY_STORAGE_INCORE;
2012 if (num >= 0x80000000)
2014 data->attrnum64data = solv_extend(data->attrnum64data, data->attrnum64datalen, 1, sizeof(unsigned long long), REPODATA_ATTRNUM64DATA_BLOCK);
2015 data->attrnum64data[data->attrnum64datalen] = num;
2016 num = 0x80000000 | data->attrnum64datalen++;
2018 repodata_set(data, solvid, &key, (Id)num);
2022 repodata_set_poolstr(Repodata *data, Id solvid, Id keyname, const char *str)
2026 if (data->localpool)
2027 id = stringpool_str2id(&data->spool, str, 1);
2029 id = pool_str2id(data->repo->pool, str, 1);
2031 key.type = REPOKEY_TYPE_ID;
2033 key.storage = KEY_STORAGE_INCORE;
2034 repodata_set(data, solvid, &key, id);
2038 repodata_set_constant(Repodata *data, Id solvid, Id keyname, unsigned int constant)
2042 key.type = REPOKEY_TYPE_CONSTANT;
2043 key.size = constant;
2044 key.storage = KEY_STORAGE_INCORE;
2045 repodata_set(data, solvid, &key, 0);
2049 repodata_set_constantid(Repodata *data, Id solvid, Id keyname, Id id)
2053 key.type = REPOKEY_TYPE_CONSTANTID;
2055 key.storage = KEY_STORAGE_INCORE;
2056 repodata_set(data, solvid, &key, 0);
2060 repodata_set_void(Repodata *data, Id solvid, Id keyname)
2064 key.type = REPOKEY_TYPE_VOID;
2066 key.storage = KEY_STORAGE_INCORE;
2067 repodata_set(data, solvid, &key, 0);
2071 repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str)
2076 l = strlen(str) + 1;
2078 key.type = REPOKEY_TYPE_STR;
2080 key.storage = KEY_STORAGE_INCORE;
2081 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2082 memcpy(data->attrdata + data->attrdatalen, str, l);
2083 repodata_set(data, solvid, &key, data->attrdatalen);
2084 data->attrdatalen += l;
2088 repodata_set_binary(Repodata *data, Id solvid, Id keyname, void *buf, int len)
2096 key.type = REPOKEY_TYPE_BINARY;
2098 key.storage = KEY_STORAGE_INCORE;
2099 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, len + 5, 1, REPODATA_ATTRDATA_BLOCK);
2100 dp = data->attrdata + data->attrdatalen;
2101 if (len >= (1 << 14))
2103 if (len >= (1 << 28))
2104 *dp++ = (len >> 28) | 128;
2105 if (len >= (1 << 21))
2106 *dp++ = (len >> 21) | 128;
2107 *dp++ = (len >> 14) | 128;
2109 if (len >= (1 << 7))
2110 *dp++ = (len >> 7) | 128;
2113 memcpy(dp, buf, len);
2114 repodata_set(data, solvid, &key, data->attrdatalen);
2115 data->attrdatalen = dp + len - data->attrdata;
2118 /* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
2119 * so that the caller can append entrysize new elements plus the termination zero there */
2121 repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
2124 Id *ida, *pp, **ppp;
2126 /* check if it is the same as last time, this speeds things up a lot */
2127 if (handle == data->lasthandle && data->keys[data->lastkey].name == keyname && data->keys[data->lastkey].type == keytype && data->attriddatalen == data->lastdatalen)
2129 /* great! just append the new data */
2130 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2131 data->attriddatalen--; /* overwrite terminating 0 */
2132 data->lastdatalen += entrysize;
2136 ppp = repodata_get_attrp(data, handle);
2140 for (; *pp; pp += 2)
2141 if (data->keys[*pp].name == keyname)
2144 if (!pp || !*pp || data->keys[*pp].type != keytype)
2146 /* not found. allocate new key */
2152 key.storage = KEY_STORAGE_INCORE;
2153 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2154 keyid = repodata_key2id(data, &key, 1);
2155 repodata_insert_keyid(data, handle, keyid, data->attriddatalen, 1);
2156 data->lasthandle = handle;
2157 data->lastkey = keyid;
2158 data->lastdatalen = data->attriddatalen + entrysize + 1;
2162 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
2163 oldsize += entrysize;
2164 if (ida + 1 == data->attriddata + data->attriddatalen)
2166 /* this was the last entry, just append it */
2167 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2168 data->attriddatalen--; /* overwrite terminating 0 */
2172 /* too bad. move to back. */
2173 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2174 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
2175 pp[1] = data->attriddatalen;
2176 data->attriddatalen += oldsize;
2178 data->lasthandle = handle;
2179 data->lastkey = *pp;
2180 data->lastdatalen = data->attriddatalen + entrysize + 1;
2184 repodata_set_bin_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2185 const unsigned char *str)
2190 if (!(l = solv_chksum_len(type)))
2195 key.storage = KEY_STORAGE_INCORE;
2196 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2197 memcpy(data->attrdata + data->attrdatalen, str, l);
2198 repodata_set(data, solvid, &key, data->attrdatalen);
2199 data->attrdatalen += l;
2203 repodata_set_checksum(Repodata *data, Id solvid, Id keyname, Id type,
2206 unsigned char buf[64];
2209 if (!(l = solv_chksum_len(type)))
2211 if (l > sizeof(buf) || solv_hex2bin(&str, buf, l) != l)
2213 repodata_set_bin_checksum(data, solvid, keyname, type, buf);
2217 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
2221 if (!(l = solv_chksum_len(type)))
2223 return pool_bin2hex(data->repo->pool, buf, l);
2226 /* rpm filenames don't contain the epoch, so strip it */
2227 static inline const char *
2228 evrid2vrstr(Pool *pool, Id evrid)
2230 const char *p, *evr = pool_id2str(pool, evrid);
2233 for (p = evr; *p >= '0' && *p <= '9'; p++)
2235 return p != evr && *p == ':' && p[1] ? p + 1 : evr;
2239 repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, const char *file)
2241 Pool *pool = data->repo->pool;
2243 const char *str, *fp;
2247 repodata_set_constant(data, solvid, SOLVABLE_MEDIANR, medianr);
2250 if ((dir = strrchr(file, '/')) != 0)
2261 if (l >= 2 && dir[0] == '.' && dir[1] == '/' && (l == 2 || dir[2] != '/'))
2266 if (l == 1 && dir[0] == '.')
2268 s = pool->solvables + solvid;
2271 str = pool_id2str(pool, s->arch);
2272 if (!strncmp(dir, str, l) && !str[l])
2273 repodata_set_void(data, solvid, SOLVABLE_MEDIADIR);
2275 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir);
2278 char *dir2 = solv_strdup(dir);
2280 repodata_set_str(data, solvid, SOLVABLE_MEDIADIR, dir2);
2285 str = pool_id2str(pool, s->name);
2287 if ((!l || !strncmp(fp, str, l)) && fp[l] == '-')
2290 str = evrid2vrstr(pool, s->evr);
2292 if ((!l || !strncmp(fp, str, l)) && fp[l] == '.')
2295 str = pool_id2str(pool, s->arch);
2297 if ((!l || !strncmp(fp, str, l)) && !strcmp(fp + l, ".rpm"))
2299 repodata_set_void(data, solvid, SOLVABLE_MEDIAFILE);
2304 repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
2308 repodata_set_sourcepkg(Repodata *data, Id solvid, const char *sourcepkg)
2310 Pool *pool = data->repo->pool;
2311 Solvable *s = pool->solvables + solvid;
2312 const char *p, *sevr, *sarch, *name, *evr;
2314 p = strrchr(sourcepkg, '.');
2315 if (!p || strcmp(p, ".rpm") != 0)
2318 repodata_set_str(data, solvid, SOLVABLE_SOURCENAME, sourcepkg);
2322 while (p > sourcepkg && *p != '.')
2324 if (*p != '.' || p == sourcepkg)
2327 while (p > sourcepkg && *p != '-')
2329 if (*p != '-' || p == sourcepkg)
2332 while (p > sourcepkg && *p != '-')
2334 if (*p != '-' || p == sourcepkg)
2337 pool = s->repo->pool;
2339 name = pool_id2str(pool, s->name);
2340 if (name && !strncmp(sourcepkg, name, sevr - sourcepkg - 1) && name[sevr - sourcepkg - 1] == 0)
2341 repodata_set_void(data, solvid, SOLVABLE_SOURCENAME);
2343 repodata_set_id(data, solvid, SOLVABLE_SOURCENAME, pool_strn2id(pool, sourcepkg, sevr - sourcepkg - 1, 1));
2345 evr = evrid2vrstr(pool, s->evr);
2346 if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
2347 repodata_set_void(data, solvid, SOLVABLE_SOURCEEVR);
2349 repodata_set_id(data, solvid, SOLVABLE_SOURCEEVR, pool_strn2id(pool, sevr, sarch - sevr - 1, 1));
2351 if (!strcmp(sarch, "src.rpm"))
2352 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_SRC);
2353 else if (!strcmp(sarch, "nosrc.rpm"))
2354 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
2356 repodata_set_constantid(data, solvid, SOLVABLE_SOURCEARCH, pool_strn2id(pool, sarch, strlen(sarch) - 4, 1));
2360 repodata_set_idarray(Repodata *data, Id solvid, Id keyname, Queue *q)
2366 key.type = REPOKEY_TYPE_IDARRAY;
2368 key.storage = KEY_STORAGE_INCORE;
2369 repodata_set(data, solvid, &key, data->attriddatalen);
2370 data->attriddata = solv_extend(data->attriddata, data->attriddatalen, q->count + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
2371 for (i = 0; i < q->count; i++)
2372 data->attriddata[data->attriddatalen++] = q->elements[i];
2373 data->attriddata[data->attriddatalen++] = 0;
2377 repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
2381 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", solvid, dir, num, num2, data->attriddatalen);
2383 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
2384 data->attriddata[data->attriddatalen++] = dir;
2385 data->attriddata[data->attriddatalen++] = num;
2386 data->attriddata[data->attriddatalen++] = num2;
2387 data->attriddata[data->attriddatalen++] = 0;
2391 repodata_add_dirstr(Repodata *data, Id solvid, Id keyname, Id dir, const char *str)
2397 l = strlen(str) + 1;
2398 data->attrdata = solv_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
2399 memcpy(data->attrdata + data->attrdatalen, str, l);
2400 stroff = data->attrdatalen;
2401 data->attrdatalen += l;
2404 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", solvid, dir, str, data->attriddatalen);
2406 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
2407 data->attriddata[data->attriddatalen++] = dir;
2408 data->attriddata[data->attriddatalen++] = stroff;
2409 data->attriddata[data->attriddatalen++] = 0;
2413 repodata_add_idarray(Repodata *data, Id solvid, Id keyname, Id id)
2416 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", solvid, id, data->attriddatalen);
2418 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_IDARRAY, 1);
2419 data->attriddata[data->attriddatalen++] = id;
2420 data->attriddata[data->attriddatalen++] = 0;
2424 repodata_add_poolstr_array(Repodata *data, Id solvid, Id keyname,
2428 if (data->localpool)
2429 id = stringpool_str2id(&data->spool, str, 1);
2431 id = pool_str2id(data->repo->pool, str, 1);
2432 repodata_add_idarray(data, solvid, keyname, id);
2436 repodata_add_fixarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2438 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FIXARRAY, 1);
2439 data->attriddata[data->attriddatalen++] = ghandle;
2440 data->attriddata[data->attriddatalen++] = 0;
2444 repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle)
2446 repodata_add_array(data, solvid, keyname, REPOKEY_TYPE_FLEXARRAY, 1);
2447 data->attriddata[data->attriddatalen++] = ghandle;
2448 data->attriddata[data->attriddatalen++] = 0;
2452 repodata_set_deleted_uninternalized(Repodata *data, Id solvid, Id keyname)
2455 app = repodata_get_attrp(data, solvid);
2459 for (; *ap; ap += 2)
2460 if (data->keys[*ap].name == keyname)
2466 for (; *ap; ap += 2)
2468 if (data->keys[*ap].name == keyname)
2476 /* XXX: does not work correctly, needs fix in iterators! */
2478 repodata_set_deleted(Repodata *data, Id solvid, Id keyname)
2482 key.type = REPOKEY_TYPE_DELETED;
2484 key.storage = KEY_STORAGE_INCORE;
2485 repodata_set(data, solvid, &key, 0);
2488 /* add all (uninternalized) attrs from src to dest */
2490 repodata_merge_attrs(Repodata *data, Id dest, Id src)
2493 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2495 for (; *keyp; keyp += 2)
2496 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
2499 /* add some (uninternalized) attrs from src to dest */
2501 repodata_merge_some_attrs(Repodata *data, Id dest, Id src, Map *keyidmap, int overwrite)
2504 if (dest == src || !data->attrs || !(keyp = data->attrs[src - data->start]))
2506 for (; *keyp; keyp += 2)
2507 if (!keyidmap || MAPTST(keyidmap, keyp[0]))
2508 repodata_insert_keyid(data, dest, keyp[0], keyp[1], overwrite);
2511 /* swap (uninternalized) attrs from src and dest */
2513 repodata_swap_attrs(Repodata *data, Id dest, Id src)
2516 if (!data->attrs || dest == src)
2518 tmpattrs = data->attrs[dest - data->start];
2519 data->attrs[dest - data->start] = data->attrs[src - data->start];
2520 data->attrs[src - data->start] = tmpattrs;
2524 /**********************************************************************/
2526 /* TODO: unify with repo_write and repo_solv! */
2528 #define EXTDATA_BLOCK 1023
2536 data_addid(struct extdata *xd, Id sx)
2538 unsigned int x = (unsigned int)sx;
2541 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2542 dp = xd->buf + xd->len;
2547 *dp++ = (x >> 28) | 128;
2549 *dp++ = (x >> 21) | 128;
2550 *dp++ = (x >> 14) | 128;
2553 *dp++ = (x >> 7) | 128;
2555 xd->len = dp - xd->buf;
2559 data_addid64(struct extdata *xd, unsigned long long x)
2561 if (x >= 0x100000000)
2565 data_addid(xd, (Id)(x >> 35));
2566 xd->buf[xd->len - 1] |= 128;
2568 data_addid(xd, (Id)((unsigned int)x | 0x80000000));
2569 xd->buf[xd->len - 5] = (x >> 28) | 128;
2572 data_addid(xd, (Id)x);
2576 data_addideof(struct extdata *xd, Id sx, int eof)
2578 unsigned int x = (unsigned int)sx;
2581 xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
2582 dp = xd->buf + xd->len;
2587 *dp++ = (x >> 27) | 128;
2589 *dp++ = (x >> 20) | 128;
2590 *dp++ = (x >> 13) | 128;
2593 *dp++ = (x >> 6) | 128;
2594 *dp++ = eof ? (x & 63) : (x & 63) | 64;
2595 xd->len = dp - xd->buf;
2599 data_addblob(struct extdata *xd, unsigned char *blob, int len)
2601 xd->buf = solv_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
2602 memcpy(xd->buf + xd->len, blob, len);
2606 /*********************************/
2608 /* internalalize some key into incore/vincore data */
2611 repodata_serialize_key(Repodata *data, struct extdata *newincore,
2612 struct extdata *newvincore,
2614 Repokey *key, Id val)
2618 unsigned int oldvincorelen = 0;
2622 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2625 oldvincorelen = xd->len;
2629 case REPOKEY_TYPE_VOID:
2630 case REPOKEY_TYPE_CONSTANT:
2631 case REPOKEY_TYPE_CONSTANTID:
2633 case REPOKEY_TYPE_STR:
2634 data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
2636 case REPOKEY_TYPE_MD5:
2637 data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
2639 case REPOKEY_TYPE_SHA1:
2640 data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
2642 case REPOKEY_TYPE_SHA256:
2643 data_addblob(xd, data->attrdata + val, SIZEOF_SHA256);
2645 case REPOKEY_TYPE_NUM:
2646 if (val & 0x80000000)
2648 data_addid64(xd, data->attrnum64data[val ^ 0x80000000]);
2652 case REPOKEY_TYPE_ID:
2653 case REPOKEY_TYPE_DIR:
2654 data_addid(xd, val);
2656 case REPOKEY_TYPE_BINARY:
2659 unsigned char *dp = data_read_id(data->attrdata + val, &len);
2660 dp += (unsigned int)len;
2661 data_addblob(xd, data->attrdata + val, dp - (data->attrdata + val));
2664 case REPOKEY_TYPE_IDARRAY:
2665 for (ida = data->attriddata + val; *ida; ida++)
2666 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
2668 case REPOKEY_TYPE_DIRNUMNUMARRAY:
2669 for (ida = data->attriddata + val; *ida; ida += 3)
2671 data_addid(xd, ida[0]);
2672 data_addid(xd, ida[1]);
2673 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
2676 case REPOKEY_TYPE_DIRSTRARRAY:
2677 for (ida = data->attriddata + val; *ida; ida += 2)
2679 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
2680 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
2683 case REPOKEY_TYPE_FIXARRAY:
2687 for (ida = data->attriddata + val; *ida; ida++)
2691 kp = data->xattrs[-*ida];
2699 schemaid = repodata_schema2id(data, schema, 1);
2700 else if (schemaid != repodata_schema2id(data, schema, 0))
2702 pool_debug(data->repo->pool, SOLV_FATAL, "fixarray substructs with different schemas\n");
2708 data_addid(xd, num);
2709 data_addid(xd, schemaid);
2710 for (ida = data->attriddata + val; *ida; ida++)
2712 Id *kp = data->xattrs[-*ida];
2716 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2720 case REPOKEY_TYPE_FLEXARRAY:
2723 for (ida = data->attriddata + val; *ida; ida++)
2725 data_addid(xd, num);
2726 for (ida = data->attriddata + val; *ida; ida++)
2728 Id *kp = data->xattrs[-*ida];
2731 data_addid(xd, 0); /* XXX */
2738 schemaid = repodata_schema2id(data, schema, 1);
2739 data_addid(xd, schemaid);
2740 kp = data->xattrs[-*ida];
2742 repodata_serialize_key(data, newincore, newvincore, schema, data->keys + *kp, kp[1]);
2747 pool_debug(data->repo->pool, SOLV_FATAL, "don't know how to handle type %d\n", key->type);
2750 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2752 /* put offset/len in incore */
2753 data_addid(newincore, data->lastverticaloffset + oldvincorelen);
2754 oldvincorelen = xd->len - oldvincorelen;
2755 data_addid(newincore, oldvincorelen);
2760 repodata_internalize(Repodata *data)
2762 Repokey *key, solvkey;
2764 Id schemaid, *schema, *sp, oldschema, *keyp, *keypstart, *seen;
2765 unsigned char *dp, *ndp;
2766 int newschema, oldcount;
2767 struct extdata newincore;
2768 struct extdata newvincore;
2771 if (!data->attrs && !data->xattrs)
2774 newvincore.buf = data->vincore;
2775 newvincore.len = data->vincorelen;
2777 /* find the solvables key, create if needed */
2778 memset(&solvkey, 0, sizeof(solvkey));
2779 solvkey.name = REPOSITORY_SOLVABLES;
2780 solvkey.type = REPOKEY_TYPE_FLEXARRAY;
2782 solvkey.storage = KEY_STORAGE_INCORE;
2783 solvkeyid = repodata_key2id(data, &solvkey, data->end != data->start ? 1 : 0);
2785 schema = solv_malloc2(data->nkeys, sizeof(Id));
2786 seen = solv_malloc2(data->nkeys, sizeof(Id));
2788 /* Merge the data already existing (in data->schemata, ->incoredata and
2789 friends) with the new attributes in data->attrs[]. */
2790 nentry = data->end - data->start;
2791 memset(&newincore, 0, sizeof(newincore));
2792 data_addid(&newincore, 0); /* start data at offset 1 */
2794 data->mainschema = 0;
2795 data->mainschemaoffsets = solv_free(data->mainschemaoffsets);
2797 /* join entry data */
2798 /* we start with the meta data, entry -1 */
2799 for (entry = -1; entry < nentry; entry++)
2801 memset(seen, 0, data->nkeys * sizeof(Id));
2803 dp = data->incoredata;
2806 dp += entry >= 0 ? data->incoreoffset[entry] : 1;
2807 dp = data_read_id(dp, &oldschema);
2810 fprintf(stderr, "oldschema %d\n", oldschema);
2811 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
2812 fprintf(stderr, "schemadata %p\n", data->schemadata);
2814 /* seen: -1: old data 0: skipped >0: id + 1 */
2818 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
2822 pool_debug(data->repo->pool, SOLV_FATAL, "Inconsistent old data (key occured twice).\n");
2830 keyp = data->attrs ? data->attrs[entry] : 0;
2833 /* strip solvables key */
2835 for (sp = keyp = schema; *sp; sp++)
2836 if (*sp != solvkeyid)
2841 seen[solvkeyid] = 0;
2842 keyp = data->xattrs ? data->xattrs[1] : 0;
2845 for (; *keyp; keyp += 2)
2852 seen[*keyp] = keyp[1] + 1;
2854 if (entry < 0 && data->end != data->start)
2861 /* Ideally we'd like to sort the new schema here, to ensure
2862 schema equality independend of the ordering. We can't do that
2863 yet. For once see below (old ids need to come before new ids).
2864 An additional difficulty is that we also need to move
2865 the values with the keys. */
2866 schemaid = repodata_schema2id(data, schema, 1);
2868 schemaid = oldschema;
2871 /* Now create data blob. We walk through the (possibly new) schema
2872 and either copy over old data, or insert the new. */
2873 /* XXX Here we rely on the fact that the (new) schema has the form
2874 o1 o2 o3 o4 ... | n1 n2 n3 ...
2875 (oX being the old keyids (possibly overwritten), and nX being
2876 the new keyids). This rules out sorting the keyids in order
2877 to ensure a small schema count. */
2879 data->incoreoffset[entry] = newincore.len;
2880 data_addid(&newincore, schemaid);
2883 data->mainschema = schemaid;
2884 data->mainschemaoffsets = solv_calloc(sp - schema, sizeof(Id));
2886 keypstart = data->schemadata + data->schemata[schemaid];
2887 for (keyp = keypstart; *keyp; keyp++)
2890 data->mainschemaoffsets[keyp - keypstart] = newincore.len;
2891 if (*keyp == solvkeyid)
2893 /* add flexarray entry count */
2894 data_addid(&newincore, data->end - data->start);
2897 key = data->keys + *keyp;
2899 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));
2904 /* Skip the data associated with this old key. */
2905 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
2907 ndp = data_skip(dp, REPOKEY_TYPE_ID);
2908 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
2910 else if (key->storage == KEY_STORAGE_INCORE)
2911 ndp = data_skip_key(data, dp, key);
2914 if (seen[*keyp] == -1)
2916 /* If this key was an old one _and_ was not overwritten with
2917 a different value copy over the old value (we skipped it
2920 data_addblob(&newincore, dp, ndp - dp);
2923 else if (seen[*keyp])
2925 /* Otherwise we have a new value. Parse it into the internal
2927 repodata_serialize_key(data, &newincore, &newvincore,
2928 schema, key, seen[*keyp] - 1);
2932 if (entry >= 0 && data->attrs && data->attrs[entry])
2933 data->attrs[entry] = solv_free(data->attrs[entry]);
2935 /* free all xattrs */
2936 for (entry = 0; entry < data->nxattrs; entry++)
2937 if (data->xattrs[entry])
2938 solv_free(data->xattrs[entry]);
2939 data->xattrs = solv_free(data->xattrs);
2942 data->lasthandle = 0;
2944 data->lastdatalen = 0;
2947 repodata_free_schemahash(data);
2949 solv_free(data->incoredata);
2950 data->incoredata = newincore.buf;
2951 data->incoredatalen = newincore.len;
2952 data->incoredatafree = 0;
2954 solv_free(data->vincore);
2955 data->vincore = newvincore.buf;
2956 data->vincorelen = newvincore.len;
2958 data->attrs = solv_free(data->attrs);
2959 data->attrdata = solv_free(data->attrdata);
2960 data->attriddata = solv_free(data->attriddata);
2961 data->attrnum64data = solv_free(data->attrnum64data);
2962 data->attrdatalen = 0;
2963 data->attriddatalen = 0;
2964 data->attrnum64datalen = 0;
2968 repodata_disable_paging(Repodata *data)
2970 if (maybe_load_repodata(data, 0))
2971 repopagestore_disable_paging(&data->store);
2975 repodata_load_stub(Repodata *data)
2977 Repo *repo = data->repo;
2978 Pool *pool = repo->pool;
2980 struct _Pool_tmpspace oldtmpspace;
2982 if (!pool->loadcallback)
2984 data->state = REPODATA_ERROR;
2987 data->state = REPODATA_LOADING;
2989 /* save tmp space */
2990 oldtmpspace = pool->tmpspace;
2991 memset(&pool->tmpspace, 0, sizeof(pool->tmpspace));
2993 r = pool->loadcallback(pool, data, pool->loadcallbackdata);
2995 /* restore tmp space */
2996 for (i = 0; i < POOL_TMPSPACEBUF; i++)
2997 solv_free(pool->tmpspace.buf[i]);
2998 pool->tmpspace = oldtmpspace;
3000 data->state = r ? REPODATA_AVAILABLE : REPODATA_ERROR;
3004 repodata_create_stubs(Repodata *data)
3006 Repo *repo = data->repo;
3007 Pool *pool = repo->pool;
3014 int datastart, dataend;
3016 repodataid = data - repo->repodata;
3017 datastart = data->start;
3018 dataend = data->end;
3019 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
3020 while (dataiterator_step(&di))
3022 if (di.data - repo->repodata != repodataid)
3026 dataiterator_free(&di);
3029 stubdataids = solv_calloc(cnt, sizeof(*stubdataids));
3030 for (i = 0; i < cnt; i++)
3032 sdata = repo_add_repodata(repo, 0);
3033 if (dataend > datastart)
3034 repodata_extend_block(sdata, datastart, dataend - datastart);
3035 stubdataids[i] = sdata - repo->repodata;
3036 sdata->state = REPODATA_STUB;
3037 sdata->loadcallback = repodata_load_stub;
3040 dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0);
3042 while (dataiterator_step(&di))
3044 if (di.data - repo->repodata != repodataid)
3046 if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents)
3048 dataiterator_entersub(&di);
3049 sdata = repo->repodata + stubdataids[i++];
3053 switch (di.key->type)
3055 case REPOKEY_TYPE_ID:
3056 repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id);
3058 case REPOKEY_TYPE_CONSTANTID:
3059 repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id);
3061 case REPOKEY_TYPE_STR:
3062 repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str);
3064 case REPOKEY_TYPE_VOID:
3065 repodata_set_void(sdata, SOLVID_META, di.key->name);
3067 case REPOKEY_TYPE_NUM:
3068 repodata_set_num(sdata, SOLVID_META, di.key->name, SOLV_KV_NUM64(&di.kv));
3070 case REPOKEY_TYPE_MD5:
3071 case REPOKEY_TYPE_SHA1:
3072 case REPOKEY_TYPE_SHA256:
3073 repodata_set_bin_checksum(sdata, SOLVID_META, di.key->name, di.key->type, (const unsigned char *)di.kv.str);
3075 case REPOKEY_TYPE_IDARRAY:
3076 repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id);
3077 if (di.key->name == REPOSITORY_KEYS)
3084 xkeyname = di.kv.id;
3087 xkey.name = xkeyname;
3088 xkey.type = di.kv.id;
3089 xkey.storage = KEY_STORAGE_INCORE;
3091 repodata_key2id(sdata, &xkey, 1);
3098 dataiterator_free(&di);
3099 for (i = 0; i < cnt; i++)
3100 repodata_internalize(repo->repodata + stubdataids[i]);
3101 solv_free(stubdataids);
3105 repodata_memused(Repodata *data)
3107 return data->incoredatalen + data->vincorelen;
3111 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: