00001
00002
00003 #ifndef AITOOLS_BIGHASHMAP_CORE_EXTERNAL_MAP_HPP
00004 #define AITOOLS_BIGHASHMAP_CORE_EXTERNAL_MAP_HPP
00005
00006 #include <mutex>
00007 #include <cmph.h>
00008 #include <boost/filesystem/fstream.hpp>
00009
00010 #include "core/cmph_map.hpp"
00011 #include "util/logging.hpp"
00012 #include "util/checksum.hpp"
00013 #include "util/systemio.hpp"
00014 #include "value/pair.hpp"
00015 #include "value/pair_traits.hpp"
00016
00017 namespace bfs = boost::filesystem;
00018
00019 namespace aitools {
00020 namespace bighashmap {
00021 namespace core {
00022
00042 template <typename T>
00043 class external_map : public cmph_map<T> {
00044
00045 public:
00046
00047 typedef cmph_map<T> base_type;
00048 typedef typename base_type::key_type key_type;
00049 typedef typename base_type::value_type value_type;
00050 typedef typename base_type::checksum_type checksum_type;
00051
00052 private:
00053
00054 typedef value::pair<checksum_type, value_type> entry_type;
00055 typedef value::value_traits<entry_type> entry_traits;
00056
00057 private:
00058
00059 external_map()
00060 : base_type() {}
00061
00062 external_map(const bfs::path& mph_file, const bfs::path& dat_file)
00063 : base_type(mph_file)
00064 {
00065 data_ = util::fopen(dat_file, "rb");
00066 }
00067
00068 public:
00069
00070 ~external_map()
00071 {
00072 util::fclose(data_);
00073 }
00074
00075 public:
00076
00077 static external_map*
00078 open(const bfs::path& idx_file)
00079 {
00080 bfs::ifstream ifs(idx_file);
00081 if (!ifs)
00082 {
00083 util::throw_runtime_error("Cannot open", idx_file);
00084 }
00085 std::string mph_file;
00086 std::string dat_file;
00087 std::getline(ifs, mph_file);
00088 std::getline(ifs, dat_file);
00089 return new external_map(idx_file.parent_path() / mph_file,
00090 idx_file.parent_path() / dat_file);
00091 }
00092
00093 public:
00094
00095 bool
00096 find(const key_type& key, value_type& value)
00097 {
00098 entry_type entry;
00099 const uint64_t offset(hash(key) * entry_traits::size_of(entry));
00100
00101 #ifdef THREAD_SAFE
00102 std::lock_guard<std::mutex> lg(mutex_);
00103 #endif
00104
00105
00106 util::fseek(data_, offset, SEEK_SET);
00107
00108 if (!entry_traits::read_from(entry, data_))
00109 {
00110 util::log_error("Key", key);
00111 util::log_error("File offset", offset);
00112 util::throw_runtime_error("entry_traits::read_from failed");
00113 }
00114
00115 const checksum_type checksum(util::hash<checksum_type>(key));
00116 if (entry.e1() != checksum)
00117 {
00118
00119 log_debug(__FILE__, __LINE__, "Key", key);
00120 log_debug(__FILE__, __LINE__, "File offset", offset);
00121 log_debug(__FILE__, __LINE__, "Actual checksum", checksum);
00122 log_debug(__FILE__, __LINE__, "Expected checksum", entry.e1());
00123 return false;
00124 }
00125 value = entry.e2();
00126 return true;
00127 }
00128
00129 private:
00130
00131 FILE* data_;
00132
00133 #ifdef THREAD_SAFE
00134 std::mutex mutex_;
00135 #endif
00136
00137 };
00138
00139 }
00140 }
00141 }
00142
00143 #endif // AITOOLS_BIGHASHMAP_CORE_EXTERNAL_MAP_HPP