Implement gzip-compression of rotated log files (this effectively
restores the functionality removed in 701b9ac00c,
which had lzma-compression of rotated logs)
This commit is contained in:
parent
605e9ed7ef
commit
57d14c7de8
6 changed files with 127 additions and 7 deletions
|
|
@ -25,6 +25,12 @@ SET( DEFAULT_EXECUTABLE_INSTALL_DIR bin/ )
|
||||||
SET( CMAKE_DEBUG_POSTFIX _debug )
|
SET( CMAKE_DEBUG_POSTFIX _debug )
|
||||||
SET( BUILD_SHARED_LIBS NO )
|
SET( BUILD_SHARED_LIBS NO )
|
||||||
SET( ECC_IMPL secp256k1 CACHE STRING "secp256k1 or openssl or mixed" )
|
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)
|
set(platformBitness 32)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
|
@ -306,6 +312,7 @@ target_include_directories(fc
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
${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} )
|
#target_link_libraries( fc PUBLIC udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} )
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fc/string.hpp>
|
#include <fc/string.hpp>
|
||||||
|
#ifdef FC_USE_FULL_ZLIB
|
||||||
|
# include <fc/filesystem.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace fc
|
namespace fc
|
||||||
{
|
{
|
||||||
|
|
||||||
string zlib_compress(const string& in);
|
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
|
} // namespace fc
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class file_appender : public appender {
|
||||||
bool rotate = false;
|
bool rotate = false;
|
||||||
microseconds rotation_interval;
|
microseconds rotation_interval;
|
||||||
microseconds rotation_limit;
|
microseconds rotation_limit;
|
||||||
|
bool rotation_compression = false;
|
||||||
};
|
};
|
||||||
file_appender( const variant& args );
|
file_appender( const variant& args );
|
||||||
~file_appender();
|
~file_appender();
|
||||||
|
|
@ -31,4 +32,4 @@ class file_appender : public appender {
|
||||||
|
|
||||||
#include <fc/reflect/reflect.hpp>
|
#include <fc/reflect/reflect.hpp>
|
||||||
FC_REFLECT( fc::file_appender::config,
|
FC_REFLECT( fc::file_appender::config,
|
||||||
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit) )
|
(format)(filename)(flush)(rotate)(rotation_interval)(rotation_limit)(rotation_compression) )
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,77 @@
|
||||||
#include <fc/compress/zlib.hpp>
|
#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
|
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)
|
string zlib_compress(const string& in)
|
||||||
{
|
{
|
||||||
size_t compressed_message_length;
|
size_t compressed_message_length;
|
||||||
|
|
@ -12,4 +80,5 @@ namespace fc
|
||||||
free(compressed_message);
|
free(compressed_message);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@
|
||||||
#include <fc/thread/scoped_lock.hpp>
|
#include <fc/thread/scoped_lock.hpp>
|
||||||
#include <fc/thread/thread.hpp>
|
#include <fc/thread/thread.hpp>
|
||||||
#include <fc/variant.hpp>
|
#include <fc/variant.hpp>
|
||||||
|
#ifdef FC_USE_FULL_ZLIB
|
||||||
|
# include <fc/compress/zlib.hpp>
|
||||||
|
#endif
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
@ -12,6 +15,8 @@
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
||||||
|
static const string compression_extension( ".gz" );
|
||||||
|
|
||||||
class file_appender::impl : public fc::retainable
|
class file_appender::impl : public fc::retainable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -22,6 +27,7 @@ namespace fc {
|
||||||
private:
|
private:
|
||||||
future<void> _rotation_task;
|
future<void> _rotation_task;
|
||||||
time_point_sec _current_file_start_time;
|
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 )
|
time_point_sec get_file_start_time( const time_point_sec& timestamp, const microseconds& interval )
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +36,28 @@ namespace fc {
|
||||||
return time_point_sec( (uint32_t)(file_number * interval_seconds) );
|
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:
|
public:
|
||||||
impl( const config& c) : cfg( c )
|
impl( const config& c) : cfg( c )
|
||||||
{
|
{
|
||||||
|
|
@ -38,8 +66,10 @@ namespace fc {
|
||||||
FC_ASSERT( cfg.rotation_interval >= seconds( 1 ) );
|
FC_ASSERT( cfg.rotation_interval >= seconds( 1 ) );
|
||||||
FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval );
|
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)" );
|
_rotation_task = async( [this]() { rotate_files( true ); }, "rotate_files(1)" );
|
||||||
}
|
}
|
||||||
|
|
@ -107,11 +137,16 @@ namespace fc {
|
||||||
fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str );
|
fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str );
|
||||||
if( current_timestamp < start_time )
|
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 );
|
remove_all( *itr );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if( !cfg.rotation_compression )
|
||||||
|
continue;
|
||||||
|
if( current_filename.find( compression_extension ) != string::npos )
|
||||||
|
continue;
|
||||||
|
compress_file( *itr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const fc::canceled_exception&)
|
catch (const fc::canceled_exception&)
|
||||||
|
|
@ -134,7 +169,8 @@ namespace fc {
|
||||||
format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
|
format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
|
||||||
filename(p),
|
filename(p),
|
||||||
flush(true),
|
flush(true),
|
||||||
rotate(false)
|
rotate(false),
|
||||||
|
rotation_compression(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
file_appender::file_appender( const variant& args ) :
|
file_appender::file_appender( const variant& args ) :
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ BOOST_AUTO_TEST_CASE(smaz_test)
|
||||||
BOOST_CHECK_EQUAL( decomp, line );
|
BOOST_CHECK_EQUAL( decomp, line );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef FC_USE_FULL_ZLIB
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
|
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
|
||||||
|
|
@ -85,5 +85,6 @@ BOOST_AUTO_TEST_CASE(zlib_test)
|
||||||
std::string decomp = zlib_decompress( compressed );
|
std::string decomp = zlib_decompress( compressed );
|
||||||
BOOST_CHECK_EQUAL( decomp, line );
|
BOOST_CHECK_EQUAL( decomp, line );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue