00001
00002
00003 #ifndef AITOOLS_BIGHASHMAP_CORE_INTERNAL_MAP_HPP
00004 #define AITOOLS_BIGHASHMAP_CORE_INTERNAL_MAP_HPP
00005
00006 #include <boost/filesystem/fstream.hpp>
00007
00008 #include "core/cmph_map.hpp"
00009 #include "util/logging.hpp"
00010 #include "util/checksum.hpp"
00011 #include "util/systemio.hpp"
00012 #include "value/pair.hpp"
00013 #include "value/pair_traits.hpp"
00014
00015 namespace bfs = boost::filesystem;
00016
00017 namespace aitools {
00018 namespace bighashmap {
00019 namespace core {
00020
00025 template <typename T>
00026 class internal_map : public cmph_map<T> {
00027
00028 public:
00029
00030 typedef cmph_map<T> base_type;
00031 typedef typename base_type::key_type key_type;
00032 typedef typename base_type::value_type value_type;
00033 typedef typename base_type::checksum_type checksum_type;
00034
00035 private:
00036
00037 typedef value::pair<checksum_type, value_type> entry_type;
00038 typedef value::value_traits<entry_type> entry_traits;
00039
00040 private:
00041
00042 internal_map()
00043 : base_type() {}
00044
00045 internal_map(const bfs::path& mph_file, const bfs::path& dat_file)
00046 : base_type(mph_file)
00047 {
00048 const entry_type entry;
00049 data_ = static_cast<char*>(
00050 std::calloc(this->size(), entry_traits::size_of(entry)));
00051 if (data_ == NULL)
00052 {
00053 util::throw_runtime_error("Cannot allocate memory",
00054 this->size() * entry_traits::size_of(entry));
00055 }
00056 FILE* dat_rfs(util::fopen(dat_file, "rb"));
00057 util::fread(data_, entry_traits::size_of(entry), this->size(), dat_rfs);
00058 util::fclose(dat_rfs);
00059 }
00060
00061 public:
00062
00063 ~internal_map()
00064 {
00065 std::free(data_);
00066 }
00067
00068 public:
00069
00070 static internal_map*
00071 open(const bfs::path& idx_file)
00072 {
00073 bfs::ifstream ifs(idx_file);
00074 if (!ifs)
00075 {
00076 util::throw_runtime_error("Cannot open", idx_file);
00077 }
00078 std::string mph_file;
00079 std::string dat_file;
00080 std::getline(ifs, mph_file);
00081 std::getline(ifs, dat_file);
00082 return new internal_map(idx_file.parent_path() / mph_file,
00083 idx_file.parent_path() / dat_file);
00084 }
00085
00086 public:
00087
00088 bool
00089 find(const key_type& key, value_type& value)
00090 {
00091 entry_type entry;
00092 const uint64_t offset(hash(key) * entry_traits::size_of(entry));
00093
00094 entry_traits::copy_from(entry, data_ + offset);
00095
00096 const checksum_type checksum(util::hash<checksum_type>(key));
00097 if (entry.e1() != checksum)
00098 {
00099
00100 log_debug(__FILE__, __LINE__, "Key", key);
00101 log_debug(__FILE__, __LINE__, "Memory offset", offset);
00102 log_debug(__FILE__, __LINE__, "Actual checksum", checksum);
00103 log_debug(__FILE__, __LINE__, "Expected checksum", entry.e1());
00104 return false;
00105 }
00106 value = entry.e2();
00107 return true;
00108 }
00109
00110 private:
00111
00112 char* data_;
00113
00114 };
00115
00116 }
00117 }
00118 }
00119
00120 #endif // AITOOLS_BIGHASHMAP_CORE_INTERNAL_MAP_HPP