Description
It would be nice to be able to save to/restore compressed ZFP arrays from mmapped files. At present a crude workaround has been applied to zfparray.h:
added three extra variables to the array class:
std::string storage; //persistent storage via mmap
bool is_mmapped;
size_t storage_size;
and then alloc() / free() have been changed too:
// allocate memory for compressed data
void alloc(bool clear = true)
{
bytes = blocks * blkbits / CHAR_BIT;
printf("zfp::array3::alloc<clear:%d, storage:%s, bytes:%zu>\n", clear, storage.c_str(), bytes);
if (bytes > 1 && storage != "")
{
//try mmap first
int fd = open(storage.c_str(), O_RDWR | O_CREAT, (mode_t)0600);
if (fd != -1)
{
int stat = ftruncate64(fd, bytes);
if (!stat)
{
void *buffer = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer != MAP_FAILED)
{
data = (uchar *)buffer;
is_mmapped = true;
storage_size = bytes;
printf("zfp::array3::alloc<mmap OK>.\n");
}
else
perror("mmap");
}
else
{
perror("ftruncate64");
}
close(fd);
}
}
if (!is_mmapped)
{
reallocate(data, bytes, 0x100u);
if (clear)
std::fill(data, data + bytes, 0);
}
stream_close(zfp->stream);
zfp_stream_set_bit_stream(zfp, stream_open(data, bytes));
clear_cache();
}
// free memory associated with compressed data
void free()
{
nx = ny = nz = 0;
bx = by = bz = 0;
blocks = 0;
stream_close(zfp->stream);
zfp_stream_set_bit_stream(zfp, 0);
bytes = 0;
if (!is_mmapped)
deallocate(data);
else
{
if (data != NULL)
{
if (munmap(data, storage_size) == -1)
perror("un-mapping error");
else
printf("zfp::array3::free.\n");
storage_size = 0;
is_mmapped = false;
};
};
data = 0;
deallocate(shape);
shape = 0;
}
This is a "quick&dirty" workaround. A more elegant ZFP-wide solution would be much nicer.
the array3 constructor in zfparray3.h has been modified slightly too:
array3(uint nx, uint ny, uint nz, double rate, const Scalar* p = 0, size_t csize = 0, std::string _storage = std::string("")) :
array(3, Codec::type),
cache(lines(csize, nx, ny, nz))
{
storage = _storage;
is_mmapped = false;
storage_size = 0;
set_rate(rate);
resize(nx, ny, nz, p == 0);
if (p)
set(p);
}