libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #ifndef MOOST_IO_VARIABLE_STORE_HPP__ 00029 #define MOOST_IO_VARIABLE_STORE_HPP__ 00030 00031 #include <cmath> 00032 #include <string> 00033 #include <fstream> 00034 #include <stdexcept> 00035 00036 #include <boost/filesystem/path.hpp> 00037 #include <boost/filesystem/operations.hpp> 00038 #include <boost/lexical_cast.hpp> 00039 00040 #include <boost/scoped_array.hpp> 00041 #include <boost/scoped_ptr.hpp> 00042 00043 #include "block_store.hpp" 00044 00045 namespace moost { namespace io { 00046 00049 class variable_store 00050 { 00051 private: 00052 00053 size_t m_min_block_size; 00054 size_t m_max_block_size; 00055 boost::scoped_array< boost::scoped_ptr< block_store > > m_block_stores; 00056 00057 size_t index_from_size(size_t block_size) 00058 { 00059 if (block_size < m_min_block_size) 00060 block_size = m_min_block_size; 00061 else if ( block_size > m_max_block_size ) 00062 throw std::invalid_argument("cannot exceed max block size"); 00063 return static_cast<size_t>( log( static_cast<double>(( block_size * 2 - 1) / m_min_block_size) ) / log(2.0) ); 00064 } 00065 00066 public: 00067 00069 class scoped_block 00070 { 00071 private: 00072 block_store::scoped_block m_scoped_block; 00073 public: 00074 scoped_block(variable_store & variable_store_, 00075 size_t block_size) 00076 : m_scoped_block( * variable_store_.m_block_stores[variable_store_.index_from_size(block_size)]) 00077 { 00078 } 00079 scoped_block(variable_store & variable_store_, 00080 size_t block_size, 00081 size_t index) 00082 : m_scoped_block( * variable_store_.m_block_stores[variable_store_.index_from_size(block_size)], index) 00083 { 00084 } 00085 void free() { m_scoped_block.free(); } 00086 std::fstream & operator * () { return m_scoped_block.operator* (); } 00087 std::fstream * operator ->() { return m_scoped_block.operator->(); } 00088 size_t index() { return m_scoped_block.index(); } 00089 size_t block_size() { return m_scoped_block.block_size(); } 00090 }; 00091 00094 variable_store(const std::string & base_path, 00095 size_t min_block_size = 64, 00096 size_t max_block_size = 16777216, 00097 size_t streams_per_block_size = 8) 00098 : m_min_block_size(min_block_size), 00099 m_max_block_size(max_block_size), 00100 m_block_stores( new boost::scoped_ptr< block_store >[1 + index_from_size(m_max_block_size) ] ) 00101 { 00102 for (int i = 0; min_block_size <= max_block_size; min_block_size *= 2, ++i) 00103 { 00104 boost::filesystem::path p = boost::filesystem::path(base_path) / boost::filesystem::path(boost::lexical_cast<std::string>(min_block_size)); 00105 m_block_stores[i].reset(new block_store(p.string(), min_block_size, streams_per_block_size)); 00106 } 00107 } 00108 }; 00109 00110 }} // moost::io 00111 00112 #endif // MOOST_IO_VARIABLE_STORE_HPP__