From 66b62f70f3d11eb00198245debdaed33a3b6abf8 Mon Sep 17 00:00:00 2001 From: Oliver Giles Date: Mon, 31 Jul 2017 08:56:58 +0300 Subject: [PATCH] only compress logs larger than a certain size this fixes an issue where empty or very small logs resulted in a larger compressed log, which was truncated and cannot be decompressed --- src/laminar.cpp | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/laminar.cpp b/src/laminar.cpp index 51847bb..e3b61d8 100644 --- a/src/laminar.cpp +++ b/src/laminar.cpp @@ -29,6 +29,8 @@ #include namespace fs = boost::filesystem; +#define COMPRESS_LOG_MIN_SIZE 1024 + #include #include @@ -139,14 +141,18 @@ void Laminar::sendStatus(LaminarClient* client) { } else { // it must be finished, fetch it from the database db->stmt("SELECT output, outputLen FROM builds WHERE name = ? AND number = ?") .bind(client->scope.job, client->scope.num) - .fetch([=](str zipped, unsigned long sz) { + .fetch([=](str maybeZipped, unsigned long sz) { std::string log(sz+1,'\0'); - int res = ::uncompress((unsigned char*)&log[0], &sz, - (unsigned char*)zipped.data(), zipped.size()); - if(res == Z_OK) - client->sendMessage(log); - else - LLOG(ERROR, "Failed to uncompress log", res); + if(sz < COMPRESS_LOG_MIN_SIZE) { + int res = ::uncompress((unsigned char*)&log[0], &sz, + (unsigned char*)maybeZipped.data(), maybeZipped.size()); + if(res == Z_OK) + client->sendMessage(log); + else + LLOG(ERROR, "Failed to uncompress log"); + } else { + client->sendMessage(maybeZipped); + } }); } return; @@ -680,17 +686,22 @@ void Laminar::runFinished(Run * r) { time_t completedAt = time(0); // compress log - std::string zipped(r->log.size(), '\0'); + std::string maybeZipped = r->log; size_t logsize = r->log.length(); - size_t zippedSize = zipped.size(); - ::compress((unsigned char*)&zipped[0], &zippedSize, - (unsigned char*)&r->log[0], logsize); - zipped.resize(zippedSize); + if(r->log.length() >= COMPRESS_LOG_MIN_SIZE) { + std::string zipped(r->log.size(), '\0'); + size_t zippedSize = zipped.size(); + if(::compress((unsigned char*)&zipped[0], &zippedSize, + (unsigned char*)&r->log[0], logsize) == Z_OK) { + zipped.resize(zippedSize); + std::swap(maybeZipped, zipped); + } + } std::string reason = r->reason(); db->stmt("INSERT INTO builds VALUES(?,?,?,?,?,?,?,?,?,?,?,?)") .bind(r->name, r->build, node->name, r->queuedAt, r->startedAt, completedAt, int(r->result), - zipped, logsize, r->parentName, r->parentBuild, reason) + maybeZipped, logsize, r->parentName, r->parentBuild, reason) .exec(); // notify clients