From 58d950b56f5d3fd434534860560d4489a768622f Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 3 Jul 2013 21:35:30 -0400 Subject: [PATCH] Adding mmap_struct & features to fc::array Fixed uninit bug in logger_config --- CMakeLists.txt | 1 + include/fc/array.hpp | 20 ++++++++ include/fc/interprocess/file_mapping.hpp | 1 + include/fc/interprocess/mmap_struct.hpp | 59 ++++++++++++++++++++++++ src/interprocess/mmap_struct.cpp | 31 +++++++++++++ src/log/logger_config.cpp | 2 +- 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 include/fc/interprocess/mmap_struct.hpp create mode 100644 src/interprocess/mmap_struct.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d59044a..2ffda6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ set( fc_sources src/filesystem.cpp src/interprocess/process.cpp src/interprocess/file_mapping.cpp + src/interprocess/mmap_struct.cpp src/rpc/json_connection.cpp src/log/log_message.cpp src/log/logger.cpp diff --git a/include/fc/array.hpp b/include/fc/array.hpp index 1533182..2a2002b 100644 --- a/include/fc/array.hpp +++ b/include/fc/array.hpp @@ -4,15 +4,35 @@ namespace fc { + /** + * Provides a fixed size array that is easier for templates to specialize + * against or overload than T[N]. + */ template class array { public: + /** + * Checked indexing (when in debug build) that also simplifies dereferencing + * when you have an array*. + */ + ///@{ + T& at( size_t pos ) { assert( pos < N); return data[pos]; } + const T& at( size_t pos )const { assert( pos < N); return data[pos]; } + ///@} + + T* begin() { return &data[0]; } + const T* begin()const { return &data[0]; } + const T* end()const { return &data[N]; } + + size_t size()const { return N; } + T data[N]; }; template bool operator == ( const array& a, const array& b ) { return 0 == memcmp( a.data, b.data, N ); } + template bool operator != ( const array& a, const array& b ) { return 0 != memcmp( a.data, b.data, N ); } diff --git a/include/fc/interprocess/file_mapping.hpp b/include/fc/interprocess/file_mapping.hpp index 00863e8..051dece 100644 --- a/include/fc/interprocess/file_mapping.hpp +++ b/include/fc/interprocess/file_mapping.hpp @@ -23,6 +23,7 @@ namespace fc { friend class mapped_region; fc::fwd my; }; + class mapped_region { public: mapped_region( const file_mapping& fm, mode_t m, uint64_t start, size_t size ); diff --git a/include/fc/interprocess/mmap_struct.hpp b/include/fc/interprocess/mmap_struct.hpp new file mode 100644 index 0000000..34dd8c4 --- /dev/null +++ b/include/fc/interprocess/mmap_struct.hpp @@ -0,0 +1,59 @@ +#pragma once +#include +#include + +namespace fc +{ + class path; + namespace detail + { + /** + * Base class used to hide common implementation details. + */ + class mmap_struct_base + { + public: + size_t size()const { return _mapped_region->get_size(); } + void flush() { _mapped_region->flush(); } + + protected: + void open( const fc::path& file, size_t s, bool create ); + std::unique_ptr _file_mapping; + std::unique_ptr _mapped_region; + }; + }; + + /** + * @class mmap_struct + * @brief A struct that has been mapped from a file. + * + * @note T must be POD + */ + template + class mmap_struct : public detail::mmap_struct_base + { + public: + mmap_struct():_mapped_struct(nullptr){} + /** + * Create the file if it does not exist or is of the wrong size if create is true, then maps + * the file to memory. + * + * @throw an exception if the file does not exist or is the wrong size and create is false + */ + void open( const fc::path& file, bool create = false ) + { + detail::mmap_struct_base::open( file, sizeof(T), create ); + _mapped_struct = (T*)_mapped_region->get_address(); + } + + T* operator->() { return _mapped_struct; } + const T* operator->()const { return _mapped_struct; } + + T& operator*() { return *_mapped_struct; } + const T& operator*()const { return *_mapped_struct; } + + private: + T* _mapped_struct; + }; + +} diff --git a/src/interprocess/mmap_struct.cpp b/src/interprocess/mmap_struct.cpp new file mode 100644 index 0000000..7ae397d --- /dev/null +++ b/src/interprocess/mmap_struct.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +namespace fc +{ + namespace detail + { + void mmap_struct_base::open( const fc::path& file, size_t s, bool create ) + { + if( !fc::exists( file ) || fc::file_size(file) != s ) + { + fc::ofstream out( file ); + char buffer[1024]; + memset( buffer, 0, sizeof(buffer) ); + + size_t bytes_left = s; + while( bytes_left > 0 ) + { + size_t to_write = std::min(bytes_left, sizeof(buffer) ); + out.write( buffer, to_write ); + bytes_left -= to_write; + } + } + _file_mapping.reset( new fc::file_mapping( file.generic_string().c_str(), fc::read_write ) ); + _mapped_region.reset( new fc::mapped_region( *_file_mapping, fc::read_write, 0, s ) ); + } + } // namespace fc + +} // namespace fc diff --git a/src/log/logger_config.cpp b/src/log/logger_config.cpp index 5762b8d..a8fa079 100644 --- a/src/log/logger_config.cpp +++ b/src/log/logger_config.cpp @@ -40,7 +40,7 @@ namespace fc { lgr.set_parent( logger::get( *cfg.loggers[i].parent ) ); } lgr.set_name(cfg.loggers[i].name); - lgr.set_log_level( *cfg.loggers[i].level ); + if( cfg.loggers[i].level ) lgr.set_log_level( *cfg.loggers[i].level ); for( auto a = cfg.loggers[i].appenders.begin(); a != cfg.loggers[i].appenders.end(); ++a ){