Commit 06fa5cce authored by Paal Kvamme's avatar Paal Kvamme
Browse files

Two additional checks for what the application is allowed to do.

parent 878690f2
......@@ -300,7 +300,13 @@ LookupTable::_getBegAndSize(
}
/**
* \brief Get file offset for the specified alpha tile.
* \brief Get file offset for the specified alpha tile. Input i/j/lod.
*
* \details
* Convert directly from i/j/lod to the entry for this tile.
* The entry gives the type, file offset, constant value, etc.
* Using this method hides knowledge of the interal "index" space
* as well as how the entry is encoded into a single 64-bit integer.
*/
LookupTable::LutInfo
LookupTable::getAlphaFilePosition(
......@@ -310,8 +316,27 @@ LookupTable::getAlphaFilePosition(
const std::vector<std::uint64_t>& alup,
std::int64_t bytesperalpha)
{
const std::int64_t pos =
alup[getAlphaLookupIndex(i, j, lod, lodsizes, alphaoffsets)];
const std::int64_t index =
getAlphaLookupIndex(i, j, lod, lodsizes, alphaoffsets);
return getAlphaFilePositionFromIndex(index, alup, bytesperalpha);
}
/**
* \brief Get file offset for the specified alpha tile. Input linear index,
*
* \details
* Using this method implies knowledge of how (i,j,k,lod) maps to
* an internal "index" position. It might be better to use the
* corresponding method without "Index" in its name.
*/
LookupTable::LutInfo
LookupTable::getAlphaFilePositionFromIndex(
std::int64_t index,
const std::vector<std::uint64_t>& alup,
std::int64_t bytesperalpha)
{
const std::uint64_t pos = alup[index];
const std::uint8_t type = static_cast<uint8_t>((pos >> 56) & 0xff);
if (pos == 0)
return LutInfo(BrickStatus::Missing, 0, 0, 0);
......@@ -329,6 +354,13 @@ LookupTable::getAlphaFilePosition(
/**
* \brief Get file offset or constant-value for the specified brick.
* Input i/j/k/lod.
*
* \details
* Convert directly from i/j/k/lod to the entry for this brick.
* The entry gives the type, file offset, constant value, etc.
* Using this method hides knowledge of the interal "index" space
* as well as how the entry is encoded into a single 64-bit integer.
*/
LookupTable::LutInfo
LookupTable::getBrickFilePosition(
......@@ -341,6 +373,25 @@ LookupTable::getBrickFilePosition(
{
const std::int64_t ix =
getBrickLookupIndex(i, j, k, lod, lodsizes, brickoffsets);
return getBrickFilePositionFromIndex(ix, blup, bend, bytesperbrick);
}
/**
* \brief Get file offset or constant-value for the specified brick.
* Input linear index.
*
* \details
* Using this method implies knowledge of how (i,j,k,lod) maps to
* an internal "index" position. It might be better to use the
* corresponding method without "Index" in its name.
*/
LookupTable::LutInfo
LookupTable::getBrickFilePositionFromIndex(
std::int64_t ix,
const std::vector<std::uint64_t>& blup,
const std::vector<std::uint64_t>& bend,
std::int64_t bytesperbrick)
{
const std::int64_t pos = blup[ix];
const std::uint8_t type = static_cast<uint8_t>((pos >> 56) & 0xff);
if (pos == 0)
......
......@@ -124,6 +124,11 @@ public:
const std::vector<std::uint64_t>& alup,
std::int64_t bytesperalpha);
static LutInfo getAlphaFilePositionFromIndex(
std::int64_t index,
const std::vector<std::uint64_t>& alup,
std::int64_t bytesperalpha);
static LutInfo getBrickFilePosition(
std::int64_t i, std::int64_t j, std::int64_t k, std::int64_t lod,
const std::vector<std::array<std::int64_t,3>>& lodsizes,
......@@ -132,6 +137,12 @@ public:
const std::vector<std::uint64_t>& bend,
std::int64_t bytesperbrick);
static LutInfo getBrickFilePositionFromIndex(
std::int64_t index,
const std::vector<std::uint64_t>& blup,
const std::vector<std::uint64_t>& bend,
std::int64_t bytesperbrick);
static void setBrickFilePosition(
std::int64_t i, std::int64_t j, std::int64_t k, std::int64_t lod,
const LutInfo& info,
......
......@@ -544,6 +544,7 @@ HeaderAccessFactory::createOffsetHeader(std::uint32_t version)
// Thread safety: None. The user of this type is responsible for that.
class InfoHeaderAccess : public IInfoHeaderAccess
{
public:
virtual void dump(std::ostream& out, const std::string& prefix = "") override;
// Derived information computed from other virtual members, which means
// they can be implemented in the base class. Note that all of these
......@@ -2162,11 +2163,11 @@ ZgyInternalMeta::initFromReopen(const ZgyInternalWriterArgs& args_in, bool compr
}
if (args.have_ilstart)
pod._orig[0] = args.annotstart[0];
pod._orig[0] = args.annotstart[0];
if (args.have_xlstart)
pod._orig[1] = args.annotstart[1];
pod._orig[1] = args.annotstart[1];
if (args.have_zstart)
pod._orig[2] = args.zstart;
pod._orig[2] = args.zstart;
if (args.have_ilinc)
pod._inc[0] = args.annotinc[0];
......@@ -2262,6 +2263,34 @@ ZgyInternalMeta::initFromReopen(const ZgyInternalWriterArgs& args_in, bool compr
(ih.lodsizes(), ih.brickoffsets(),
&this->_blup->lup(), &this->_blup->lupend());
}
if (complete && compress) {
// Disallow opening a finalized file, even if uncompressed, if the
// second open specifies compression. Because we must assume that
// the application is going to finalize in this session and that
// would not be allowed. To be really pedantic I could allow the
// compressor to be set as long as the lodcompressor is not,
// but this is getting ridiculous.
throw OpenZGY::Errors::ZgyUserError
("A finalized file cannot have compressed data appended.");
}
if (complete) {
// Disallow any write of a file that has been finalized with compressed
// low resolution bricks. Because with current rules you won't be
// allowed to re-finalize it. That counts as an update. Need to catch
// this error early. If the application is allowed to start writing but
// not finalize at the end then the file would essentially be corrupted.
const std::vector<std::uint64_t>& blup = this->_blup->lup();
const std::vector<std::uint64_t>& bend = this->_blup->lupend();
const std::int64_t perbrick = ih.bytesperbrick();
for (std::size_t ii=0; ii<blup.size(); ++ii) {
if (LookupTable::getBrickFilePositionFromIndex
(ii, blup, bend, perbrick).status == BrickStatus::Compressed)
throw OpenZGY::Errors::ZgyUserError
("A finalized compressed file cannot be opened for update.");
}
}
}
void
......
......@@ -757,25 +757,12 @@ test_reopen_not_if_final()
// Current checks are incomplete; the error might not be caught
// until the finalize and at that point the file is effectively corrupt.
#if 0 // TODO-@@@ FAILS. Check is not implemented yet.
must_throw("compressed finalized file cannot be opened for update", [&](){
must_throw("finalized compressed file cannot be opened for update", [&](){
writer = OpenZGY::IZgyWriter::reopen
(ZgyWriterArgs()
.iocontext(Test_Utils::default_context())
.filename(lad.name()));
});
#endif
// This documents the current behavior.
// Errors not raised and disk space gets leaked.
// See explanation in one of the later tests.
writer = OpenZGY::IZgyWriter::reopen
(ZgyWriterArgs()
.iocontext(Test_Utils::default_context())
.filename(lad.name()));
writer->write(size3i_t{0,0,64}, size3i_t{1,1,1}, &fifteen);
/*MUST_THROW("is illegal",*/ writer->close(); /*);*/
writer.reset();
// Re-create the file as uncompressed.
writer = OpenZGY::IZgyWriter::open
......@@ -793,7 +780,7 @@ test_reopen_not_if_final()
// would not be allowed. To be really pedantic I could allow the
// compressor to be set as long as the lodcompressor is not,
// but this is getting ridiculous.
#if 0 // TODO-@@@ FAILS. Check is not implemented yet.
must_throw("finalized file cannot have compressed data appended", [&](){
writer = OpenZGY::IZgyWriter::reopen
(ZgyWriterArgs()
......@@ -801,18 +788,6 @@ test_reopen_not_if_final()
.filename(lad.name())
.zfp_compressor(99));
});
#endif
// This documents the current behavior.
// Errors raised during finalize only.
writer = OpenZGY::IZgyWriter::reopen
(ZgyWriterArgs()
.iocontext(Test_Utils::default_context())
.filename(lad.name())
.zfp_compressor(99));
writer->write(size3i_t{0,0,64}, size3i_t{1,1,1}, &fifteen);
MUST_THROW("is illegal", writer->close(););
writer.reset();
}
/**
......
Supports Markdown
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