wsd: fileserver: better compression failure handling

We now always cache the uncompressed file data even
when compressing fails. If no compressed data exists,
we return the uncompressed version.

Change-Id: I885275dac526f4d47ea74d6badcb609390e7c139
Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk>
Ashod Nakashian 2024-05-05 08:02:05 -04:00
parent d7931b1bef
commit 55526f42f2
1 changed files with 45 additions and 28 deletions

View File

@ -830,6 +830,25 @@ void FileServerRequestHandler::readDirToHash(const std::string &basePath, const
}
else if (S_ISREG(fileStat.st_mode))
{
std::string uncompressedFile;
const ssize_t size =
FileUtil::readFile(basePath + relPath, uncompressedFile, /*maxSize=*/1024 * 1024);
if (size <= 0)
{
assert(uncompressedFile.empty() &&
"Unexpected data in uncompressedFile after failed read");
if (size < 0)
{
LOG_ERR("Failed to read file [" << basePath + relPath
<< "] or is too large to cache and serve");
}
// Always add the entry, even if the contents are empty.
FileHash.emplace(prefix + relPath,
std::make_pair(std::move(uncompressedFile), std::string()));
continue;
}
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
@ -837,44 +856,40 @@ void FileServerRequestHandler::readDirToHash(const std::string &basePath, const
const int initResult = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY);
if (initResult != Z_OK)
{
LOG_ERR("Failed to deflateInit2, result: " << initResult);
continue;
LOG_ERR("Failed to deflateInit2 for file [" << basePath + relPath
<< "], result: " << initResult);
// Add the uncompressed version; it's better to serve uncompressed than nothing at all.
FileHash.emplace(prefix + relPath,
std::make_pair(std::move(uncompressedFile), std::string()));
continue;
}
fileCount++;
filesRead.append(currentFile->d_name);
filesRead += ' ';
// Compress.
assert(size > 0 && "No data to compress");
assert(!uncompressedFile.empty() && "Unexpected empty uncompressedFile");
std::string compressedFile;
std::string uncompressedFile;
const ssize_t size =
FileUtil::readFile(basePath + relPath, uncompressedFile, /*maxSize=*/1024 * 1024);
if (size > 0)
{
const long unsigned int compSize = compressBound(size);
compressedFile.resize(compSize);
strm.next_in = (unsigned char*)&uncompressedFile[0];
strm.avail_in = size;
strm.avail_out = compSize;
strm.next_out = (unsigned char*)&compressedFile[0];
strm.total_out = strm.total_in = 0;
const long unsigned int compSize = compressBound(size);
compressedFile.resize(compSize);
strm.next_in = (unsigned char*)&uncompressedFile[0];
strm.avail_in = size;
strm.avail_out = compSize;
strm.next_out = (unsigned char*)&compressedFile[0];
strm.total_out = strm.total_in = 0;
const int deflateResult = deflate(&strm, Z_FINISH);
if (deflateResult != Z_OK && deflateResult != Z_STREAM_END)
{
LOG_ERR("Failed to deflate [" << basePath + relPath
<< "], result: " << deflateResult);
compressedFile.clear();
}
else
{
compressedFile.resize(compSize - strm.avail_out);
}
const int deflateResult = deflate(&strm, Z_FINISH);
if (deflateResult != Z_OK && deflateResult != Z_STREAM_END)
{
LOG_ERR("Failed to deflate [" << basePath + relPath
<< "], result: " << deflateResult);
compressedFile.clear(); // Can't trust the compressed data, if any.
}
else
{
LOG_ERR("File [" << basePath + relPath
<< "] is too large to cache and serve. Ignoring");
compressedFile.resize(compSize - strm.avail_out);
}
FileHash.emplace(prefix + relPath, std::make_pair(std::move(uncompressedFile),
@ -891,7 +906,9 @@ void FileServerRequestHandler::readDirToHash(const std::string &basePath, const
const std::string *FileServerRequestHandler::getCompressedFile(const std::string &path)
{
return &FileHash[path].second;
// If a compressed version is not available, return the original uncompressed data.
const auto& pair = FileHash[path];
return pair.second.empty() ? &pair.first : &pair.second;
}
const std::string *FileServerRequestHandler::getUncompressedFile(const std::string &path)