Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement gzip-compression of rotated log files (this effectively #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ )
SET( CMAKE_DEBUG_POSTFIX _debug )
SET( BUILD_SHARED_LIBS NO )
SET( ECC_IMPL secp256k1 CACHE STRING "secp256k1 or openssl or mixed" )
SET( FC_USE_FULL_ZLIB FALSE CACHE BOOL "TRUE to try to use full zlib for compression, FALSE to use miniz.c")

if( FC_USE_FULL_ZLIB )
find_package( ZLIB REQUIRED )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFC_USE_FULL_ZLIB")
endif()

set(platformBitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
Expand Down Expand Up @@ -322,6 +328,7 @@ target_include_directories(fc
${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
${ZLIB_INCLUDE_DIRS}
)

#target_link_libraries( fc PUBLIC udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
Expand Down
6 changes: 6 additions & 0 deletions include/fc/compress/zlib.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#pragma once

#include <fc/string.hpp>
#ifdef FC_USE_FULL_ZLIB
# include <fc/filesystem.hpp>
#endif

namespace fc
{

string zlib_compress(const string& in);
#ifdef FC_USE_FULL_ZLIB
void gzip_compress_file(const path& input_filename, const path& output_filename);
#endif

} // namespace fc
3 changes: 2 additions & 1 deletion include/fc/log/file_appender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class file_appender : public appender {
bool rotate = false;
microseconds rotation_interval;
microseconds rotation_limit;
bool rotation_compression = false;
};
file_appender( const variant& args );
~file_appender();
Expand All @@ -31,4 +32,4 @@ class file_appender : public appender {

#include <fc/reflect/reflect.hpp>
FC_REFLECT( fc::file_appender::config,
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit) )
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit)(rotation_compression) )
71 changes: 70 additions & 1 deletion src/compress/zlib.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,77 @@
#include <fc/compress/zlib.hpp>

#include "miniz.c"
#ifdef FC_USE_FULL_ZLIB
# include <zlib.h>
# include <memory>
# include <fstream>
#else
# include "miniz.c"
#endif

namespace fc
{
#ifdef FC_USE_FULL_ZLIB
string zlib_compress(const string& in)
{
unsigned long bufferLen = compressBound(in.size());
std::unique_ptr<char[]> buffer(new char[bufferLen]);
compress((unsigned char*)buffer.get(), &bufferLen, (const unsigned char*)in.c_str(), in.size());
string result(buffer.get(), bufferLen);
return result;
}

void gzip_compress_file(const path& input_filename, const path& output_filename)
{
std::ifstream infile(input_filename.generic_string().c_str(), std::ios::binary);
std::ofstream outfile(output_filename.generic_string().c_str(), std::ios::out | std::ios::binary);
unsigned bufferLen = 1024 * 1024;
std::unique_ptr<char[]> inputBuffer(new char[bufferLen]);
std::unique_ptr<char[]> outputBuffer(new char[bufferLen]);

z_stream outputStream;
outputStream.zalloc = 0;
outputStream.zfree = 0;
outputStream.opaque = 0;
int windowBits = 15;
int GZIP_ENCODING = 16;

deflateInit2(&outputStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits | GZIP_ENCODING,
8, Z_DEFAULT_STRATEGY);

if (infile)
{
do
{
infile.read(inputBuffer.get(), bufferLen);
int bytesRead = infile.gcount();
if (bytesRead == 0)
break;
outputStream.avail_in = bytesRead;
outputStream.next_in = (unsigned char*)inputBuffer.get();
do
{
outputStream.avail_out = bufferLen;
outputStream.next_out = (unsigned char*)outputBuffer.get();
deflate(&outputStream, Z_NO_FLUSH);
int compressedBytesGenerated = bufferLen - outputStream.avail_out;
outfile.write(outputBuffer.get(), compressedBytesGenerated);
}
while (outputStream.avail_out == 0);
}
while (infile);
}
do
{
outputStream.avail_out = bufferLen;
outputStream.next_out = (unsigned char*)outputBuffer.get();
deflate(&outputStream, Z_FINISH);
int compressedBytesGenerated = bufferLen - outputStream.avail_out;
outfile.write(outputBuffer.get(), compressedBytesGenerated);
}
while (outputStream.avail_out == 0);
deflateEnd(&outputStream);
}
#else
string zlib_compress(const string& in)
{
size_t compressed_message_length;
Expand All @@ -12,4 +80,5 @@ namespace fc
free(compressed_message);
return result;
}
#endif
}
44 changes: 40 additions & 4 deletions src/log/file_appender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
#include <fc/thread/scoped_lock.hpp>
#include <fc/thread/thread.hpp>
#include <fc/variant.hpp>
#ifdef FC_USE_FULL_ZLIB
# include <fc/compress/zlib.hpp>
#endif
#include <boost/thread/mutex.hpp>
#include <iomanip>
#include <queue>
#include <sstream>

namespace fc {

static const string compression_extension( ".gz" );

class file_appender::impl : public fc::retainable
{
public:
Expand All @@ -22,6 +27,7 @@ namespace fc {
private:
future<void> _rotation_task;
time_point_sec _current_file_start_time;
std::unique_ptr<thread> _compression_thread;

time_point_sec get_file_start_time( const time_point_sec& timestamp, const microseconds& interval )
{
Expand All @@ -30,6 +36,28 @@ namespace fc {
return time_point_sec( (uint32_t)(file_number * interval_seconds) );
}

void compress_file( const fc::path& filename )
{
#ifdef FC_USE_FULL_ZLIB
FC_ASSERT( cfg.rotate && cfg.rotation_compression );
FC_ASSERT( _compression_thread );
if( !_compression_thread->is_current() )
{
_compression_thread->async( [this, filename]() { compress_file( filename ); }, "compress_file" ).wait();
return;
}

try
{
gzip_compress_file( filename, filename.parent_path() / (filename.filename().string() + compression_extension) );
remove_all( filename );
}
catch( ... )
{
}
#endif
}

public:
impl( const config& c) : cfg( c )
{
Expand All @@ -38,8 +66,10 @@ namespace fc {
FC_ASSERT( cfg.rotation_interval >= seconds( 1 ) );
FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval );



#ifdef FC_USE_FULL_ZLIB
if( cfg.rotation_compression )
_compression_thread.reset( new thread( "compression") );
#endif

_rotation_task = async( [this]() { rotate_files( true ); }, "rotate_files(1)" );
}
Expand Down Expand Up @@ -107,11 +137,16 @@ namespace fc {
fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str );
if( current_timestamp < start_time )
{
if( current_timestamp < limit_time || file_size( current_filename ) <= 0 )
if( current_timestamp < limit_time || file_size( link_filename.parent_path() / itr->filename() ) <= 0 )
{
remove_all( *itr );
continue;
}
if( !cfg.rotation_compression )
continue;
if( current_filename.find( compression_extension ) != string::npos )
continue;
compress_file( *itr );
}
}
catch (const fc::canceled_exception&)
Expand All @@ -134,7 +169,8 @@ namespace fc {
format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
filename(p),
flush(true),
rotate(false)
rotate(false),
rotation_compression(false)
{}

file_appender::file_appender( const variant& args ) :
Expand Down
3 changes: 2 additions & 1 deletion tests/compress/compress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ BOOST_AUTO_TEST_CASE(smaz_test)
BOOST_CHECK_EQUAL( decomp, line );
}

#ifndef FC_USE_FULL_ZLIB

extern "C" {

enum
{
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
Expand Down Expand Up @@ -85,5 +85,6 @@ BOOST_AUTO_TEST_CASE(zlib_test)
std::string decomp = zlib_decompress( compressed );
BOOST_CHECK_EQUAL( decomp, line );
}
#endif

BOOST_AUTO_TEST_SUITE_END()