Commit 38f7e4bc authored by Mike Hibler's avatar Mike Hibler

Conditional code USE_CHUNKMAP to create a map from chunkno to range bounds.

Useful for fast lookup of the first address range in a chunk.
parent 3f02cf23
......@@ -24,6 +24,8 @@
#ifndef _LIBNDZ_H_
#define _LIBNDZ_H_
//#define USE_CHUNKMAP
#include "imagehdr.h"
#include "imagehash.h"
#include "rangemap.h"
......@@ -38,6 +40,11 @@ struct ndz_hashdata {
uint8_t hash[HASH_MAXSIZE];
};
struct ndz_bounds {
ndz_addr_t losect;
ndz_addr_t hisect;
};
struct ndz_file {
int fd;
int flags;
......@@ -48,6 +55,11 @@ struct ndz_file {
ndz_chunkno_t nchunks;
ndz_addr_t maplo, maphi;
struct ndz_rangemap *rangemap;
#ifdef USE_CHUNKMAP
/* map of chunks to covered ranges */
ndz_chunkno_t chunkmapentries;
struct ndz_bounds *chunkmap;
#endif
/* chunk object info */
ndz_chunk_t chunkobj;
ndz_addr_t chunksect;
......
......@@ -33,6 +33,7 @@
//#define CHUNK_DEBUG
#ifndef USE_CHUNKMAP
/*
* Find the first range for a particular chunk.
*
......@@ -56,6 +57,7 @@ findchunk(struct ndz_rangemap *map, struct ndz_range *range, void *arg)
}
return 0;
}
#endif
/*
* Read uncompessed data from an imagefile.
......@@ -70,7 +72,6 @@ ndz_readdata(struct ndz_file *ndz, void *buf, ndz_size_t nsect, ndz_addr_t sect)
struct ndz_range *range, *crange;
ndz_chunkno_t chunkno, lchunkno;
ndz_chunk_t chunk;
struct fcarg fcarg;
ssize_t rbytes, cc;
if (ndz->rangemap == NULL && ndz_readranges(ndz) == NULL) {
......@@ -101,7 +102,8 @@ ndz_readdata(struct ndz_file *ndz, void *buf, ndz_size_t nsect, ndz_addr_t sect)
ndz->chunkuses++;
#endif
chunk = ndz->chunkobj;
if (chunk && ndz_chunk_chunkno(chunk) == chunkno && ndz->chunksect <= ssect) {
if (chunk && ndz_chunk_chunkno(chunk) == chunkno &&
ndz->chunksect <= ssect) {
#ifdef CHUNK_DEBUG
fprintf(stderr, "%s: reusing chunk %d object, sect=%ld\n",
ndz->fname, chunkno, ndz->chunksect);
......@@ -152,13 +154,26 @@ ndz_readdata(struct ndz_file *ndz, void *buf, ndz_size_t nsect, ndz_addr_t sect)
}
}
/* note: chunk numbers are 1-based in range map */
fcarg.in_chunkno = chunkno + 1;
fcarg.out_range = NULL;
(void) ndz_rangemap_iterate(ndz->rangemap, findchunk, &fcarg);
crange = fcarg.out_range;
#ifdef USE_CHUNKMAP
assert(chunkno < ndz->chunkmapentries);
csect = ndz->chunkmap[chunkno].losect;
crange = ndz_rangemap_lookup(ndz->rangemap, csect, NULL);
assert(crange != NULL);
csect = ndz->chunksect = crange->start;
assert(crange->start == csect);
#else
{
struct fcarg fcarg;
/* note: chunk numbers are 1-based in range map */
fcarg.in_chunkno = chunkno + 1;
fcarg.out_range = NULL;
(void) ndz_rangemap_iterate(ndz->rangemap, findchunk, &fcarg);
crange = fcarg.out_range;
assert(crange != NULL);
csect = crange->start;
}
#endif
ndz->chunksect = csect;
#ifdef CHUNK_DEBUG
fprintf(stderr, "%s: (re)opened chunk %d object, sect=%ld\n",
ndz->fname, chunkno, ndz->chunksect);
......
......@@ -27,6 +27,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/stat.h>
#include "libndz.h"
......@@ -122,6 +123,10 @@ ndz_close(struct ndz_file *ndz)
ndz_rangemap_deinit(ndz->hashmap);
if (ndz->rangemap)
ndz_rangemap_deinit(ndz->rangemap);
#ifdef USE_CHUNKMAP
if (ndz->chunkmap)
free(ndz->chunkmap);
#endif
if (ndz->fname)
free(ndz->fname);
free(ndz);
......@@ -204,6 +209,9 @@ ndz_readranges(struct ndz_file *ndz)
int rv, i;
ndz_chunkno_t chunkno;
ndz_addr_t first = 0, last = 0;
#ifdef USE_CHUNKMAP
struct stat sb;
#endif
if (ndz == NULL || (ndz->flags & NDZ_FILE_WRITE) != 0)
return NULL;
......@@ -217,10 +225,35 @@ ndz_readranges(struct ndz_file *ndz)
return NULL;
}
#ifdef USE_CHUNKMAP
/*
* See if we can fstat the input so that we only have to do
* one allocation for the chunkmap.
*/
if (fstat(ndz->fd, &sb) == 0 && sb.st_size > 0) {
ndz->chunkmapentries = (sb.st_size + CHUNKSIZE - 1) / CHUNKSIZE;
ndz->chunkmap = malloc(ndz->chunkmapentries *
sizeof(ndz->chunkmap[0]));
if (ndz->chunkmap == NULL) {
fprintf(stderr, "%s: could not allocate chunkmap\n",
ndz->fname);
ndz->chunkmapentries = 0;
ndz_rangemap_deinit(map);
return NULL;
}
fprintf(stderr, "allocated chunkmap of %d bytes\n",
ndz->chunkmapentries * sizeof(ndz->chunkmap[0]));
}
#endif
/*
* Read the header of each chunk adding regions to the map.
*/
for (chunkno = 0; ; chunkno++) {
#ifdef USE_CHUNKMAP
ndz_addr_t clo, chi = 0;
#endif
rv = ndz_readchunkheader(ndz, chunkno, &head);
if (rv)
return NULL;
......@@ -233,6 +266,10 @@ ndz_readranges(struct ndz_file *ndz)
if (chunkno == 0)
first = hdr->firstsect;
last = hdr->lastsect;
#ifdef USE_CHUNKMAP
clo = hdr->firstsect;
chi = hdr->lastsect;
#endif
}
/* get the regions */
......@@ -243,6 +280,11 @@ ndz_readranges(struct ndz_file *ndz)
if (chunkno == 0)
first = (ndz_addr_t)reg->start;
last = (ndz_addr_t)reg->start + (ndz_size_t)reg->size - 1;
#ifdef USE_CHUNKMAP
if (i == 0)
clo = (ndz_addr_t)reg->start;
chi = last;
#endif
}
rv = ndz_rangemap_alloc(map,
(ndz_addr_t)reg->start,
......@@ -259,11 +301,36 @@ ndz_readranges(struct ndz_file *ndz)
reg++;
}
#ifdef USE_CHUNKMAP
if (chunkno >= ndz->chunkmapentries) {
assert(chunkno == ndz->chunkmapentries);
ndz->chunkmap = realloc(ndz->chunkmap,
(chunkno+1)*sizeof(ndz->chunkmap[0]));
if (ndz->chunkmap == NULL) {
fprintf(stderr, "%s: could not allocate chunkmap entry\n",
ndz->fname);
ndz->chunkmapentries = 0;
ndz_rangemap_deinit(map);
return NULL;
}
ndz->chunkmapentries = chunkno + 1;
}
ndz->chunkmap[chunkno].losect = clo;
ndz->chunkmap[chunkno].hisect = chi;
#endif
/* get the relocations */
if (head.reloc) {
if (ndz_reloc_get(ndz, head.header, head.reloc) != 0) {
fprintf(stderr, "%s: could not add relocations\n",
ndz->fname);
#ifdef USE_CHUNKMAP
if (ndz->chunkmap) {
free(ndz->chunkmap);
ndz->chunkmap = NULL;
ndz->chunkmapentries = 0;
}
#endif
ndz_rangemap_deinit(map);
return NULL;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment