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
26 #include "poolid_private.h"
31 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
32 unsigned char *out, unsigned int out_len);
33 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
36 unsigned int out_len);
38 #define REPODATA_BLOCK 255
42 repodata_init(Repodata *data, Repo *repo, int localpool)
44 memset(data, 0, sizeof (*data));
46 data->localpool = localpool;
48 stringpool_init_empty(&data->spool);
49 data->keys = sat_calloc(1, sizeof(Repokey));
51 data->schemata = sat_calloc(1, sizeof(Id));
52 data->schemadata = sat_calloc(1, sizeof(Id));
54 data->schemadatalen = 1;
55 data->start = repo->start;
56 data->end = repo->end;
57 data->nextra = repo->nextra;
59 data->incoreoffset = sat_extend_resize(0, data->end - data->start, sizeof(Id), REPODATA_BLOCK);
60 data->extraoffset = sat_extend_resize(0, repo->nextra, sizeof(Id), REPODATA_BLOCK);
65 repodata_free(Repodata *data)
68 sat_free(data->schemata);
69 sat_free(data->schemadata);
71 sat_free(data->spool.strings);
72 sat_free(data->spool.stringspace);
73 sat_free(data->spool.stringhashtbl);
75 sat_free(data->dirpool.dirs);
76 sat_free(data->dirpool.dirtraverse);
78 sat_free(data->incoredata);
79 sat_free(data->incoreoffset);
80 sat_free(data->extraoffset);
81 sat_free(data->verticaloffset);
83 sat_free(data->blob_store);
84 sat_free(data->pages);
85 sat_free(data->mapped);
87 sat_free(data->vincore);
89 sat_free(data->attrs);
90 sat_free(data->extraattrs);
91 sat_free(data->attrdata);
92 sat_free(data->attriddata);
94 sat_free(data->location);
95 sat_free(data->addedfileprovides);
97 if (data->pagefd != -1)
101 static unsigned char *
102 forward_to_key(Repodata *data, Id keyid, Id schemaid, unsigned char *dp)
106 keyp = data->schemadata + data->schemata[schemaid];
107 while ((k = *keyp++) != 0)
111 if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
113 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip that offset */
114 dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip that length */
117 if (data->keys[k].storage != KEY_STORAGE_INCORE)
119 dp = data_skip(dp, data->keys[k].type);
124 #define BLOB_PAGEBITS 15
125 #define BLOB_PAGESIZE (1 << BLOB_PAGEBITS)
127 static unsigned char *
128 load_page_range(Repodata *data, unsigned int pstart, unsigned int pend)
130 /* Make sure all pages from PSTART to PEND (inclusive) are loaded,
131 and are consecutive. Return a pointer to the mapping of PSTART. */
132 unsigned char buf[BLOB_PAGESIZE];
135 /* Quick check in case all pages are there already and consecutive. */
136 for (i = pstart; i <= pend; i++)
137 if (data->pages[i].mapped_at == -1
139 && data->pages[i].mapped_at
140 != data->pages[i-1].mapped_at + BLOB_PAGESIZE))
143 return data->blob_store + data->pages[pstart].mapped_at;
145 if (data->pagefd == -1)
148 /* Ensure that we can map the numbers of pages we need at all. */
149 if (pend - pstart + 1 > data->ncanmap)
151 unsigned int oldcan = data->ncanmap;
152 data->ncanmap = pend - pstart + 1;
153 if (data->ncanmap < 4)
155 data->mapped = sat_realloc2(data->mapped, data->ncanmap, sizeof(data->mapped[0]));
156 memset (data->mapped + oldcan, 0, (data->ncanmap - oldcan) * sizeof (data->mapped[0]));
157 data->blob_store = sat_realloc2(data->blob_store, data->ncanmap, BLOB_PAGESIZE);
159 fprintf (stderr, "PAGE: can map %d pages\n", data->ncanmap);
163 /* Now search for "cheap" space in our store. Space is cheap if it's either
164 free (very cheap) or contains pages we search for anyway. */
166 /* Setup cost array. */
167 unsigned int cost[data->ncanmap];
168 for (i = 0; i < data->ncanmap; i++)
170 unsigned int pnum = data->mapped[i];
176 Attrblobpage *p = data->pages + pnum;
177 assert (p->mapped_at != -1);
178 if (pnum >= pstart && pnum <= pend)
185 /* And search for cheapest space. */
186 unsigned int best_cost = -1;
187 unsigned int best = 0;
188 unsigned int same_cost = 0;
189 for (i = 0; i + pend - pstart < data->ncanmap; i++)
191 unsigned int c = cost[i];
193 for (j = 0; j < pend - pstart + 1; j++)
196 best_cost = c, best = i;
197 else if (c == best_cost)
199 /* A null cost won't become better. */
203 /* If all places have the same cost we would thrash on slot 0. Avoid
204 this by doing a round-robin strategy in this case. */
205 if (same_cost == data->ncanmap - pend + pstart - 1)
206 best = data->rr_counter++ % (data->ncanmap - pend + pstart);
208 /* So we want to map our pages from [best] to [best+pend-pstart].
209 Use a very simple strategy, which doesn't make the best use of
210 our resources, but works. Throw away all pages in that range
211 (even ours) then copy around ours (in case they were outside the
212 range) or read them in. */
213 for (i = best; i < best + pend - pstart + 1; i++)
215 unsigned int pnum = data->mapped[i];
217 /* If this page is exactly at the right place already,
218 no need to evict it. */
219 && pnum != pstart + i - best)
221 /* Evict this page. */
223 fprintf (stderr, "PAGE: evict page %d from %d\n", pnum, i);
227 data->pages[pnum].mapped_at = -1;
231 /* Everything is free now. Read in the pages we want. */
232 for (i = pstart; i <= pend; i++)
234 Attrblobpage *p = data->pages + i;
235 unsigned int pnum = i - pstart + best;
236 void *dest = data->blob_store + pnum * BLOB_PAGESIZE;
237 if (p->mapped_at != -1)
239 if (p->mapped_at != pnum * BLOB_PAGESIZE)
242 fprintf (stderr, "PAGECOPY: %d to %d\n", i, pnum);
244 /* Still mapped somewhere else, so just copy it from there. */
245 memcpy (dest, data->blob_store + p->mapped_at, BLOB_PAGESIZE);
246 data->mapped[p->mapped_at / BLOB_PAGESIZE] = 0;
251 unsigned int in_len = p->file_size;
252 unsigned int compressed = in_len & 1;
255 fprintf (stderr, "PAGEIN: %d to %d", i, pnum);
257 if (pread(data->pagefd, compressed ? buf : dest, in_len, p->file_offset) != in_len)
259 perror ("mapping pread");
264 unsigned int out_len;
265 out_len = unchecked_decompress_buf(buf, in_len,
266 dest, BLOB_PAGESIZE);
267 if (out_len != BLOB_PAGESIZE && i < data->num_pages - 1)
269 fprintf(stderr, "can't decompress\n");
273 fprintf (stderr, " (expand %d to %d)", in_len, out_len);
277 fprintf (stderr, "\n");
280 p->mapped_at = pnum * BLOB_PAGESIZE;
281 data->mapped[pnum] = i + 1;
283 return data->blob_store + best * BLOB_PAGESIZE;
286 static unsigned char *
287 make_vertical_available(Repodata *data, Repokey *key, Id off, Id len)
292 if (off >= data->lastverticaloffset)
294 off -= data->lastverticaloffset;
295 if (off + len > data->vincorelen)
297 return data->vincore + off;
299 if (off + len > key->size)
301 /* we now have the offset, go into vertical */
302 off += data->verticaloffset[key - data->keys];
303 /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
304 dp = load_page_range(data, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
306 dp += off % BLOB_PAGESIZE;
310 static inline unsigned char *
311 get_data(Repodata *data, Repokey *key, unsigned char **dpp)
313 unsigned char *dp = *dpp;
317 if (key->storage == KEY_STORAGE_INCORE)
319 /* hmm, this is a bit expensive */
320 *dpp = data_skip(dp, key->type);
323 else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
326 dp = data_read_id(dp, &off);
327 dp = data_read_id(dp, &len);
329 return make_vertical_available(data, key, off, len);
335 maybe_load_repodata(Repodata *data, Id *keyid)
337 if (data->state == REPODATA_STUB)
339 if (data->loadcallback)
343 /* key order may change when loading */
345 Id name = data->keys[*keyid].name;
346 Id type = data->keys[*keyid].type;
347 data->loadcallback(data);
348 if (data->state == REPODATA_AVAILABLE)
350 for (i = 1; i < data->nkeys; i++)
351 if (data->keys[i].name == name && data->keys[i].type == type)
360 data->loadcallback(data);
363 data->state = REPODATA_ERROR;
365 if (data->state == REPODATA_AVAILABLE)
367 data->state = REPODATA_ERROR;
371 static inline unsigned char*
372 entry2data(Repodata *data, Id entry)
375 return data->incoredata + data->extraoffset[-1 - entry];
377 return data->incoredata + data->incoreoffset[entry];
381 repodata_lookup_id(Repodata *data, Id entry, Id keyid)
388 if (!maybe_load_repodata(data, &keyid))
390 dp = entry2data(data, entry);
393 dp = data_read_id(dp, &schema);
394 /* make sure the schema of this solvable contains the key */
395 for (keyp = data->schemadata + data->schemata[schema]; *keyp != keyid; keyp++)
398 dp = forward_to_key(data, keyid, schema, dp);
399 key = data->keys + keyid;
400 dp = get_data(data, key, &dp);
403 if (key->type == REPOKEY_TYPE_CONSTANTID)
405 if (key->type != REPOKEY_TYPE_ID)
407 dp = data_read_id(dp, &id);
412 repodata_lookup_str(Repodata *data, Id entry, Id keyid)
419 if (!maybe_load_repodata(data, &keyid))
422 dp = entry2data(data, entry);
425 dp = data_read_id(dp, &schema);
426 /* make sure the schema of this solvable contains the key */
427 for (keyp = data->schemadata + data->schemata[schema]; *keyp != keyid; keyp++)
430 dp = forward_to_key(data, keyid, schema, dp);
431 key = data->keys + keyid;
432 dp = get_data(data, key, &dp);
435 if (key->type == REPOKEY_TYPE_STR)
436 return (const char *)dp;
437 if (key->type == REPOKEY_TYPE_CONSTANTID)
438 return id2str(data->repo->pool, key->size);
439 if (key->type == REPOKEY_TYPE_ID)
440 dp = data_read_id(dp, &id);
444 return data->spool.stringspace + data->spool.strings[id];
445 return id2str(data->repo->pool, id);
449 repodata_lookup_num(Repodata *data, Id entry, Id keyid, unsigned int *value)
459 if (!maybe_load_repodata(data, &keyid))
462 dp = entry2data(data, entry);
465 dp = data_read_id(dp, &schema);
466 /* make sure the schema of this solvable contains the key */
467 for (keyp = data->schemadata + data->schemata[schema]; *keyp != keyid; keyp++)
470 dp = forward_to_key(data, keyid, schema, dp);
471 key = data->keys + keyid;
472 dp = get_data(data, key, &dp);
475 if (key->type == REPOKEY_TYPE_NUM
476 || key->type == REPOKEY_TYPE_U32
477 || key->type == REPOKEY_TYPE_CONSTANT)
479 dp = data_fetch(dp, &kv, key);
487 repodata_lookup_void(Repodata *data, Id entry, Id keyid)
492 if (!maybe_load_repodata(data, &keyid))
494 dp = entry2data(data, entry);
497 dp = data_read_id(dp, &schema);
498 for (keyp = data->schemadata + data->schemata[schema]; *keyp != keyid; keyp++)
504 const unsigned char *
505 repodata_lookup_bin_checksum(Repodata *data, Id entry, Id keyid, Id *typep)
512 if (!maybe_load_repodata(data, &keyid))
514 dp = entry2data(data, entry);
517 dp = data_read_id(dp, &schema);
518 for (keyp = data->schemadata + data->schemata[schema]; *keyp != keyid; keyp++)
521 dp = forward_to_key(data, keyid, schema, dp);
522 key = data->keys + keyid;
524 return get_data(data, key, &dp);
528 repodata_search(Repodata *data, Id entry, Id keyname, int (*callback)(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv), void *cbdata)
532 Id k, keyid, *kp, *keyp;
533 unsigned char *dp, *ddp;
539 || !maybe_load_repodata(data, 0))
542 dp = entry2data(data, entry);
545 dp = data_read_id(dp, &schema);
546 keyp = data->schemadata + data->schemata[schema];
549 /* search in a specific key */
550 for (kp = keyp; (k = *kp++) != 0; )
551 if (data->keys[k].name == keyname)
555 dp = forward_to_key(data, k, schema, dp);
561 while ((keyid = *keyp++) != 0)
564 key = data->keys + keyid;
565 ddp = get_data(data, key, &dp);
568 ddp = data_fetch(ddp, &kv, key);
571 stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
573 while (!kv.eof && !stop);
574 if (onekey || stop > SEARCH_NEXT_KEY)
580 dataiterator_newdata(Dataiterator *di)
582 Id keyname = di->keyname;
583 Repodata *data = di->data;
586 if (data->state == REPODATA_STUB)
591 for (j = 1; j < data->nkeys; j++)
592 if (keyname == data->keys[j].name)
594 if (j == data->nkeys)
598 if (data->loadcallback)
599 data->loadcallback(data);
601 data->state = REPODATA_ERROR;
603 if (data->state == REPODATA_ERROR)
607 unsigned char *dp = data->incoredata;
611 dp += data->incoreoffset[di->solvid - data->start];
613 dp += data->extraoffset[-1 - di->solvid - data->extrastart];
614 dp = data_read_id(dp, &schema);
615 Id *keyp = data->schemadata + data->schemata[schema];
619 /* search in a specific key */
620 for (kp = keyp; (k = *kp++) != 0; )
621 if (data->keys[k].name == keyname)
625 dp = forward_to_key(data, k, schema, dp);
635 di->key = di->data->keys + keyid;
640 di->dp = get_data(di->data, di->key, &di->nextkeydp);
645 dataiterator_init(Dataiterator *di, Repo *repo, Id p, Id keyname,
646 const char *match, int flags)
652 di->flags |= __SEARCH_ONESOLVABLE;
653 di->data = repo->repodata - 1;
654 if (flags & SEARCH_NO_STORAGE_SOLVABLE)
661 di->solvid = repo->start - 1;
664 fprintf(stderr, "A repo contains the NULL solvable!\n");
667 di->data = repo->repodata + repo->nrepodata - 1;
671 di->keyname = keyname;
672 static Id zeroid = 0;
679 /* FIXME factor and merge with repo_matchvalue */
681 dataiterator_match_int_real(Dataiterator *di, int flags, const void *vmatch)
683 KeyValue *kv = &di->kv;
684 const char *match = vmatch;
685 if ((flags & SEARCH_STRINGMASK) != 0)
687 switch (di->key->type)
689 case REPOKEY_TYPE_ID:
690 case REPOKEY_TYPE_IDARRAY:
691 if (di->data && di->data->localpool)
692 kv->str = stringpool_id2str(&di->data->spool, kv->id);
694 kv->str = id2str(di->repo->pool, kv->id);
696 case REPOKEY_TYPE_STR:
701 switch ((flags & SEARCH_STRINGMASK))
703 case SEARCH_SUBSTRING:
704 if (flags & SEARCH_NOCASE)
706 if (!strcasestr(kv->str, match))
711 if (!strstr(kv->str, match))
716 if (flags & SEARCH_NOCASE)
718 if (strcasecmp(match, kv->str))
723 if (strcmp(match, kv->str))
728 if (fnmatch(match, kv->str, (flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0))
733 if (regexec((const regex_t *)vmatch, kv->str, 0, NULL, 0))
744 dataiterator_match_int(Dataiterator *di)
746 return dataiterator_match_int_real(di, di->flags, di->match);
750 dataiterator_match(Dataiterator *di, int flags, const void *vmatch)
752 return dataiterator_match_int_real(di, flags, vmatch);
755 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
756 { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
757 { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
758 { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
759 { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
760 { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
761 { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
762 { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
763 { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
764 { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
765 { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
766 { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
767 { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
768 { SOLVABLE_FRESHENS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
769 { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
773 dataiterator_step(Dataiterator *di)
787 di->kv.eof = idp[1] ? 0 : 1;
793 Solvable *s = di->repo->pool->solvables + di->solvid;
794 int state = di->state;
795 di->key = solvablekeys + state - 1;
797 di->state = RPM_RPMDBID;
804 state = di->keyname - 1;
826 case SOLVABLE_VENDOR:
829 di->kv.id = s->vendor;
832 case SOLVABLE_PROVIDES:
833 di->idp = s->provides
834 ? di->repo->idarraydata + s->provides : 0;
836 case SOLVABLE_OBSOLETES:
837 di->idp = s->obsoletes
838 ? di->repo->idarraydata + s->obsoletes : 0;
840 case SOLVABLE_CONFLICTS:
841 di->idp = s->conflicts
842 ? di->repo->idarraydata + s->conflicts : 0;
844 case SOLVABLE_REQUIRES:
845 di->idp = s->requires
846 ? di->repo->idarraydata + s->requires : 0;
848 case SOLVABLE_RECOMMENDS:
849 di->idp = s->recommends
850 ? di->repo->idarraydata + s->recommends : 0;
852 case SOLVABLE_SUPPLEMENTS:
853 di->idp = s->supplements
854 ? di->repo->idarraydata + s->supplements : 0;
856 case SOLVABLE_SUGGESTS:
857 di->idp = s->suggests
858 ? di->repo->idarraydata + s->suggests : 0;
860 case SOLVABLE_ENHANCES:
861 di->idp = s->enhances
862 ? di->repo->idarraydata + s->enhances : 0;
864 case SOLVABLE_FRESHENS:
865 di->idp = s->freshens
866 ? di->repo->idarraydata + s->freshens : 0;
869 if (!di->repo->rpmdbid)
871 di->kv.num = di->repo->rpmdbid[di->solvid - di->repo->start];
875 di->data = di->repo->repodata - 1;
886 di->dp = data_fetch(di->dp, &di->kv, di->key);
891 if (di->keyname || !(keyid = *di->keyp++))
895 Repo *repo = di->repo;
896 Repodata *data = ++di->data;
897 if (data >= repo->repodata + repo->nrepodata)
899 if (di->flags & __SEARCH_ONESOLVABLE)
903 while (++di->solvid < repo->end)
904 if (repo->pool->solvables[di->solvid].repo == repo)
906 if (di->solvid >= repo->end)
908 if (!(di->flags & SEARCH_EXTRA))
911 if (di->solvid < -repo->nextra)
918 if (di->solvid < -repo->nextra)
921 Pool *pool = di->repo->pool;
922 if (!(di->flags & SEARCH_ALL_REPOS)
923 || di->repo == pool->repos[pool->nrepos - 1])
926 for (i = 0; i < pool->nrepos; i++)
927 if (di->repo == pool->repos[i])
929 di->repo = pool->repos[i + 1];
930 dataiterator_init(di, di->repo, 0, di->keyname, di->match, di->flags);
934 di->data = repo->repodata - 1;
936 || (di->flags & SEARCH_NO_STORAGE_SOLVABLE))
938 static Id zeroid = 0;
943 if ((di->solvid < 0 && (-1 - di->solvid) >= data->extrastart && (-1 - di->solvid) < (data->extrastart + data->nextra))
944 || (di->solvid >= 0 && di->solvid >= data->start && di->solvid < data->end))
946 dataiterator_newdata(di);
954 di->key = di->data->keys + keyid;
955 di->dp = get_data(di->data, di->key, &di->nextkeydp);
957 di->dp = data_fetch(di->dp, &di->kv, di->key);
962 || dataiterator_match_int(di))
969 dataiterator_skip_attribute(Dataiterator *di)
973 /* This will make the next _step call to retrieve the next field. */
978 dataiterator_skip_solvable(Dataiterator *di)
980 /* We're done with this field. */
982 /* And with solvable data. */
984 /* And with all keys for this repodata and thing. */
985 static Id zeroid = 0;
987 /* And with all repodatas for this thing. */
988 di->data = di->repo->repodata + di->repo->nrepodata - 1;
989 /* Hence the next call to _step will retrieve the next thing. */
993 dataiterator_skip_repo(Dataiterator *di)
995 dataiterator_skip_solvable(di);
996 /* We're done with all solvables and all extra things for this repo. */
997 di->solvid = -1 - di->repo->nextra;
1001 dataiterator_jump_to_solvable(Dataiterator *di, Solvable *s)
1004 /* Simulate us being done with the solvable before the requested one. */
1005 dataiterator_skip_solvable(di);
1006 di->solvid = s - s->repo->pool->solvables;
1011 dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
1014 dataiterator_skip_solvable(di);
1015 di->solvid = repo->start - 1;
1018 /* extend repodata so that it includes solvables p */
1020 repodata_extend(Repodata *data, Id p)
1022 if (data->start == data->end)
1023 data->start = data->end = p;
1026 int old = data->end - data->start;
1027 int new = p - data->end + 1;
1030 data->attrs = sat_extend(data->attrs, old, new, sizeof(Id *), REPODATA_BLOCK);
1031 memset(data->attrs + old, 0, new * sizeof(Id *));
1033 data->incoreoffset = sat_extend(data->incoreoffset, old, new, sizeof(Id), REPODATA_BLOCK);
1034 memset(data->incoreoffset + old, 0, new * sizeof(Id));
1037 if (p < data->start)
1039 int old = data->end - data->start;
1040 int new = data->start - p;
1043 data->attrs = sat_extend_resize(data->attrs, old + new, sizeof(Id *), REPODATA_BLOCK);
1044 memmove(data->attrs + new, data->attrs, old * sizeof(Id *));
1045 memset(data->attrs, 0, new * sizeof(Id *));
1047 data->incoreoffset = sat_extend_resize(data->incoreoffset, old + new, sizeof(Id), REPODATA_BLOCK);
1048 memmove(data->incoreoffset + new, data->incoreoffset, old * sizeof(Id));
1049 memset(data->incoreoffset, 0, new * sizeof(Id));
1055 repodata_extend_extra(Repodata *data, int nextra)
1057 if (nextra <= data->nextra)
1059 if (data->extraattrs)
1061 data->extraattrs = sat_extend(data->extraattrs, data->nextra, nextra - data->nextra, sizeof(Id *), REPODATA_BLOCK);
1062 memset(data->extraattrs + data->nextra, 0, (nextra - data->nextra) * sizeof (Id *));
1064 data->extraoffset = sat_extend(data->extraoffset, data->nextra, nextra - data->nextra, sizeof(Id), REPODATA_BLOCK);
1065 memset(data->extraoffset + data->nextra, 0, (nextra - data->nextra) * sizeof(Id));
1066 data->nextra = nextra;
1070 repodata_extend_block(Repodata *data, Id start, Id num)
1074 if (!data->incoreoffset)
1076 data->incoreoffset = sat_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
1077 data->start = start;
1078 data->end = start + num;
1081 repodata_extend(data, start);
1083 repodata_extend(data, start + num - 1);
1086 /**********************************************************************/
1088 #define REPODATA_ATTRS_BLOCK 63
1089 #define REPODATA_ATTRDATA_BLOCK 1023
1090 #define REPODATA_ATTRIDDATA_BLOCK 63
1093 repodata_insert_keyid(Repodata *data, Id entry, Id keyid, Id val, int overwrite)
1098 if (!data->attrs && entry >= 0)
1100 data->attrs = sat_calloc_block(data->end - data->start, sizeof(Id *),
1103 else if (!data->extraattrs && entry < 0)
1104 data->extraattrs = sat_calloc_block(data->nextra, sizeof(Id *), REPODATA_BLOCK);
1106 ap = data->extraattrs[-1 - entry];
1108 ap = data->attrs[entry];
1112 for (pp = ap; *pp; pp += 2)
1113 /* Determine equality based on the name only, allows us to change
1114 type (when overwrite is set), and makes TYPE_CONSTANT work. */
1115 if (data->keys[*pp].name == data->keys[keyid].name)
1128 ap = sat_extend(ap, i, 3, sizeof(Id), REPODATA_ATTRS_BLOCK);
1130 data->extraattrs[-1 - entry] = ap;
1132 data->attrs[entry] = ap;
1140 repodata_set(Repodata *data, Id entry, Repokey *key, Id val)
1144 /* find key in keys */
1145 for (keyid = 1; keyid < data->nkeys; keyid++)
1146 if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
1148 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
1152 if (keyid == data->nkeys)
1154 /* allocate new key */
1155 data->keys = sat_realloc2(data->keys, data->nkeys + 1, sizeof(Repokey));
1156 data->keys[data->nkeys++] = *key;
1157 if (data->verticaloffset)
1159 data->verticaloffset = sat_realloc2(data->verticaloffset, data->nkeys, sizeof(Id));
1160 data->verticaloffset[data->nkeys - 1] = 0;
1163 repodata_insert_keyid(data, entry, keyid, val, 1);
1167 repodata_set_id(Repodata *data, Id entry, Id keyname, Id id)
1171 key.type = REPOKEY_TYPE_ID;
1173 key.storage = KEY_STORAGE_INCORE;
1174 repodata_set(data, entry, &key, id);
1178 repodata_set_num(Repodata *data, Id entry, Id keyname, unsigned int num)
1182 key.type = REPOKEY_TYPE_NUM;
1184 key.storage = KEY_STORAGE_INCORE;
1185 repodata_set(data, entry, &key, (Id)num);
1189 repodata_set_poolstr(Repodata *data, Id entry, Id keyname, const char *str)
1193 if (data->localpool)
1194 id = stringpool_str2id(&data->spool, str, 1);
1196 id = str2id(data->repo->pool, str, 1);
1198 key.type = REPOKEY_TYPE_ID;
1200 key.storage = KEY_STORAGE_INCORE;
1201 repodata_set(data, entry, &key, id);
1205 repodata_set_constant(Repodata *data, Id entry, Id keyname, unsigned int constant)
1209 key.type = REPOKEY_TYPE_CONSTANT;
1210 key.size = constant;
1211 key.storage = KEY_STORAGE_INCORE;
1212 repodata_set(data, entry, &key, 0);
1216 repodata_set_constantid(Repodata *data, Id entry, Id keyname, Id id)
1220 key.type = REPOKEY_TYPE_CONSTANTID;
1222 key.storage = KEY_STORAGE_INCORE;
1223 repodata_set(data, entry, &key, 0);
1227 repodata_set_void(Repodata *data, Id entry, Id keyname)
1231 key.type = REPOKEY_TYPE_VOID;
1233 key.storage = KEY_STORAGE_INCORE;
1234 repodata_set(data, entry, &key, 0);
1238 repodata_set_str(Repodata *data, Id entry, Id keyname, const char *str)
1243 l = strlen(str) + 1;
1245 key.type = REPOKEY_TYPE_STR;
1247 key.storage = KEY_STORAGE_INCORE;
1248 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1249 memcpy(data->attrdata + data->attrdatalen, str, l);
1250 repodata_set(data, entry, &key, data->attrdatalen);
1251 data->attrdatalen += l;
1255 repoadata_add_array(Repodata *data, Id entry, Id keyname, Id keytype, int entrysize)
1261 pp = data->extraattrs ? data->extraattrs[-1 - entry] : 0;
1263 pp = data->attrs ? data->attrs[entry] : 0;
1265 for (; *pp; pp += 2)
1266 if (data->keys[*pp].name == keyname && data->keys[*pp].type == keytype)
1270 /* not found. allocate new key */
1275 key.storage = KEY_STORAGE_INCORE;
1276 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1277 repodata_set(data, entry, &key, data->attriddatalen);
1281 for (ida = data->attriddata + pp[1]; *ida; ida += entrysize)
1282 oldsize += entrysize;
1283 if (ida + 1 == data->attriddata + data->attriddatalen)
1285 /* this was the last entry, just append it */
1286 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, entrysize, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1287 data->attriddatalen--; /* overwrite terminating 0 */
1291 /* too bad. move to back. */
1292 data->attriddata = sat_extend(data->attriddata, data->attriddatalen, oldsize + entrysize + 1, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
1293 memcpy(data->attriddata + data->attriddatalen, data->attriddata + pp[1], oldsize * sizeof(Id));
1294 pp[1] = data->attriddatalen;
1295 data->attriddatalen += oldsize;
1300 checksumtype2len(Id type)
1304 case REPOKEY_TYPE_MD5:
1306 case REPOKEY_TYPE_SHA1:
1308 case REPOKEY_TYPE_SHA256:
1309 return SIZEOF_SHA256;
1316 repodata_set_bin_checksum(Repodata *data, Id entry, Id keyname, Id type,
1317 const unsigned char *str)
1320 int l = checksumtype2len(type);
1327 key.storage = KEY_STORAGE_INCORE;
1328 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1329 memcpy(data->attrdata + data->attrdatalen, str, l);
1330 repodata_set(data, entry, &key, data->attrdatalen);
1331 data->attrdatalen += l;
1335 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
1338 for (i = 0; i < buflen; i++)
1340 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
1341 : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
1342 : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
1353 buf[i] = (buf[i] << 4) | v;
1360 repodata_set_checksum(Repodata *data, Id entry, Id keyname, Id type,
1363 unsigned char buf[64];
1364 int l = checksumtype2len(type);
1368 if (hexstr2bytes(buf, str, l) != l)
1370 fprintf(stderr, "Invalid hex character in '%s'\n", str);
1373 repodata_set_bin_checksum(data, entry, keyname, type, buf);
1377 repodata_chk2str(Repodata *data, Id type, const unsigned char *buf)
1382 l = checksumtype2len(type);
1385 s = str = pool_alloctmpspace(data->repo->pool, 2 * l + 1);
1386 for (i = 0; i < l; i++)
1388 unsigned char v = buf[i];
1389 unsigned char w = v >> 4;
1390 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1392 *s++ = w >= 10 ? w + ('a' - 10) : w + '0';
1399 repodata_globalize_id(Repodata *data, Id id)
1401 if (!data || !data->localpool)
1403 return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
1407 repodata_add_dirnumnum(Repodata *data, Id entry, Id keyname, Id dir, Id num, Id num2)
1411 fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", entry, dir, num, num2, data->attriddatalen);
1413 repoadata_add_array(data, entry, keyname, REPOKEY_TYPE_DIRNUMNUMARRAY, 3);
1414 data->attriddata[data->attriddatalen++] = dir;
1415 data->attriddata[data->attriddatalen++] = num;
1416 data->attriddata[data->attriddatalen++] = num2;
1417 data->attriddata[data->attriddatalen++] = 0;
1421 repodata_add_dirstr(Repodata *data, Id entry, Id keyname, Id dir, const char *str)
1426 l = strlen(str) + 1;
1427 data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
1428 memcpy(data->attrdata + data->attrdatalen, str, l);
1429 stroff = data->attrdatalen;
1430 data->attrdatalen += l;
1433 fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", entry, dir, str, data->attriddatalen);
1435 repoadata_add_array(data, entry, keyname, REPOKEY_TYPE_DIRSTRARRAY, 2);
1436 data->attriddata[data->attriddatalen++] = dir;
1437 data->attriddata[data->attriddatalen++] = stroff;
1438 data->attriddata[data->attriddatalen++] = 0;
1442 repodata_add_idarray(Repodata *data, Id entry, Id keyname, Id id)
1445 fprintf(stderr, "repodata_add_idarray %d %d (%d)\n", entry, id, data->attriddatalen);
1447 repoadata_add_array(data, entry, keyname, REPOKEY_TYPE_IDARRAY, 1);
1448 data->attriddata[data->attriddatalen++] = id;
1449 data->attriddata[data->attriddatalen++] = 0;
1453 repodata_add_poolstr_array(Repodata *data, Id entry, Id keyname,
1457 if (data->localpool)
1458 id = stringpool_str2id(&data->spool, str, 1);
1460 id = str2id(data->repo->pool, str, 1);
1461 repodata_add_idarray(data, entry, keyname, id);
1465 repodata_merge_attrs(Repodata *data, Id dest, Id src)
1469 || !(keyp = src < 0 ? data->extraattrs[-1 - src] : data->attrs[src]))
1471 for (; *keyp; keyp += 2)
1472 repodata_insert_keyid(data, dest, keyp[0], keyp[1], 0);
1475 /*********************************/
1477 /* unify with repo_write! */
1479 #define EXTDATA_BLOCK 1023
1480 #define SCHEMATA_BLOCK 31
1481 #define SCHEMATADATA_BLOCK 255
1489 data_addid(struct extdata *xd, Id x)
1492 xd->buf = sat_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
1493 dp = xd->buf + xd->len;
1498 *dp++ = (x >> 28) | 128;
1500 *dp++ = (x >> 21) | 128;
1501 *dp++ = (x >> 14) | 128;
1504 *dp++ = (x >> 7) | 128;
1506 xd->len = dp - xd->buf;
1510 data_addideof(struct extdata *xd, Id x, int eof)
1513 x = (x & 63) | ((x & ~63) << 1);
1514 data_addid(xd, (eof ? x: x | 64));
1518 data_addblob(struct extdata *xd, unsigned char *blob, int len)
1520 xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
1521 memcpy(xd->buf + xd->len, blob, len);
1525 /*********************************/
1528 addschema_prepare(Repodata *data, Id *schematacache)
1533 memset(schematacache, 0, 256 * sizeof(Id));
1534 for (i = 0; i < data->nschemata; i++)
1536 for (sp = data->schemadata + data->schemata[i], h = 0; *sp; len++)
1539 schematacache[h] = i + 1;
1541 data->schemadata = sat_extend_resize(data->schemadata, data->schemadatalen, sizeof(Id), SCHEMATADATA_BLOCK);
1542 data->schemata = sat_extend_resize(data->schemata, data->nschemata, sizeof(Id), SCHEMATA_BLOCK);
1546 addschema(Repodata *data, Id *schema, Id *schematacache)
1551 for (sp = schema, len = 0, h = 0; *sp; len++)
1556 cid = schematacache[h];
1560 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
1562 /* cache conflict */
1563 for (cid = 0; cid < data->nschemata; cid++)
1564 if (!memcmp(data->schemadata + data->schemata[cid], schema, len * sizeof(Id)))
1567 /* a new one. make room. */
1568 data->schemadata = sat_extend(data->schemadata, data->schemadatalen, len, sizeof(Id), SCHEMATADATA_BLOCK);
1569 data->schemata = sat_extend(data->schemata, data->nschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
1571 memcpy(data->schemadata + data->schemadatalen, schema, len * sizeof(Id));
1572 data->schemata[data->nschemata] = data->schemadatalen;
1573 data->schemadatalen += len;
1574 schematacache[h] = data->nschemata + 1;
1576 fprintf(stderr, "addschema: new schema\n");
1578 return data->nschemata++;
1583 repodata_internalize(Repodata *data)
1586 Id id, entry, nentry, *ida;
1587 Id schematacache[256];
1588 Id schemaid, *schema, *sp, oldschema, *keyp, *seen;
1589 unsigned char *dp, *ndp;
1590 int newschema, oldcount;
1591 struct extdata newincore;
1592 struct extdata newvincore;
1594 if (!data->attrs && !data->extraattrs)
1597 newvincore.buf = data->vincore;
1598 newvincore.len = data->vincorelen;
1600 schema = sat_malloc2(data->nkeys, sizeof(Id));
1601 seen = sat_malloc2(data->nkeys, sizeof(Id));
1603 /* Merge the data already existing (in data->schemata, ->incoredata and
1604 friends) with the new attributes in data->attrs[]. */
1605 nentry = data->end - data->start;
1606 addschema_prepare(data, schematacache);
1607 memset(&newincore, 0, sizeof(newincore));
1608 data_addid(&newincore, 0);
1611 for (entry = data->extraattrs ? -data->nextra : 0; entry < nentry; entry++)
1613 memset(seen, 0, data->nkeys * sizeof(Id));
1615 dp = entry2data(data, entry);
1616 if (data->incoredata)
1617 dp = data_read_id(dp, &oldschema);
1621 fprintf(stderr, "oldschema %d\n", oldschema);
1622 fprintf(stderr, "schemata %d\n", data->schemata[oldschema]);
1623 fprintf(stderr, "schemadata %p\n", data->schemadata);
1625 /* seen: -1: old data 0: skipped >0: id + 1 */
1628 for (keyp = data->schemadata + data->schemata[oldschema]; *keyp; keyp++)
1632 fprintf(stderr, "Inconsistent old data (key occured twice).\n");
1639 keyp = entry < 0 ? data->extraattrs[-1 - entry] : data->attrs[entry];
1641 for (; *keyp; keyp += 2)
1648 seen[*keyp] = keyp[1] + 1;
1652 /* Ideally we'd like to sort the new schema here, to ensure
1653 schema equality independend of the ordering. We can't do that
1654 yet. For once see below (old ids need to come before new ids).
1655 An additional difficulty is that we also need to move
1656 the values with the keys. */
1657 schemaid = addschema(data, schema, schematacache);
1659 schemaid = oldschema;
1662 /* Now create data blob. We walk through the (possibly new) schema
1663 and either copy over old data, or insert the new. */
1664 /* XXX Here we rely on the fact that the (new) schema has the form
1665 o1 o2 o3 o4 ... | n1 n2 n3 ...
1666 (oX being the old keyids (possibly overwritten), and nX being
1667 the new keyids). This rules out sorting the keyids in order
1668 to ensure a small schema count. */
1670 data->extraoffset[-1 - entry] = newincore.len;
1672 data->incoreoffset[entry] = newincore.len;
1673 data_addid(&newincore, schemaid);
1674 for (keyp = data->schemadata + data->schemata[schemaid]; *keyp; keyp++)
1676 key = data->keys + *keyp;
1680 /* Skip the data associated with this old key. */
1681 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1683 ndp = data_skip(dp, REPOKEY_TYPE_ID);
1684 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
1686 else if (key->storage == KEY_STORAGE_INCORE)
1687 ndp = data_skip(dp, key->type);
1690 if (seen[*keyp] == -1)
1692 /* If this key was an old one _and_ was not overwritten with
1693 a different value copy over the old value (we skipped it
1696 data_addblob(&newincore, dp, ndp - dp);
1699 else if (seen[*keyp])
1701 /* Otherwise we have a new value. Parse it into the internal
1704 unsigned int oldvincorelen = 0;
1707 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1710 oldvincorelen = xd->len;
1712 id = seen[*keyp] - 1;
1715 case REPOKEY_TYPE_VOID:
1716 case REPOKEY_TYPE_CONSTANT:
1717 case REPOKEY_TYPE_CONSTANTID:
1719 case REPOKEY_TYPE_STR:
1720 data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1);
1722 case REPOKEY_TYPE_MD5:
1723 data_addblob(xd, data->attrdata + id, SIZEOF_MD5);
1725 case REPOKEY_TYPE_SHA1:
1726 data_addblob(xd, data->attrdata + id, SIZEOF_SHA1);
1728 case REPOKEY_TYPE_ID:
1729 case REPOKEY_TYPE_NUM:
1730 case REPOKEY_TYPE_DIR:
1733 case REPOKEY_TYPE_IDARRAY:
1734 for (ida = data->attriddata + id; *ida; ida++)
1735 data_addideof(xd, ida[0], ida[1] ? 0 : 1);
1737 case REPOKEY_TYPE_DIRNUMNUMARRAY:
1738 for (ida = data->attriddata + id; *ida; ida += 3)
1740 data_addid(xd, ida[0]);
1741 data_addid(xd, ida[1]);
1742 data_addideof(xd, ida[2], ida[3] ? 0 : 1);
1745 case REPOKEY_TYPE_DIRSTRARRAY:
1746 for (ida = data->attriddata + id; *ida; ida += 2)
1748 data_addideof(xd, ida[0], ida[2] ? 0 : 1);
1749 data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
1753 fprintf(stderr, "don't know how to handle type %d\n", key->type);
1756 if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
1758 /* put offset/len in incore */
1759 data_addid(&newincore, data->lastverticaloffset + oldvincorelen);
1760 oldvincorelen = xd->len - oldvincorelen;
1761 data_addid(&newincore, oldvincorelen);
1766 if (entry < 0 && data->extraattrs[-1 - entry])
1767 sat_free(data->extraattrs[-1 - entry]);
1768 else if (entry >= 0 && data->attrs[entry])
1769 sat_free(data->attrs[entry]);
1774 sat_free(data->incoredata);
1775 data->incoredata = newincore.buf;
1776 data->incoredatalen = newincore.len;
1777 data->incoredatafree = 0;
1779 sat_free(data->vincore);
1780 data->vincore = newvincore.buf;
1781 data->vincorelen = newvincore.len;
1783 data->attrs = sat_free(data->attrs);
1784 data->extraattrs = sat_free(data->extraattrs);
1785 data->attrdata = sat_free(data->attrdata);
1786 data->attriddata = sat_free(data->attriddata);
1787 data->attrdatalen = 0;
1788 data->attriddatalen = 0;
1792 repodata_str2dir(Repodata *data, const char *dir, int create)
1798 while (*dir == '/' && dir[1] == '/')
1800 if (*dir == '/' && !dir[1])
1804 dire = strchrnul(dir, '/');
1805 if (data->localpool)
1806 id = stringpool_strn2id(&data->spool, dir, dire - dir, create);
1808 id = strn2id(data->repo->pool, dir, dire - dir, create);
1811 parent = dirpool_add_dir(&data->dirpool, parent, id, create);
1824 repodata_dir2str(Repodata *data, Id did, const char *suf)
1826 Pool *pool = data->repo->pool;
1833 return suf ? suf : "";
1837 comp = dirpool_compid(&data->dirpool, parent);
1838 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
1840 parent = dirpool_parent(&data->dirpool, parent);
1845 l += strlen(suf) + 1;
1846 p = pool_alloctmpspace(pool, l + 1) + l;
1857 comp = dirpool_compid(&data->dirpool, parent);
1858 comps = stringpool_id2str(data->localpool ? &data->spool : &pool->ss, comp);
1861 strncpy(p, comps, l);
1862 parent = dirpool_parent(&data->dirpool, parent);
1870 repodata_compress_page(unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max)
1872 return compress_buf(page, len, cpage, max);
1875 #define SOLV_ERROR_EOF 3
1877 static inline unsigned int
1883 for (i = 0; i < 4; i++)
1893 #define SOLV_ERROR_EOF 3
1894 #define SOLV_ERROR_CORRUPT 6
1896 /* Try to either setup on-demand paging (using FP as backing
1897 file), or in case that doesn't work (FP not seekable) slurps in
1898 all pages and deactivates paging. */
1900 repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int blobsz)
1902 FILE *fp = data->fp;
1903 unsigned int npages;
1905 unsigned int can_seek;
1907 unsigned char buf[BLOB_PAGESIZE];
1909 if (pagesz != BLOB_PAGESIZE)
1911 /* We could handle this by slurping in everything. */
1912 data->error = SOLV_ERROR_CORRUPT;
1916 if ((cur_file_ofs = ftell(fp)) < 0)
1920 data->pagefd = dup(fileno(fp));
1921 if (data->pagefd == -1)
1925 fprintf (stderr, "can %sseek\n", can_seek ? "" : "NOT ");
1927 npages = (blobsz + BLOB_PAGESIZE - 1) / BLOB_PAGESIZE;
1929 data->num_pages = npages;
1930 data->pages = sat_malloc2(npages, sizeof(data->pages[0]));
1932 /* If we can't seek on our input we have to slurp in everything. */
1934 data->blob_store = sat_malloc(npages * BLOB_PAGESIZE);
1935 for (i = 0; i < npages; i++)
1937 unsigned int in_len = read_u32(fp);
1938 unsigned int compressed = in_len & 1;
1939 Attrblobpage *p = data->pages + i;
1942 fprintf (stderr, "page %d: len %d (%scompressed)\n",
1943 i, in_len, compressed ? "" : "not ");
1949 p->file_offset = cur_file_ofs;
1950 p->file_size = in_len * 2 + compressed;
1951 if (fseek(fp, in_len, SEEK_CUR) < 0)
1954 fprintf (stderr, "can't seek after we thought we can\n");
1955 /* We can't fall back to non-seeking behaviour as we already
1956 read over some data pages without storing them away. */
1957 data->error = SOLV_ERROR_EOF;
1958 close(data->pagefd);
1962 cur_file_ofs += in_len;
1966 unsigned int out_len;
1967 void *dest = data->blob_store + i * BLOB_PAGESIZE;
1968 p->mapped_at = i * BLOB_PAGESIZE;
1971 /* We can't seek, so suck everything in. */
1972 if (fread(compressed ? buf : dest, in_len, 1, fp) != 1)
1975 data->error = SOLV_ERROR_EOF;
1980 out_len = unchecked_decompress_buf(buf, in_len, dest, BLOB_PAGESIZE);
1981 if (out_len != BLOB_PAGESIZE && i < npages - 1)
1983 data->error = SOLV_ERROR_CORRUPT;
1992 repodata_disable_paging(Repodata *data)
1994 if (maybe_load_repodata(data, 0)
1996 load_page_range (data, 0, data->num_pages - 1);
1999 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: