/*
- * Copyright (c) 2007-2008, Novell Inc.
+ * Copyright (c) 2007-2012, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
/*
* repopage.c
*
- * Pageing and compression functions for the vertical repository data
- *
+ * Paging and compression functions for the vertical repository data.
+ * Vertical data is grouped by key, normal data is grouped by solvable.
+ * This makes searching for a string in vertical data fast as there's
+ * no need to skip over data if keys we're not interested in.
+ *
+ * The vertical data is split into pages, each page is compressed with a fast
+ * compression algorithm. These pages are read in on demand, not recently used
+ * pages automatically get dropped.
*/
#define _XOPEN_SOURCE 500
#include <sys/types.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
+#include <fcntl.h>
#include <time.h>
+#ifdef _WIN32
+ #include <windows.h>
+ #include <fileapi.h>
+ #include <io.h>
+#endif
+
#include "repo.h"
#include "repopage.h"
#define BLOCK_SIZE (65536*1)
#if BLOCK_SIZE <= 65536
-typedef __uint16_t Ref;
+typedef uint16_t Ref;
#else
-typedef __uint32_t Ref;
+typedef uint32_t Ref;
#endif
/*
The format is tailored for fast decompression (i.e. only byte based),
and skewed to ASCII content (highest bit often not set):
-
+
a 0LLLLLLL
- self-describing ASCII character hex L
b 100lllll <l+1 bytes>
compress_buf(const unsigned char *in, unsigned int in_len,
unsigned char *out, unsigned int out_len)
{
- unsigned int oo = 0; //out-offset
- unsigned int io = 0; //in-offset
+ unsigned int oo = 0; /* out-offset */
+ unsigned int io = 0; /* in-offset */
#define HS (65536)
Ref htab[HS];
Ref hnext[BLOCK_SIZE];
- memset (htab, -1, sizeof (htab));
- memset (hnext, -1, sizeof (hnext));
unsigned int litofs = 0;
+ memset(htab, -1, sizeof (htab));
+ memset(hnext, -1, sizeof (hnext));
while (io + 2 < in_len)
{
/* Search for a match of the string starting at IN, we have at
}
for (; try != -1 && tries < 12; tries++)
{
- //assert (mlen >= 2);
- //assert (io + mlen < in_len);
+ /* assert(mlen >= 2); */
+ /* assert(io + mlen < in_len); */
/* Try a match starting from [io] with the strings at [try].
That's only sensible if TRY actually is before IO (can happen
with uninit hash table). If we have a previous match already
if (try < io && in[try + mlen] == in[io + mlen])
{
unsigned int this_len, this_ofs;
- if (memcmp (in + try, in + io, mlen))
+ if (memcmp(in + try, in + io, mlen))
goto no_match;
this_len = mlen + 1;
/* Now try extending the match by more characters. */
#if 0
unsigned int testi;
for (testi = 0; testi < this_len; testi++)
- assert (in[try + testi] == in[io + testi]);
+ assert(in[try + testi] == in[io + testi]);
#endif
this_ofs = (io - try) - 1;
/*if (this_ofs > 65535)
goto no_match; */
#if 0
- assert (this_len >= 2);
- assert (this_len >= mlen);
- assert (this_len > mlen || (this_len == mlen && this_ofs > mofs));
+ assert(this_len >= 2);
+ assert(this_len >= mlen);
+ assert(this_len > mlen || (this_len == mlen && this_ofs > mofs));
#endif
mlen = this_len, mofs = this_ofs;
/* If our match extends up to the end of input, no next
match_done:
if (mlen)
{
- //fprintf (stderr, "%d %d\n", mlen, mofs);
+ /*fprintf(stderr, "%d %d\n", mlen, mofs);*/
if (mlen == 2 && (litofs || mofs >= 1024))
mlen = 0;
/*else if (mofs >= 65536)
{
if (litofs)
{
+ unsigned litlen;
litofs--;
- unsigned litlen = io - litofs;
- //fprintf (stderr, "lit: %d\n", litlen);
+ litlen = io - litofs;
+ /* fprintf(stderr, "lit: %d\n", litlen); */
while (litlen)
{
unsigned int easy_sz;
{
if (oo + easy_sz >= out_len)
return 0;
- memcpy (out + oo, in + litofs, easy_sz);
+ memcpy(out + oo, in + litofs, easy_sz);
litofs += easy_sz;
oo += easy_sz;
litlen -= easy_sz;
if (oo + 1 + 32 >= out_len)
return 0;
out[oo++] = 0x80 | 31;
- memcpy (out + oo, in + litofs, 32);
+ memcpy(out + oo, in + litofs, 32);
oo += 32;
litofs += 32;
litlen -= 32;
litofs = 0;
}
- //fprintf (stderr, "ref: %d @ %d\n", mlen, mofs);
+ /* fprintf(stderr, "ref: %d @ %d\n", mlen, mofs); */
if (mlen >= 2 && mlen <= 9 && mofs < 1024)
{
}
else if (mofs >= 65536)
{
- assert (mlen >= 5 && mlen < 2048 + 5);
+ assert(mlen >= 5 && mlen < 2048 + 5);
if (oo + 5 >= out_len)
return 0;
out[oo++] = 0xf8 | ((mlen - 5) >> 8);
}
else if (mlen >= 3 && mlen <= 18)
{
- assert (mofs < 65536);
+ assert(mofs < 65536);
if (oo + 3 >= out_len)
return 0;
out[oo++] = 0xe0 | (mlen - 3);
}
else
{
- assert (mlen >= 19 && mlen <= 4095 + 19 && mofs < 65536);
+ assert(mlen >= 19 && mlen <= 4095 + 19 && mofs < 65536);
if (oo + 4 >= out_len)
return 0;
out[oo++] = 0xf0 | ((mlen - 19) >> 8);
io = in_len;
if (litofs)
{
+ unsigned litlen;
litofs--;
- unsigned litlen = io - litofs;
- //fprintf (stderr, "lit: %d\n", litlen);
+ litlen = io - litofs;
+ /* fprintf(stderr, "lit: %d\n", litlen); */
while (litlen)
{
unsigned int easy_sz;
{
if (oo + easy_sz >= out_len)
return 0;
- memcpy (out + oo, in + litofs, easy_sz);
+ memcpy(out + oo, in + litofs, easy_sz);
litofs += easy_sz;
oo += easy_sz;
litlen -= easy_sz;
if (oo + 1 + 32 >= out_len)
return 0;
out[oo++] = 0x80 | 31;
- memcpy (out + oo, in + litofs, 32);
+ memcpy(out + oo, in + litofs, 32);
oo += 32;
litofs += 32;
litlen -= 32;
}
}
- litofs = 0;
}
return oo;
}
case 2: case 3:
case 4: case 5:
case 6: case 7:
- //a 0LLLLLLL
- //fprintf (stderr, "lit: 1\n");
+ /* a 0LLLLLLL */
+ /* fprintf (stderr, "lit: 1\n"); */
*out++ = first;
continue;
case 8: case 9:
- //b 100lllll <l+1 bytes>
+ /* b 100lllll <l+1 bytes> */
{
unsigned int l = first & 31;
- //fprintf (stderr, "lit: %d\n", l);
+ /* fprintf (stderr, "lit: %d\n", l); */
do
*out++ = *in++;
while (l--);
continue;
}
case 10: case 11:
- //c 101oolll <8o>
+ /* c 101oolll <8o> */
{
o = first & (3 << 3);
o = (o << 5) | *in++;
break;
}
case 12: case 13:
- //d 110lllll <8o>
+ /* d 110lllll <8o> */
{
o = *in++;
first = (first & 31) + 10;
break;
}
case 14:
- // e 1110llll <8o> <8o>
+ /* e 1110llll <8o> <8o> */
{
o = in[0] | (in[1] << 8);
in += 2;
break;
}
case 15:
- //f1 1111llll <8o> <8o> <8l>
- //f2 11110lll <8o> <8o> <8l>
- // g 11111lll <8o> <8o> <8o> <8l>
+ /* f1 1111llll <8o> <8o> <8l> */
+ /* f2 11110lll <8o> <8o> <8l> */
+ /* g 11111lll <8o> <8o> <8o> <8l> */
{
first = first & 15;
if (first >= 8)
break;
}
}
- //fprintf (stderr, "ref: %d @ %d\n", first, o);
+ /* fprintf(stderr, "ref: %d @ %d\n", first, o); */
o++;
o = -o;
#if 0
/**********************************************************************/
+void repopagestore_init(Repopagestore *store)
+{
+ memset(store, 0, sizeof(*store));
+ store->pagefd = -1;
+}
+
+void repopagestore_free(Repopagestore *store)
+{
+ store->blob_store = solv_free(store->blob_store);
+ store->file_pages = solv_free(store->file_pages);
+ store->mapped_at = solv_free(store->mapped_at);
+ store->mapped = solv_free(store->mapped);
+ if (store->pagefd != -1)
+ close(store->pagefd);
+ store->pagefd = -1;
+}
+
+
+/**********************************************************************/
+
unsigned char *
-repodata_load_page_range(Repodata *data, unsigned int pstart, unsigned int pend)
+repopagestore_load_page_range(Repopagestore *store, unsigned int pstart, unsigned int pend)
{
/* Make sure all pages from PSTART to PEND (inclusive) are loaded,
and are consecutive. Return a pointer to the mapping of PSTART. */
- unsigned char buf[BLOB_PAGESIZE];
- unsigned int i;
+ unsigned char buf[REPOPAGE_BLOBSIZE];
+ unsigned int i, best, pnum;
- /* Quick check in case all pages are there already and consecutive. */
- for (i = pstart; i <= pend; i++)
- if (data->pages[i].mapped_at == -1
- || (i > pstart
- && data->pages[i].mapped_at
- != data->pages[i-1].mapped_at + BLOB_PAGESIZE))
- break;
- if (i > pend)
- return data->blob_store + data->pages[pstart].mapped_at;
+ if (pstart == pend)
+ {
+ /* Quick check in case the requested page is already mapped */
+ if (store->mapped_at[pstart] != -1)
+ return store->blob_store + store->mapped_at[pstart];
+ }
+ else
+ {
+ /* Quick check in case all pages are already mapped and consecutive. */
+ for (pnum = pstart; pnum <= pend; pnum++)
+ if (store->mapped_at[pnum] == -1
+ || (pnum > pstart
+ && store->mapped_at[pnum]
+ != store->mapped_at[pnum-1] + REPOPAGE_BLOBSIZE))
+ break;
+ if (pnum > pend)
+ return store->blob_store + store->mapped_at[pstart];
+ }
+
+ if (store->pagefd == -1 || !store->file_pages)
+ return 0; /* no backing file */
- if (data->pagefd == -1)
- return 0;
+#ifdef DEBUG_PAGING
+ fprintf(stderr, "PAGE: want %d pages starting at %d\n", pend - pstart + 1, pstart);
+#endif
/* Ensure that we can map the numbers of pages we need at all. */
- if (pend - pstart + 1 > data->ncanmap)
+ if (pend - pstart + 1 > store->nmapped)
{
- unsigned int oldcan = data->ncanmap;
- data->ncanmap = pend - pstart + 1;
- if (data->ncanmap < 4)
- data->ncanmap = 4;
- data->mapped = sat_realloc2(data->mapped, data->ncanmap, sizeof(data->mapped[0]));
- memset (data->mapped + oldcan, 0, (data->ncanmap - oldcan) * sizeof (data->mapped[0]));
- data->blob_store = sat_realloc2(data->blob_store, data->ncanmap, BLOB_PAGESIZE);
+ unsigned int oldcan = store->nmapped;
+ store->nmapped = pend - pstart + 1;
+ if (store->nmapped < 4)
+ store->nmapped = 4;
+ store->mapped = solv_realloc2(store->mapped, store->nmapped, sizeof(store->mapped[0]));
+ for (i = oldcan; i < store->nmapped; i++)
+ store->mapped[i] = -1;
+ store->blob_store = solv_realloc2(store->blob_store, store->nmapped, REPOPAGE_BLOBSIZE);
#ifdef DEBUG_PAGING
- fprintf (stderr, "PAGE: can map %d pages\n", data->ncanmap);
+ fprintf(stderr, "PAGE: can map %d pages\n", store->nmapped);
#endif
}
- /* Now search for "cheap" space in our store. Space is cheap if it's either
- free (very cheap) or contains pages we search for anyway. */
-
- /* Setup cost array. */
- unsigned int cost[data->ncanmap];
- for (i = 0; i < data->ncanmap; i++)
+ if (store->mapped_at[pstart] != -1)
{
- unsigned int pnum = data->mapped[i];
- if (pnum == 0)
- cost[i] = 0;
- else
- {
- pnum--;
- Attrblobpage *p = data->pages + pnum;
- assert (p->mapped_at != -1);
- if (pnum >= pstart && pnum <= pend)
- cost[i] = 1;
- else
- cost[i] = 3;
- }
+ /* assume forward search */
+ best = store->mapped_at[pstart] / REPOPAGE_BLOBSIZE;
+ if (best + (pend - pstart) >= store->nmapped)
+ best = 0;
}
-
- /* And search for cheapest space. */
- unsigned int best_cost = -1;
- unsigned int best = 0;
- unsigned int same_cost = 0;
- for (i = 0; i + pend - pstart < data->ncanmap; i++)
+ else if (store->mapped_at[pend] != -1)
+ {
+ /* assume backward search */
+ best = store->mapped_at[pend] / REPOPAGE_BLOBSIZE;
+ if (best < pend - pstart)
+ best = store->nmapped - 1;
+ best -= pend - pstart;
+ }
+ else
{
- unsigned int c = cost[i];
- unsigned int j;
- for (j = 0; j < pend - pstart + 1; j++)
- c += cost[i+j];
- if (c < best_cost)
- best_cost = c, best = i;
- else if (c == best_cost)
- same_cost++;
- /* A null cost won't become better. */
- if (c == 0)
- break;
+ /* choose some "random" location to avoid thrashing */
+ best = (pstart + store->rr_counter++) % (store->nmapped - pend + pstart);
}
- /* If all places have the same cost we would thrash on slot 0. Avoid
- this by doing a round-robin strategy in this case. */
- if (same_cost == data->ncanmap - pend + pstart - 1)
- best = data->rr_counter++ % (data->ncanmap - pend + pstart);
/* So we want to map our pages from [best] to [best+pend-pstart].
Use a very simple strategy, which doesn't make the best use of
our resources, but works. Throw away all pages in that range
- (even ours) then copy around ours (in case they were outside the
- range) or read them in. */
- for (i = best; i < best + pend - pstart + 1; i++)
+ (even ours) then copy around ours or read them in. */
+ for (i = best, pnum = pstart; pnum <= pend; i++, pnum++)
{
- unsigned int pnum = data->mapped[i];
- if (pnum--
- /* If this page is exactly at the right place already,
- no need to evict it. */
- && pnum != pstart + i - best)
+ unsigned int pnum_mapped_at;
+ unsigned int oldpnum = store->mapped[i];
+ if (oldpnum != -1)
{
+ if (oldpnum == pnum)
+ continue; /* already have the correct page */
/* Evict this page. */
#ifdef DEBUG_PAGING
- fprintf (stderr, "PAGE: evict page %d from %d\n", pnum, i);
+ fprintf(stderr, "PAGE: evict page %d from %d\n", oldpnum, i);
#endif
- cost[i] = 0;
- data->mapped[i] = 0;
- data->pages[pnum].mapped_at = -1;
+ store->mapped[i] = -1;
+ store->mapped_at[oldpnum] = -1;
+ }
+ /* check if we can copy the correct content (before it gets evicted) */
+ pnum_mapped_at = store->mapped_at[pnum];
+ if (pnum_mapped_at != -1 && pnum_mapped_at != i * REPOPAGE_BLOBSIZE)
+ {
+ void *dest = store->blob_store + i * REPOPAGE_BLOBSIZE;
+#ifdef DEBUG_PAGING
+ fprintf(stderr, "PAGECOPY: %d from %d to %d\n", pnum, pnum_mapped_at / REPOPAGE_BLOBSIZE, i);
+#endif
+ memcpy(dest, store->blob_store + pnum_mapped_at, REPOPAGE_BLOBSIZE);
+ store->mapped[pnum_mapped_at / REPOPAGE_BLOBSIZE] = -1;
+ store->mapped[i] = pnum;
+ store->mapped_at[pnum] = i * REPOPAGE_BLOBSIZE;
}
}
- /* Everything is free now. Read in the pages we want. */
- for (i = pstart; i <= pend; i++)
+ /* Everything is free now. Read in or copy the pages we want. */
+ for (i = best, pnum = pstart; pnum <= pend; i++, pnum++)
{
- Attrblobpage *p = data->pages + i;
- unsigned int pnum = i - pstart + best;
- void *dest = data->blob_store + pnum * BLOB_PAGESIZE;
- if (p->mapped_at != -1)
+ void *dest = store->blob_store + i * REPOPAGE_BLOBSIZE;
+ if (store->mapped_at[pnum] != -1)
{
- if (p->mapped_at != pnum * BLOB_PAGESIZE)
+ unsigned int pnum_mapped_at = store->mapped_at[pnum];
+ if (pnum_mapped_at != i * REPOPAGE_BLOBSIZE)
{
#ifdef DEBUG_PAGING
- fprintf (stderr, "PAGECOPY: %d to %d\n", i, pnum);
+ fprintf(stderr, "PAGECOPY: %d from %d to %d\n", pnum, pnum_mapped_at / REPOPAGE_BLOBSIZE, i);
#endif
/* Still mapped somewhere else, so just copy it from there. */
- memcpy (dest, data->blob_store + p->mapped_at, BLOB_PAGESIZE);
- data->mapped[p->mapped_at / BLOB_PAGESIZE] = 0;
+ memcpy(dest, store->blob_store + pnum_mapped_at, REPOPAGE_BLOBSIZE);
+ store->mapped[pnum_mapped_at / REPOPAGE_BLOBSIZE] = -1;
}
}
else
{
- unsigned int in_len = p->file_size;
+ Attrblobpage *p = store->file_pages + pnum;
+ unsigned int in_len = p->page_size;
unsigned int compressed = in_len & 1;
in_len >>= 1;
#ifdef DEBUG_PAGING
- fprintf (stderr, "PAGEIN: %d to %d", i, pnum);
+ fprintf(stderr, "PAGEIN: %d to %d", pnum, i);
#endif
- if (pread(data->pagefd, compressed ? buf : dest, in_len, p->file_offset) != in_len)
+#ifndef _WIN32
+ if (pread(store->pagefd, compressed ? buf : dest, in_len, store->file_offset + p->page_offset) != in_len)
{
- perror ("mapping pread");
+ perror("mapping pread");
return 0;
}
+#else
+ DWORD read_len;
+ OVERLAPPED ovlp = {0};
+ ovlp.Offset = store->file_offset + p->page_offset;
+ if (!ReadFile((HANDLE) _get_osfhandle(store->pagefd), compressed ? buf : dest, in_len, &read_len, &ovlp) || read_len != in_len)
+ {
+ perror("mapping ReadFile");
+ return 0;
+ }
+#endif
if (compressed)
{
unsigned int out_len;
- out_len = unchecked_decompress_buf(buf, in_len,
- dest, BLOB_PAGESIZE);
- if (out_len != BLOB_PAGESIZE && i < data->num_pages - 1)
+ out_len = unchecked_decompress_buf(buf, in_len, dest, REPOPAGE_BLOBSIZE);
+ if (out_len != REPOPAGE_BLOBSIZE && pnum < store->num_pages - 1)
{
+#ifdef DEBUG_PAGING
fprintf(stderr, "can't decompress\n");
+#endif
return 0;
}
#ifdef DEBUG_PAGING
- fprintf (stderr, " (expand %d to %d)", in_len, out_len);
+ fprintf(stderr, " (expand %d to %d)", in_len, out_len);
#endif
}
#ifdef DEBUG_PAGING
- fprintf (stderr, "\n");
+ fprintf(stderr, "\n");
#endif
}
- p->mapped_at = pnum * BLOB_PAGESIZE;
- data->mapped[pnum] = i + 1;
- }
- return data->blob_store + best * BLOB_PAGESIZE;
-}
-
-unsigned char *
-repodata_fetch_vertical(Repodata *data, Repokey *key, Id off, Id len)
-{
- unsigned char *dp;
- if (!len)
- return 0;
- if (off >= data->lastverticaloffset)
- {
- off -= data->lastverticaloffset;
- if (off + len > data->vincorelen)
- return 0;
- return data->vincore + off;
+ store->mapped_at[pnum] = i * REPOPAGE_BLOBSIZE;
+ store->mapped[i] = pnum;
}
- if (off + len > key->size)
- return 0;
- /* we now have the offset, go into vertical */
- off += data->verticaloffset[key - data->keys];
- /* fprintf(stderr, "key %d page %d\n", key->name, off / BLOB_PAGESIZE); */
- dp = repodata_load_page_range(data, off / BLOB_PAGESIZE, (off + len - 1) / BLOB_PAGESIZE);
- if (dp)
- dp += off % BLOB_PAGESIZE;
- return dp;
+ return store->blob_store + best * REPOPAGE_BLOBSIZE;
}
unsigned int
-repodata_compress_page(unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max)
+repopagestore_compress_page(unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max)
{
return compress_buf(page, len, cpage, max);
}
read_u32(FILE *fp)
{
int c, i;
- unsigned int x = 0;
+ unsigned int x = 0;
- for (i = 0; i < 4; i++)
- {
+ for (i = 0; i < 4; i++)
+ {
c = getc(fp);
- if (c == EOF)
+ if (c == EOF)
return 0;
- x = (x << 8) | c;
- }
+ x = (x << 8) | c;
+ }
return x;
}
/* Try to either setup on-demand paging (using FP as backing
file), or in case that doesn't work (FP not seekable) slurps in
all pages and deactivates paging. */
-void
-repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int blobsz)
+int
+repopagestore_read_or_setup_pages(Repopagestore *store, FILE *fp, unsigned int pagesz, unsigned int blobsz)
{
- FILE *fp = data->fp;
unsigned int npages;
unsigned int i;
unsigned int can_seek;
- long cur_file_ofs;
- unsigned char buf[BLOB_PAGESIZE];
+ unsigned int cur_page_ofs;
+ unsigned char buf[REPOPAGE_BLOBSIZE];
- if (pagesz != BLOB_PAGESIZE)
+ if (pagesz != REPOPAGE_BLOBSIZE)
{
/* We could handle this by slurping in everything. */
- data->error = SOLV_ERROR_CORRUPT;
- return;
+ return SOLV_ERROR_CORRUPT;
}
can_seek = 1;
- if ((cur_file_ofs = ftell(fp)) < 0)
+ if ((store->file_offset = ftell(fp)) < 0)
can_seek = 0;
clearerr(fp);
if (can_seek)
- data->pagefd = dup(fileno(fp));
- if (data->pagefd == -1)
+ store->pagefd = dup(fileno(fp));
+ if (store->pagefd == -1)
can_seek = 0;
+ else
+ solv_setcloexec(store->pagefd, 1);
#ifdef DEBUG_PAGING
- fprintf (stderr, "can %sseek\n", can_seek ? "" : "NOT ");
+ fprintf(stderr, "can %sseek\n", can_seek ? "" : "NOT ");
#endif
- npages = (blobsz + BLOB_PAGESIZE - 1) / BLOB_PAGESIZE;
+ npages = (blobsz + REPOPAGE_BLOBSIZE - 1) / REPOPAGE_BLOBSIZE;
- data->num_pages = npages;
- data->pages = sat_malloc2(npages, sizeof(data->pages[0]));
+ store->num_pages = npages;
+ store->mapped_at = solv_malloc2(npages, sizeof(*store->mapped_at));
- /* If we can't seek on our input we have to slurp in everything. */
- if (!can_seek)
- data->blob_store = sat_malloc(npages * BLOB_PAGESIZE);
+ /* If we can't seek on our input we have to slurp in everything.
+ * Otherwise set up file_pages containing offest/length of the
+ * pages */
+ if (can_seek)
+ store->file_pages = solv_malloc2(npages, sizeof(*store->file_pages));
+ else
+ store->blob_store = solv_malloc2(npages, REPOPAGE_BLOBSIZE);
+ cur_page_ofs = 0;
for (i = 0; i < npages; i++)
{
unsigned int in_len = read_u32(fp);
unsigned int compressed = in_len & 1;
- Attrblobpage *p = data->pages + i;
in_len >>= 1;
#ifdef DEBUG_PAGING
- fprintf (stderr, "page %d: len %d (%scompressed)\n",
+ fprintf(stderr, "page %d: len %d (%scompressed)\n",
i, in_len, compressed ? "" : "not ");
#endif
if (can_seek)
{
- cur_file_ofs += 4;
- p->mapped_at = -1;
- p->file_offset = cur_file_ofs;
- p->file_size = in_len * 2 + compressed;
+ Attrblobpage *p = store->file_pages + i;
+ cur_page_ofs += 4;
+ store->mapped_at[i] = -1; /* not mapped yet */
+ p->page_offset = cur_page_ofs;
+ p->page_size = in_len * 2 + compressed;
if (fseek(fp, in_len, SEEK_CUR) < 0)
{
- perror ("fseek");
- fprintf (stderr, "can't seek after we thought we can\n");
/* We can't fall back to non-seeking behaviour as we already
read over some data pages without storing them away. */
- data->error = SOLV_ERROR_EOF;
- close(data->pagefd);
- data->pagefd = -1;
- return;
+ close(store->pagefd);
+ store->pagefd = -1;
+ return SOLV_ERROR_EOF;
}
- cur_file_ofs += in_len;
+ cur_page_ofs += in_len;
}
else
{
unsigned int out_len;
- void *dest = data->blob_store + i * BLOB_PAGESIZE;
- p->mapped_at = i * BLOB_PAGESIZE;
- p->file_offset = 0;
- p->file_size = 0;
+ void *dest = store->blob_store + i * REPOPAGE_BLOBSIZE;
+ store->mapped_at[i] = i * REPOPAGE_BLOBSIZE;
/* We can't seek, so suck everything in. */
if (fread(compressed ? buf : dest, in_len, 1, fp) != 1)
{
perror("fread");
- data->error = SOLV_ERROR_EOF;
- return;
+ return SOLV_ERROR_EOF;
}
if (compressed)
{
- out_len = unchecked_decompress_buf(buf, in_len, dest, BLOB_PAGESIZE);
- if (out_len != BLOB_PAGESIZE && i < npages - 1)
+ out_len = unchecked_decompress_buf(buf, in_len, dest, REPOPAGE_BLOBSIZE);
+ if (out_len != REPOPAGE_BLOBSIZE && i < npages - 1)
{
- data->error = SOLV_ERROR_CORRUPT;
- return;
+ return SOLV_ERROR_CORRUPT;
}
}
}
}
+ return 0;
}
+void
+repopagestore_disable_paging(Repopagestore *store)
+{
+ if (store->num_pages)
+ repopagestore_load_page_range(store, 0, store->num_pages - 1);
+}
#ifdef STANDALONE
static void
-transfer_file (FILE * from, FILE * to, int compress)
+transfer_file(FILE * from, FILE * to, int compress)
{
unsigned char inb[BLOCK_SIZE];
unsigned char outb[BLOCK_SIZE];
unsigned int in_len, out_len;
if (compress)
{
- in_len = fread (inb, 1, BLOCK_SIZE, from);
+ in_len = fread(inb, 1, BLOCK_SIZE, from);
if (in_len)
{
unsigned char *b = outb;
- out_len = compress_buf (inb, in_len, outb, sizeof (outb));
+ out_len = compress_buf(inb, in_len, outb, sizeof (outb));
if (!out_len)
b = inb, out_len = in_len;
- if (fwrite (&out_len, sizeof (out_len), 1, to) != 1)
+ if (fwrite(&out_len, sizeof (out_len), 1, to) != 1)
{
- perror ("write size");
+ perror("write size");
exit (1);
}
- if (fwrite (b, out_len, 1, to) != 1)
+ if (fwrite(b, out_len, 1, to) != 1)
{
- perror ("write data");
+ perror("write data");
exit (1);
}
}
}
else
{
- if (fread (&in_len, sizeof (in_len), 1, from) != 1)
+ if (fread(&in_len, sizeof(in_len), 1, from) != 1)
{
- if (feof (from))
+ if (feof(from))
return;
- perror ("can't read size");
- exit (1);
+ perror("can't read size");
+ exit(1);
}
- if (fread (inb, in_len, 1, from) != 1)
+ if (fread(inb, in_len, 1, from) != 1)
{
- perror ("can't read data");
- exit (1);
+ perror("can't read data");
+ exit(1);
}
out_len =
- unchecked_decompress_buf (inb, in_len, outb, sizeof (outb));
- if (fwrite (outb, out_len, 1, to) != 1)
+ unchecked_decompress_buf(inb, in_len, outb, sizeof(outb));
+ if (fwrite(outb, out_len, 1, to) != 1)
{
- perror ("can't write output");
- exit (1);
+ perror("can't write output");
+ exit(1);
}
}
}
/* Just for benchmarking purposes. */
static void
-dumb_memcpy (void *dest, const void *src, unsigned int len)
+dumb_memcpy(void *dest, const void *src, unsigned int len)
{
char *d = dest;
const char *s = src;
}
static void
-benchmark (FILE * from)
+benchmark(FILE * from)
{
unsigned char inb[BLOCK_SIZE];
unsigned char outb[BLOCK_SIZE];
- unsigned int in_len = fread (inb, 1, BLOCK_SIZE, from);
+ unsigned int in_len = fread(inb, 1, BLOCK_SIZE, from);
unsigned int out_len;
if (!in_len)
{
- perror ("can't read from input");
- exit (1);
+ perror("can't read from input");
+ exit(1);
}
unsigned int calib_loop;
#if 0
calib_loop = 1;
per_loop = 0;
- start = clock ();
- while ((clock () - start) < CLOCKS_PER_SEC / 4)
+ start = clock();
+ while ((clock() - start) < CLOCKS_PER_SEC / 4)
{
calib_loop *= 2;
for (i = 0; i < calib_loop; i++)
- dumb_memcpy (outb, inb, in_len);
+ dumb_memcpy(outb, inb, in_len);
per_loop += calib_loop;
}
- fprintf (stderr, "memcpy:\nCalibrated to %d iterations per loop\n",
+ fprintf(stderr, "memcpy:\nCalibrated to %d iterations per loop\n",
per_loop);
- start = clock ();
+ start = clock();
for (i = 0; i < 10; i++)
for (j = 0; j < per_loop; j++)
- dumb_memcpy (outb, inb, in_len);
- end = clock ();
+ dumb_memcpy(outb, inb, in_len);
+ end = clock();
seconds = (end - start) / (float) CLOCKS_PER_SEC;
- fprintf (stderr, "%.2f seconds == %.2f MB/s\n", seconds,
+ fprintf(stderr, "%.2f seconds == %.2f MB/s\n", seconds,
((long long) in_len * per_loop * 10) / (1024 * 1024 * seconds));
#endif
calib_loop = 1;
per_loop = 0;
- start = clock ();
- while ((clock () - start) < CLOCKS_PER_SEC / 4)
+ start = clock();
+ while ((clock() - start) < CLOCKS_PER_SEC / 4)
{
calib_loop *= 2;
for (i = 0; i < calib_loop; i++)
- compress_buf(inb, in_len, outb, sizeof (outb));
+ compress_buf(inb, in_len, outb, sizeof(outb));
per_loop += calib_loop;
}
fprintf(stderr, "compression:\nCalibrated to %d iterations per loop\n",
per_loop);
- start = clock ();
+ start = clock();
for (i = 0; i < 10; i++)
for (j = 0; j < per_loop; j++)
- compress_buf (inb, in_len, outb, sizeof (outb));
- end = clock ();
+ compress_buf(inb, in_len, outb, sizeof(outb));
+ end = clock();
seconds = (end - start) / (float) CLOCKS_PER_SEC;
fprintf(stderr, "%.2f seconds == %.2f MB/s\n", seconds,
((long long) in_len * per_loop * 10) / (1024 * 1024 * seconds));
- out_len = compress_buf(inb, in_len, outb, sizeof (outb));
+ out_len = compress_buf(inb, in_len, outb, sizeof(outb));
calib_loop = 1;
per_loop = 0;
- start = clock ();
- while ((clock () - start) < CLOCKS_PER_SEC / 4)
+ start = clock();
+ while ((clock() - start) < CLOCKS_PER_SEC / 4)
{
calib_loop *= 2;
for (i = 0; i < calib_loop; i++)
- unchecked_decompress_buf(outb, out_len, inb, sizeof (inb));
+ unchecked_decompress_buf(outb, out_len, inb, sizeof(inb));
per_loop += calib_loop;
}
fprintf(stderr, "decompression:\nCalibrated to %d iterations per loop\n",
per_loop);
- start = clock ();
+ start = clock();
for (i = 0; i < 10; i++)
for (j = 0; j < per_loop; j++)
- unchecked_decompress_buf(outb, out_len, inb, sizeof (inb));
+ unchecked_decompress_buf(outb, out_len, inb, sizeof(inb));
end = clock();
seconds = (end - start) / (float) CLOCKS_PER_SEC;
fprintf(stderr, "%.2f seconds == %.2f MB/s\n", seconds,
}
int
-main (int argc, char *argv[])
+main(int argc, char *argv[])
{
int compress = 1;
- if (argc > 1 && !strcmp (argv[1], "-d"))
+ if (argc > 1 && !strcmp(argv[1], "-d"))
compress = 0;
- if (argc > 1 && !strcmp (argv[1], "-b"))
- benchmark (stdin);
+ if (argc > 1 && !strcmp(argv[1], "-b"))
+ benchmark(stdin);
else
- transfer_file (stdin, stdout, compress);
+ transfer_file(stdin, stdout, compress);
return 0;
}