Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'generator/data_cache_file.hpp')
-rw-r--r--generator/data_cache_file.hpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/generator/data_cache_file.hpp b/generator/data_cache_file.hpp
new file mode 100644
index 0000000000..086b70804b
--- /dev/null
+++ b/generator/data_cache_file.hpp
@@ -0,0 +1,254 @@
+#pragma once
+
+#include "../indexer/file_reader_stream.hpp"
+#include "../indexer/file_writer_stream.hpp"
+#include "../indexer/osm_decl.hpp"
+
+#include "../coding/file_reader.hpp"
+#include "../coding/file_writer.hpp"
+
+#include "../base/logging.hpp"
+
+#include "../std/utility.hpp"
+#include "../std/vector.hpp"
+#include "../std/algorithm.hpp"
+#include "../std/limits.hpp"
+#include "../std/exception.hpp"
+
+
+/// Classes for reading and writing any data in file with map of offsets for
+/// fast searching in memory by some user-id.
+namespace cache
+{
+ namespace detail
+ {
+ template <class TFile, class TValue> class file_map_t
+ {
+ typedef pair<uint64_t, TValue> element_t;
+ typedef vector<element_t> id_cont_t;
+ id_cont_t m_memory;
+ TFile m_file;
+
+ static const size_t s_max_count = 1024;
+
+ struct element_less_t
+ {
+ bool operator() (element_t const & r1, element_t const & r2) const
+ {
+ return ((r1.first == r2.first) ? r1.second < r2.second : r1.first < r2.first);
+ }
+ bool operator() (element_t const & r1, uint64_t r2) const
+ {
+ return (r1.first < r2);
+ }
+ bool operator() (uint64_t r1, element_t const & r2) const
+ {
+ return (r1 < r2.first);
+ }
+ };
+
+ size_t uint64_to_size(uint64_t v)
+ {
+ ASSERT ( v < numeric_limits<size_t>::max(), ("Value to long for memory address : ", v) );
+ return static_cast<size_t>(v);
+ }
+
+ public:
+ file_map_t(string const & name) : m_file(name.c_str()) {}
+
+ string get_name() const { return m_file.GetName(); }
+
+ void flush_to_file()
+ {
+ if (!m_memory.empty())
+ {
+ m_file.Write(&m_memory[0], m_memory.size() * sizeof(element_t));
+ m_memory.clear();
+ }
+ }
+
+ void read_to_memory()
+ {
+ m_memory.clear();
+ uint64_t const fileSize = m_file.Size();
+ if (fileSize == 0) return;
+
+ LOG_SHORT(LINFO, ("Reading offsets started in file ", get_name()));
+
+ try
+ {
+ m_memory.resize(uint64_to_size(fileSize / sizeof(element_t)));
+ }
+ catch (exception const &) // bad_alloc
+ {
+ LOG(LCRITICAL, ("Insufficient memory for required offset map"));
+ }
+
+ m_file.Read(0, &m_memory[0], uint64_to_size(fileSize));
+
+ sort(m_memory.begin(), m_memory.end(), element_less_t());
+
+ LOG_SHORT(LINFO, ("Reading offsets finished"));
+ }
+
+ void write(uint64_t k, TValue const & v)
+ {
+ if (m_memory.size() > s_max_count)
+ flush_to_file();
+
+ m_memory.push_back(make_pair(k, v));
+ }
+
+ bool read_one(uint64_t k, TValue & v) const
+ {
+ typename id_cont_t::const_iterator i =
+ lower_bound(m_memory.begin(), m_memory.end(), k, element_less_t());
+ if ((i != m_memory.end()) && ((*i).first == k))
+ {
+ v = (*i).second;
+ return true;
+ }
+ return false;
+ }
+
+ typedef typename id_cont_t::const_iterator iter_t;
+ pair<iter_t, iter_t> GetRange(uint64_t k) const
+ {
+ return equal_range(m_memory.begin(), m_memory.end(), k, element_less_t());
+ }
+
+ template <class ToDo> void for_each_ret(uint64_t k, ToDo & toDo) const
+ {
+ pair<iter_t, iter_t> range = GetRange(k);
+ for (; range.first != range.second; ++range.first)
+ if (toDo((*range.first).second))
+ return;
+ }
+ };
+ }
+
+ template <class TStream, class TOffsetFile> class DataFileBase
+ {
+ public:
+ typedef uint64_t user_id_t;
+
+ protected:
+ TStream m_stream;
+ detail::file_map_t<TOffsetFile, uint64_t> m_offsets;
+
+ public:
+ DataFileBase(string const & name)
+ : m_stream(name.c_str()), m_offsets(name + OFFSET_EXT)
+ {
+ }
+ };
+
+ class DataFileWriter : public DataFileBase<FileWriterStream, FileWriter>
+ {
+ typedef DataFileBase<FileWriterStream, FileWriter> base_type;
+
+ static const size_t s_max_count = 1024;
+
+ public:
+ DataFileWriter(string const & name) : base_type(name) {}
+
+ template <class T> void Write(user_id_t id, T const & t)
+ {
+ m_offsets.write(id, m_stream.Pos());
+ m_stream << t;
+ }
+
+ void SaveOffsets()
+ {
+ m_offsets.flush_to_file();
+ }
+ };
+
+ class DataFileReader : public DataFileBase<FileReaderStream, FileReader>
+ {
+ typedef DataFileBase<FileReaderStream, FileReader> base_type;
+
+ public:
+ DataFileReader(string const & name) : base_type(name) {}
+
+ template <class T> bool Read(user_id_t id, T & t)
+ {
+ uint64_t pos;
+ if (m_offsets.read_one(id, pos))
+ {
+ m_stream.Seek(pos);
+ m_stream >> t;
+ return true;
+ }
+ else
+ {
+ LOG_SHORT(LWARNING, ("Can't find offset in file ", m_offsets.get_name(), " by id ", id) );
+ return false;
+ }
+ }
+
+ void LoadOffsets()
+ {
+ m_offsets.read_to_memory();
+ }
+ };
+
+ class MappedWay
+ {
+ public:
+
+ enum WayType
+ {
+ coast_direct = 0,
+ empty_direct = 1,
+ coast_opposite = 2,
+ empty_opposite = 3
+ };
+
+ MappedWay() : m_id(0) {}
+ MappedWay(uint64_t id, WayType type) : m_id((id << 2) | type)
+ {
+ CHECK_EQUAL(0, id & 0xC000000000000000ULL, ("Highest 2 bits should be 0.", id));
+ }
+
+ bool operator<(MappedWay const & r) const
+ {
+ return m_id < r.m_id;
+ }
+
+ uint64_t GetId() const { return m_id >> 2; }
+ WayType GetType() const { return static_cast<WayType>(m_id & 3); }
+
+ private:
+ uint64_t m_id;
+ };
+ STATIC_ASSERT(sizeof(MappedWay) == 8);
+
+ template <class TNodesHolder, class TData, class TFile>
+ class BaseFileHolder
+ {
+ protected:
+ typedef typename TData::user_id_t user_id_t;
+
+ TNodesHolder & m_nodes;
+
+ TData m_ways, m_relations;
+
+ typedef detail::file_map_t<TFile, uint64_t> offset_map_t;
+ offset_map_t m_nodes2rel, m_ways2rel;
+
+ typedef detail::file_map_t<TFile, MappedWay> ways_map_t;
+ ways_map_t m_mappedWays;
+
+ public:
+ BaseFileHolder(TNodesHolder & nodes, string const & dir)
+ : m_nodes(nodes),
+ m_ways(dir + WAYS_FILE),
+ m_relations(dir + RELATIONS_FILE),
+ m_nodes2rel(dir + NODES_FILE + ID2REL_EXT),
+ m_ways2rel(dir + WAYS_FILE + ID2REL_EXT),
+ m_mappedWays(dir + MAPPED_WAYS)
+ {
+ }
+ };
+}