Merge branch 'master' of https://github.com/BitShares/fc
This commit is contained in:
commit
633c889ce3
12 changed files with 406 additions and 86 deletions
|
|
@ -86,15 +86,6 @@ ENDIF()
|
||||||
|
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
|
|
||||||
IF(APPLE)
|
|
||||||
# As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency
|
|
||||||
# on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib
|
|
||||||
# option or not when it was built, but that's difficult to do in practice, so we
|
|
||||||
# just always try to link it in on mac.
|
|
||||||
find_package( ZLIB REQUIRED )
|
|
||||||
ENDIF(APPLE)
|
|
||||||
|
|
||||||
|
|
||||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
|
set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} )
|
||||||
|
|
||||||
option( UNITY_BUILD OFF )
|
option( UNITY_BUILD OFF )
|
||||||
|
|
@ -137,6 +128,7 @@ set( fc_sources
|
||||||
src/log/appender.cpp
|
src/log/appender.cpp
|
||||||
src/log/console_appender.cpp
|
src/log/console_appender.cpp
|
||||||
src/log/file_appender.cpp
|
src/log/file_appender.cpp
|
||||||
|
src/log/gelf_appender.cpp
|
||||||
src/log/logger_config.cpp
|
src/log/logger_config.cpp
|
||||||
src/crypto/openssl.cpp
|
src/crypto/openssl.cpp
|
||||||
src/crypto/aes.cpp
|
src/crypto/aes.cpp
|
||||||
|
|
@ -353,6 +345,14 @@ if(WIN32)
|
||||||
|
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
|
IF(APPLE)
|
||||||
|
# As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency
|
||||||
|
# on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib
|
||||||
|
# option or not when it was built, but that's difficult to do in practice, so we
|
||||||
|
# just always try to link it in on mac.
|
||||||
|
find_package( ZLIB REQUIRED )
|
||||||
|
ENDIF(APPLE)
|
||||||
|
|
||||||
SET(OPENSSL_CONF_TARGET )
|
SET(OPENSSL_CONF_TARGET )
|
||||||
IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||||
SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||||
|
|
|
||||||
|
|
@ -298,21 +298,26 @@ namespace fc
|
||||||
* @brief Checks a condition and throws an assert_exception if the test is FALSE
|
* @brief Checks a condition and throws an assert_exception if the test is FALSE
|
||||||
*/
|
*/
|
||||||
#define FC_ASSERT( TEST, ... ) \
|
#define FC_ASSERT( TEST, ... ) \
|
||||||
FC_EXPAND_MACRO( \
|
FC_EXPAND_MACRO( \
|
||||||
do { if( !(TEST) ) { FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); } } while(0) \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
)
|
if( !(TEST) ) \
|
||||||
|
FC_THROW_EXCEPTION( fc::assert_exception, #TEST ": " __VA_ARGS__ ); \
|
||||||
|
FC_MULTILINE_MACRO_END \
|
||||||
|
)
|
||||||
|
|
||||||
#define FC_CAPTURE_AND_THROW( EXCEPTION_TYPE, ... ) \
|
#define FC_CAPTURE_AND_THROW( EXCEPTION_TYPE, ... ) \
|
||||||
do { throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); } while(0)
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
|
throw EXCEPTION_TYPE( FC_LOG_MESSAGE( error, "", FC_FORMAT_ARG_PARAMS(__VA_ARGS__) ) ); \
|
||||||
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
//#define FC_THROW( FORMAT, ... )
|
//#define FC_THROW( FORMAT, ... )
|
||||||
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
|
// FC_INDIRECT_EXPAND workas around a bug in Visual C++ variadic macro processing that prevents it
|
||||||
// from separating __VA_ARGS__ into separate tokens
|
// from separating __VA_ARGS__ into separate tokens
|
||||||
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
|
#define FC_INDIRECT_EXPAND(MACRO, ARGS) MACRO ARGS
|
||||||
#define FC_THROW( ... ) \
|
#define FC_THROW( ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
|
throw fc::exception( FC_INDIRECT_EXPAND(FC_LOG_MESSAGE, ( error, __VA_ARGS__ )) ); \
|
||||||
} while(0)
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
|
#define FC_EXCEPTION( EXCEPTION_TYPE, FORMAT, ... ) \
|
||||||
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
|
EXCEPTION_TYPE( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) )
|
||||||
|
|
@ -322,9 +327,9 @@ namespace fc
|
||||||
* @param format - a const char* string with "${keys}"
|
* @param format - a const char* string with "${keys}"
|
||||||
*/
|
*/
|
||||||
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
|
#define FC_THROW_EXCEPTION( EXCEPTION, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
throw EXCEPTION( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} while(0)
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -332,10 +337,10 @@ namespace fc
|
||||||
* @brief Appends a log_message to the exception ER and rethrows it.
|
* @brief Appends a log_message to the exception ER and rethrows it.
|
||||||
*/
|
*/
|
||||||
#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
|
#define FC_RETHROW_EXCEPTION( ER, LOG_LEVEL, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
|
ER.append_log( FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, __VA_ARGS__ ) ); \
|
||||||
throw;\
|
throw; \
|
||||||
} while(0)
|
FC_MULTILINE_MACRO_END
|
||||||
|
|
||||||
#define FC_LOG_AND_RETHROW( ) \
|
#define FC_LOG_AND_RETHROW( ) \
|
||||||
catch( fc::exception& er ) { \
|
catch( fc::exception& er ) { \
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <fc/string.hpp>
|
#include <fc/string.hpp>
|
||||||
#include <fc/reflect/typename.hpp>
|
#include <fc/reflect/typename.hpp>
|
||||||
#include <fc/optional.hpp>
|
#include <fc/optional.hpp>
|
||||||
|
|
@ -226,5 +228,37 @@ namespace fc {
|
||||||
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
|
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
// this code is known to work on linux and windows. It may work correctly on mac,
|
||||||
|
// or it may need slight tweaks or extra includes. It's disabled now to avoid giving
|
||||||
|
// a false sense of security.
|
||||||
|
# define FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
#endif
|
||||||
|
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
/** simple class which only allows one process to open any given file.
|
||||||
|
* approximate usage:
|
||||||
|
* int main() {
|
||||||
|
* fc::simple_file_lock instance_lock("~/.my_app/.lock");
|
||||||
|
* if (!instance_lock.try_lock()) {
|
||||||
|
* elog("my_app is already running");
|
||||||
|
* return 1;
|
||||||
|
* }
|
||||||
|
* // do stuff here, file will be unlocked when instance_lock goes out of scope
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
class simple_lock_file
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
simple_lock_file(const path& lock_file_path);
|
||||||
|
~simple_lock_file();
|
||||||
|
bool try_lock();
|
||||||
|
void unlock();
|
||||||
|
private:
|
||||||
|
class impl;
|
||||||
|
std::unique_ptr<impl> my;
|
||||||
|
};
|
||||||
|
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
32
include/fc/log/gelf_appender.hpp
Normal file
32
include/fc/log/gelf_appender.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fc/log/appender.hpp>
|
||||||
|
#include <fc/log/logger.hpp>
|
||||||
|
#include <fc/time.hpp>
|
||||||
|
|
||||||
|
namespace fc
|
||||||
|
{
|
||||||
|
// Log appender that sends log messages in JSON format over UDP
|
||||||
|
// https://www.graylog2.org/resources/gelf/specification
|
||||||
|
class gelf_appender : public appender
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct config
|
||||||
|
{
|
||||||
|
string endpoint = "127.0.0.1:12201";
|
||||||
|
string host = "fc"; // the name of the host, source or application that sent this message (just passed through to GELF server)
|
||||||
|
};
|
||||||
|
|
||||||
|
gelf_appender(const variant& args);
|
||||||
|
~gelf_appender();
|
||||||
|
virtual void log(const log_message& m) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class impl;
|
||||||
|
fc::shared_ptr<impl> my;
|
||||||
|
};
|
||||||
|
} // namespace fc
|
||||||
|
|
||||||
|
#include <fc/reflect/reflect.hpp>
|
||||||
|
FC_REFLECT(fc::gelf_appender::config,
|
||||||
|
(endpoint)(host))
|
||||||
|
|
@ -61,74 +61,77 @@ namespace fc
|
||||||
#define DEFAULT_LOGGER
|
#define DEFAULT_LOGGER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// suppress warning "conditional expression is constant" in the while(0) for visual c++
|
||||||
|
// http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/
|
||||||
|
#define FC_MULTILINE_MACRO_BEGIN do {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define FC_MULTILINE_MACRO_END \
|
||||||
|
__pragma(warning(push)) \
|
||||||
|
__pragma(warning(disable:4127)) \
|
||||||
|
} while (0) \
|
||||||
|
__pragma(warning(pop))
|
||||||
|
#else
|
||||||
|
# define FC_MULTILINE_MACRO_END } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define fc_dlog( LOGGER, FORMAT, ... ) \
|
#define fc_dlog( LOGGER, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (LOGGER).is_enabled( fc::log_level::debug ) ) { \
|
if( (LOGGER).is_enabled( fc::log_level::debug ) ) \
|
||||||
(LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
(LOGGER).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define fc_ilog( LOGGER, FORMAT, ... ) \
|
#define fc_ilog( LOGGER, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (LOGGER).is_enabled( fc::log_level::info ) ) { \
|
if( (LOGGER).is_enabled( fc::log_level::info ) ) \
|
||||||
(LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
(LOGGER).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define fc_wlog( LOGGER, FORMAT, ... ) \
|
#define fc_wlog( LOGGER, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (LOGGER).is_enabled( fc::log_level::warn ) ) { \
|
if( (LOGGER).is_enabled( fc::log_level::warn ) ) \
|
||||||
(LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
(LOGGER).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define fc_elog( LOGGER, FORMAT, ... ) \
|
#define fc_elog( LOGGER, FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (LOGGER).is_enabled( fc::log_level::error ) ) { \
|
if( (LOGGER).is_enabled( fc::log_level::error ) ) \
|
||||||
(LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
(LOGGER).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define dlog( FORMAT, ... ) \
|
#define dlog( FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) { \
|
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::debug ) ) \
|
||||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the log message to a special 'user' log stream designed for messages that
|
* Sends the log message to a special 'user' log stream designed for messages that
|
||||||
* the end user may like to see.
|
* the end user may like to see.
|
||||||
*/
|
*/
|
||||||
#define ulog( FORMAT, ... ) \
|
#define ulog( FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (fc::logger::get("user")).is_enabled( fc::log_level::debug ) ) { \
|
if( (fc::logger::get("user")).is_enabled( fc::log_level::debug ) ) \
|
||||||
(fc::logger::get("user")).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
(fc::logger::get("user")).log( FC_LOG_MESSAGE( debug, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
#define ilog( FORMAT, ... ) \
|
#define ilog( FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::info ) ) { \
|
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::info ) ) \
|
||||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( info, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define wlog( FORMAT, ... ) \
|
#define wlog( FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::warn ) ) { \
|
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::warn ) ) \
|
||||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( warn, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define elog( FORMAT, ... ) \
|
#define elog( FORMAT, ... ) \
|
||||||
do { \
|
FC_MULTILINE_MACRO_BEGIN \
|
||||||
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::error ) ) { \
|
if( (fc::logger::get(DEFAULT_LOGGER)).is_enabled( fc::log_level::error ) ) \
|
||||||
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
(fc::logger::get(DEFAULT_LOGGER)).log( FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ ) ); \
|
||||||
} \
|
FC_MULTILINE_MACRO_END
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#include <boost/preprocessor/seq/for_each.hpp>
|
#include <boost/preprocessor/seq/for_each.hpp>
|
||||||
#include <boost/preprocessor/seq/enum.hpp>
|
#include <boost/preprocessor/seq/enum.hpp>
|
||||||
|
|
@ -164,13 +167,13 @@ namespace fc
|
||||||
// a slowdown.
|
// a slowdown.
|
||||||
#ifdef FC_DISABLE_LOGGING
|
#ifdef FC_DISABLE_LOGGING
|
||||||
# undef ulog
|
# undef ulog
|
||||||
# define ulog(...) do {} while(0)
|
# define ulog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||||
# undef elog
|
# undef elog
|
||||||
# define elog(...) do {} while(0)
|
# define elog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||||
# undef wlog
|
# undef wlog
|
||||||
# define wlog(...) do {} while(0)
|
# define wlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||||
# undef ilog
|
# undef ilog
|
||||||
# define ilog(...) do {} while(0)
|
# define ilog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||||
# undef dlog
|
# undef dlog
|
||||||
# define dlog(...) do {} while(0)
|
# define dlog(...) FC_MULTILINE_MACRO_BEGIN FC_MULTILINE_MACRO_END
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -618,7 +618,7 @@ std::string to_base58( const std::vector<char>& d )
|
||||||
std::vector<char> from_base58( const std::string& base58_str ) {
|
std::vector<char> from_base58( const std::string& base58_str ) {
|
||||||
std::vector<unsigned char> out;
|
std::vector<unsigned char> out;
|
||||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||||
FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||||
}
|
}
|
||||||
return std::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
return std::vector<char>((const char*)out.data(), ((const char*)out.data())+out.size() );
|
||||||
}
|
}
|
||||||
|
|
@ -629,7 +629,7 @@ size_t from_base58( const std::string& base58_str, char* out_data, size_t out_da
|
||||||
//slog( "%s", base58_str.c_str() );
|
//slog( "%s", base58_str.c_str() );
|
||||||
std::vector<unsigned char> out;
|
std::vector<unsigned char> out;
|
||||||
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
if( !DecodeBase58( base58_str.c_str(), out ) ) {
|
||||||
FC_THROW_EXCEPTION( exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
FC_THROW_EXCEPTION( parse_error_exception, "Unable to decode base58 string ${base58_str}", ("base58_str",base58_str) );
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy( out_data, out.data(), out.size() );
|
memcpy( out_data, out.data(), out.size() );
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
# ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
@ -495,4 +499,101 @@ namespace fc {
|
||||||
return appCurrentPath;
|
return appCurrentPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
class simple_lock_file::impl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE file_handle;
|
||||||
|
#else
|
||||||
|
int file_handle;
|
||||||
|
#endif
|
||||||
|
bool is_locked;
|
||||||
|
path lock_file_path;
|
||||||
|
|
||||||
|
impl(const path& lock_file_path);
|
||||||
|
~impl();
|
||||||
|
|
||||||
|
bool try_lock();
|
||||||
|
void unlock();
|
||||||
|
};
|
||||||
|
|
||||||
|
simple_lock_file::impl::impl(const path& lock_file_path) :
|
||||||
|
is_locked(false),
|
||||||
|
lock_file_path(lock_file_path),
|
||||||
|
#ifdef _WIN32
|
||||||
|
file_handle(INVALID_HANDLE_VALUE)
|
||||||
|
#else
|
||||||
|
file_handle(-1)
|
||||||
|
#endif
|
||||||
|
{}
|
||||||
|
|
||||||
|
simple_lock_file::impl::~impl()
|
||||||
|
{
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_lock_file::impl::try_lock()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE fh = CreateFileA(lock_file_path.to_native_ansi_path().c_str(),
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0, 0,
|
||||||
|
OPEN_ALWAYS, 0, NULL);
|
||||||
|
if (fh == INVALID_HANDLE_VALUE)
|
||||||
|
return false;
|
||||||
|
is_locked = true;
|
||||||
|
file_handle = fh;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
int fd = open(lock_file_path.string().c_str(), O_RDWR|O_CREAT, 0644);
|
||||||
|
if (fd < 0)
|
||||||
|
return false;
|
||||||
|
if (flock(fd, LOCK_EX|LOCK_NB) == -1)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
is_locked = true;
|
||||||
|
file_handle = fd;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void simple_lock_file::impl::unlock()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
CloseHandle(file_handle);
|
||||||
|
file_handle = INVALID_HANDLE_VALUE;
|
||||||
|
is_locked = false;
|
||||||
|
#else
|
||||||
|
flock(file_handle, LOCK_UN);
|
||||||
|
close(file_handle);
|
||||||
|
file_handle = -1;
|
||||||
|
is_locked = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
simple_lock_file::simple_lock_file(const path& lock_file_path) :
|
||||||
|
my(new impl(lock_file_path))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_lock_file::~simple_lock_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_lock_file::try_lock()
|
||||||
|
{
|
||||||
|
return my->try_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void simple_lock_file::unlock()
|
||||||
|
{
|
||||||
|
my->unlock();
|
||||||
|
}
|
||||||
|
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <fc/thread/scoped_lock.hpp>
|
#include <fc/thread/scoped_lock.hpp>
|
||||||
#include <fc/log/console_appender.hpp>
|
#include <fc/log/console_appender.hpp>
|
||||||
#include <fc/log/file_appender.hpp>
|
#include <fc/log/file_appender.hpp>
|
||||||
|
#include <fc/log/gelf_appender.hpp>
|
||||||
#include <fc/variant.hpp>
|
#include <fc/variant.hpp>
|
||||||
#include "console_defines.h"
|
#include "console_defines.h"
|
||||||
|
|
||||||
|
|
@ -45,4 +46,6 @@ namespace fc {
|
||||||
|
|
||||||
static bool reg_console_appender = appender::register_appender<console_appender>( "console" );
|
static bool reg_console_appender = appender::register_appender<console_appender>( "console" );
|
||||||
static bool reg_file_appender = appender::register_appender<file_appender>( "file" );
|
static bool reg_file_appender = appender::register_appender<file_appender>( "file" );
|
||||||
|
static bool reg_gelf_appender = appender::register_appender<gelf_appender>( "gelf" );
|
||||||
|
|
||||||
} // namespace fc
|
} // namespace fc
|
||||||
|
|
|
||||||
139
src/log/gelf_appender.cpp
Normal file
139
src/log/gelf_appender.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
#include <fc/network/udp_socket.hpp>
|
||||||
|
#include <fc/network/ip.hpp>
|
||||||
|
#include <fc/network/resolve.hpp>
|
||||||
|
#include <fc/exception/exception.hpp>
|
||||||
|
#include <fc/log/gelf_appender.hpp>
|
||||||
|
#include <fc/reflect/variant.hpp>
|
||||||
|
#include <fc/thread/scoped_lock.hpp>
|
||||||
|
#include <fc/thread/thread.hpp>
|
||||||
|
#include <fc/variant.hpp>
|
||||||
|
#include <fc/io/json.hpp>
|
||||||
|
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <queue>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace fc
|
||||||
|
{
|
||||||
|
|
||||||
|
class gelf_appender::impl : public retainable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
config cfg;
|
||||||
|
optional<ip::endpoint> gelf_endpoint;
|
||||||
|
udp_socket gelf_socket;
|
||||||
|
boost::mutex socket_mutex;
|
||||||
|
|
||||||
|
impl(const config& c) :
|
||||||
|
cfg(c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~impl()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
gelf_appender::gelf_appender(const variant& args) :
|
||||||
|
my(new impl(args.as<config>()))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// if it's a numeric address:port, this will parse it
|
||||||
|
my->gelf_endpoint = ip::endpoint::from_string(my->cfg.endpoint);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (!my->gelf_endpoint)
|
||||||
|
{
|
||||||
|
// couldn't parse as a numeric ip address, try resolving as a DNS name.
|
||||||
|
// This can yield, so don't do it in the catch block above
|
||||||
|
string::size_type colon_pos = my->cfg.endpoint.find(':');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
uint16_t port = boost::lexical_cast<uint16_t>(my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size()));
|
||||||
|
|
||||||
|
string hostname = my->cfg.endpoint.substr( 0, colon_pos );
|
||||||
|
std::vector<ip::endpoint> endpoints = resolve(hostname, port);
|
||||||
|
if (endpoints.empty())
|
||||||
|
FC_THROW_EXCEPTION(unknown_host_exception, "The host name can not be resolved: ${hostname}",
|
||||||
|
("hostname", hostname));
|
||||||
|
my->gelf_endpoint = endpoints.back();
|
||||||
|
}
|
||||||
|
catch (const boost::bad_lexical_cast&)
|
||||||
|
{
|
||||||
|
FC_THROW("Bad port: ${port}", ("port", my->cfg.endpoint.substr(colon_pos + 1, my->cfg.endpoint.size())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my->gelf_endpoint)
|
||||||
|
my->gelf_socket.open();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
std::cerr << "error opening GELF socket to endpoint ${endpoint}" << my->cfg.endpoint << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gelf_appender::~gelf_appender()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void gelf_appender::log(const log_message& message)
|
||||||
|
{
|
||||||
|
if (!my->gelf_endpoint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_context context = message.get_context();
|
||||||
|
|
||||||
|
mutable_variant_object gelf_message;
|
||||||
|
gelf_message["version"] = "1.1";
|
||||||
|
gelf_message["host"] = my->cfg.host;
|
||||||
|
gelf_message["short_message"] = format_string(message.get_format(), message.get_data());
|
||||||
|
|
||||||
|
gelf_message["timestamp"] = context.get_timestamp().time_since_epoch().count() / 1000000.;
|
||||||
|
|
||||||
|
switch (context.get_log_level())
|
||||||
|
{
|
||||||
|
case log_level::debug:
|
||||||
|
gelf_message["level"] = 7; // debug
|
||||||
|
break;
|
||||||
|
case log_level::info:
|
||||||
|
gelf_message["level"] = 6; // info
|
||||||
|
break;
|
||||||
|
case log_level::warn:
|
||||||
|
gelf_message["level"] = 4; // warning
|
||||||
|
break;
|
||||||
|
case log_level::error:
|
||||||
|
gelf_message["level"] = 3; // error
|
||||||
|
break;
|
||||||
|
case log_level::all:
|
||||||
|
case log_level::off:
|
||||||
|
// these shouldn't be used in log messages, but do something deterministic just in case
|
||||||
|
gelf_message["level"] = 6; // info
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context.get_context().empty())
|
||||||
|
gelf_message["context"] = context.get_context();
|
||||||
|
gelf_message["_line"] = context.get_line_number();
|
||||||
|
gelf_message["_file"] = context.get_file();
|
||||||
|
gelf_message["_method_name"] = context.get_method();
|
||||||
|
gelf_message["_thread_name"] = context.get_thread_name();
|
||||||
|
if (!context.get_task_name().empty())
|
||||||
|
gelf_message["_task_name"] = context.get_task_name();
|
||||||
|
|
||||||
|
string gelf_message_as_string = json::to_string(gelf_message);
|
||||||
|
std::shared_ptr<char> send_buffer(new char[gelf_message_as_string.size()], [](char* p){ delete[] p; });
|
||||||
|
memcpy(send_buffer.get(), gelf_message_as_string.c_str(), gelf_message_as_string.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
scoped_lock<boost::mutex> lock(my->socket_mutex);
|
||||||
|
my->gelf_socket.send_to(send_buffer, gelf_message_as_string.size(), *my->gelf_endpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // fc
|
||||||
|
|
@ -83,7 +83,9 @@ namespace fc
|
||||||
|
|
||||||
void log_context::append_context( const fc::string& s )
|
void log_context::append_context( const fc::string& s )
|
||||||
{
|
{
|
||||||
my->context += "->" + s;
|
if (!my->context.empty())
|
||||||
|
my->context += " -> ";
|
||||||
|
my->context += s;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_context::~log_context(){}
|
log_context::~log_context(){}
|
||||||
|
|
@ -158,6 +160,7 @@ namespace fc
|
||||||
string log_context::get_host_name()const { return my->hostname; }
|
string log_context::get_host_name()const { return my->hostname; }
|
||||||
time_point log_context::get_timestamp()const { return my->timestamp; }
|
time_point log_context::get_timestamp()const { return my->timestamp; }
|
||||||
log_level log_context::get_log_level()const{ return my->level; }
|
log_level log_context::get_log_level()const{ return my->level; }
|
||||||
|
string log_context::get_context()const { return my->context; }
|
||||||
|
|
||||||
|
|
||||||
variant log_context::to_variant()const
|
variant log_context::to_variant()const
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace fc { namespace http {
|
||||||
case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break;
|
case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break;
|
||||||
case fc::http::reply::NotFound: ss << "Not Found\r\n"; break;
|
case fc::http::reply::NotFound: ss << "Not Found\r\n"; break;
|
||||||
case fc::http::reply::Found: ss << "Found\r\n"; break;
|
case fc::http::reply::Found: ss << "Found\r\n"; break;
|
||||||
case fc::http::reply::InternalServerError: ss << "Internal Server Error\r\n"; break;
|
default: ss << "Internal Server Error\r\n"; break;
|
||||||
}
|
}
|
||||||
for( uint32_t i = 0; i < rep.headers.size(); ++i ) {
|
for( uint32_t i = 0; i < rep.headers.size(); ++i ) {
|
||||||
ss << rep.headers[i].key <<": "<<rep.headers[i].val <<"\r\n";
|
ss << rep.headers[i].key <<": "<<rep.headers[i].val <<"\r\n";
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ namespace fc { namespace rpc {
|
||||||
*_out << ",\"result\":";
|
*_out << ",\"result\":";
|
||||||
json::to_stream( *_out, result);
|
json::to_stream( *_out, result);
|
||||||
*_out << "}\n";
|
*_out << "}\n";
|
||||||
|
_out->flush();
|
||||||
}
|
}
|
||||||
_out->flush();
|
|
||||||
}
|
}
|
||||||
void send_error( variant id, fc::exception& e )
|
void send_error( variant id, fc::exception& e )
|
||||||
{
|
{
|
||||||
|
|
@ -59,9 +59,9 @@ namespace fc { namespace rpc {
|
||||||
*_out <<",\"code\":0,\"data\":";
|
*_out <<",\"code\":0,\"data\":";
|
||||||
json::to_stream( *_out, variant(e));
|
json::to_stream( *_out, variant(e));
|
||||||
*_out << "}}\n";
|
*_out << "}}\n";
|
||||||
|
_out->flush();
|
||||||
}
|
}
|
||||||
//wlog( "exception: ${except}", ("except", variant(e)) );
|
//wlog( "exception: ${except}", ("except", variant(e)) );
|
||||||
_out->flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_message( const variant_object& obj )
|
void handle_message( const variant_object& obj )
|
||||||
|
|
@ -306,8 +306,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",\"params\":";
|
*my->_out << ",\"params\":";
|
||||||
fc::json::to_stream( *my->_out, named_args );
|
fc::json::to_stream( *my->_out, named_args );
|
||||||
*my->_out << "}\n";
|
*my->_out << "}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
}
|
}
|
||||||
void json_connection::notice( const fc::string& method )
|
void json_connection::notice( const fc::string& method )
|
||||||
{
|
{
|
||||||
|
|
@ -316,8 +316,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << "{\"method\":";
|
*my->_out << "{\"method\":";
|
||||||
json::to_stream( *my->_out, method );
|
json::to_stream( *my->_out, method );
|
||||||
*my->_out << "}\n";
|
*my->_out << "}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -342,8 +342,8 @@ namespace fc { namespace rpc {
|
||||||
{
|
{
|
||||||
*my->_out << ",\"params\":[]}\n";
|
*my->_out << ",\"params\":[]}\n";
|
||||||
}
|
}
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -361,8 +361,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",\"params\":[";
|
*my->_out << ",\"params\":[";
|
||||||
fc::json::to_stream( *my->_out, a1 );
|
fc::json::to_stream( *my->_out, a1 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2 )
|
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2 )
|
||||||
|
|
@ -381,8 +381,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a2 );
|
fc::json::to_stream( *my->_out, a2 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3 )
|
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3 )
|
||||||
|
|
@ -403,8 +403,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a3 );
|
fc::json::to_stream( *my->_out, a3 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -428,8 +428,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a4 );
|
fc::json::to_stream( *my->_out, a4 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -455,8 +455,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a5 );
|
fc::json::to_stream( *my->_out, a5 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,8 +484,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a6 );
|
fc::json::to_stream( *my->_out, a6 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5, const variant& a6, const variant& a7 )
|
future<variant> json_connection::async_call( const fc::string& method, const variant& a1, const variant& a2, const variant& a3, const variant& a4, const variant& a5, const variant& a6, const variant& a7 )
|
||||||
|
|
@ -514,8 +514,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a7 );
|
fc::json::to_stream( *my->_out, a7 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method,
|
future<variant> json_connection::async_call( const fc::string& method,
|
||||||
|
|
@ -554,8 +554,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a8 );
|
fc::json::to_stream( *my->_out, a8 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method,
|
future<variant> json_connection::async_call( const fc::string& method,
|
||||||
|
|
@ -597,8 +597,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a9 );
|
fc::json::to_stream( *my->_out, a9 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method,
|
future<variant> json_connection::async_call( const fc::string& method,
|
||||||
|
|
@ -643,8 +643,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",";
|
*my->_out << ",";
|
||||||
fc::json::to_stream( *my->_out, a10 );
|
fc::json::to_stream( *my->_out, a10 );
|
||||||
*my->_out << "]}\n";
|
*my->_out << "]}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -665,8 +665,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",\"params\":";
|
*my->_out << ",\"params\":";
|
||||||
fc::json::to_stream( *my->_out, named_args );
|
fc::json::to_stream( *my->_out, named_args );
|
||||||
*my->_out << "}\n";
|
*my->_out << "}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
future<variant> json_connection::async_call( const fc::string& method )
|
future<variant> json_connection::async_call( const fc::string& method )
|
||||||
|
|
@ -680,8 +680,8 @@ namespace fc { namespace rpc {
|
||||||
*my->_out << ",\"method\":";
|
*my->_out << ",\"method\":";
|
||||||
json::to_stream( *my->_out, method );
|
json::to_stream( *my->_out, method );
|
||||||
*my->_out << "}\n";
|
*my->_out << "}\n";
|
||||||
|
my->_out->flush();
|
||||||
}
|
}
|
||||||
my->_out->flush();
|
|
||||||
return my->_awaiting[id];
|
return my->_awaiting[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue