Fix FileStorage to not close files after they are opened

This is particularly an issue with KTX file reading/writing where we do
both concurrently.
This commit is contained in:
Ryan Huffman 2017-05-19 11:16:20 -07:00
parent c36b85bb05
commit 64bf5784e6
3 changed files with 18 additions and 38 deletions

View file

@ -210,7 +210,6 @@ std::shared_ptr<storage::FileStorage> KtxStorage::maybeOpenFile() const {
}
PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const {
storage::StoragePointer result;
auto faceOffset = _ktxDescriptor->getMipFaceTexelsOffset(level, face);
auto faceSize = _ktxDescriptor->getMipFaceTexelsSize(level, face);
if (faceSize != 0 && faceOffset != 0) {
@ -226,7 +225,7 @@ PixelsPointer KtxStorage::getMipFace(uint16 level, uint8 face) const {
qWarning() << "Failed to get a valid file out of maybeOpenFile " << QString::fromStdString(_filename);
}
}
return result;
return nullptr;
}
Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const {
@ -260,8 +259,13 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
}
auto file = maybeOpenFile();
if (!file) {
qWarning() << "Failed to open file to assign mip data " << QString::fromStdString(_filename);
return;
}
auto imageData = file->mutableData();
auto fileData = file->mutableData();
auto imageData = fileData;
imageData += ktx::KTX_HEADER_SIZE + _ktxDescriptor->header.bytesOfKeyValueData + _ktxDescriptor->images[level]._imageOffset;
imageData += ktx::IMAGE_SIZE_WIDTH;
@ -276,7 +280,7 @@ void KtxStorage::assignMipData(uint16 level, const storage::StoragePointer& stor
memcpy(imageData, storage->data(), storage->size());
_minMipLevelAvailable = level;
if (_offsetToMinMipKV > 0) {
auto minMipKeyData = file->mutableData() + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV;
auto minMipKeyData = fileData + ktx::KTX_HEADER_SIZE + _offsetToMinMipKV;
memcpy(minMipKeyData, (void*)&_minMipLevelAvailable, 1);
}
}

View file

@ -70,7 +70,15 @@ StoragePointer FileStorage::create(const QString& filename, size_t size, const u
}
FileStorage::FileStorage(const QString& filename) : _file(filename) {
if (_file.open(QFile::ReadOnly)) {
bool opened = _file.open(QFile::ReadWrite);
if (opened) {
_hasWriteAccess = true;
} else {
_hasWriteAccess = false;
opened = _file.open(QFile::ReadOnly);
}
if (opened) {
_mapped = _file.map(0, _file.size());
if (_mapped) {
_valid = true;
@ -91,35 +99,4 @@ FileStorage::~FileStorage() {
if (_file.isOpen()) {
_file.close();
}
}
void FileStorage::ensureWriteAccess() {
if (_hasWriteAccess) {
return;
}
if (_mapped) {
if (!_file.unmap(_mapped)) {
throw std::runtime_error("Unable to unmap file");
}
}
if (_file.isOpen()) {
_file.close();
}
_valid = false;
_mapped = nullptr;
if (_file.open(QFile::ReadWrite)) {
_mapped = _file.map(0, _file.size());
if (_mapped) {
_valid = true;
_hasWriteAccess = true;
} else {
qCWarning(storagelogging) << "Failed to map file " << _file.fileName();
throw std::runtime_error("Failed to map file");
}
} else {
qCWarning(storagelogging) << "Failed to open file " << _file.fileName();
throw std::runtime_error("Failed to open file");
}
}

View file

@ -60,11 +60,10 @@ namespace storage {
FileStorage& operator=(const FileStorage& other) = delete;
const uint8_t* data() const override { return _mapped; }
uint8_t* mutableData() override { ensureWriteAccess(); return _mapped; }
uint8_t* mutableData() override { return _hasWriteAccess ? _mapped : nullptr; }
size_t size() const override { return _file.size(); }
operator bool() const override { return _valid; }
private:
void ensureWriteAccess();
bool _valid { false };
bool _hasWriteAccess { false };