diff options
author | Sergey Yershov <yershov@corp.mail.ru> | 2015-01-27 20:14:23 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:38:04 +0300 |
commit | 9372d0a8ca30aa4e497ed677e155b9e6ed040b75 (patch) | |
tree | 27b1983ca34d30dd4b132eec883b52a1c9de8fcb /generator | |
parent | 418ef1202ff93eec26b2aa0c5c3a63df0ab8c3c6 (diff) |
Refactoring work with nodes storage
Added new methods storing intermediate points data to disk
Added support for storing coordinates as two signed ints instead two doubles
Diffstat (limited to 'generator')
-rw-r--r-- | generator/data_generator.cpp | 67 | ||||
-rw-r--r-- | generator/data_generator.hpp | 2 | ||||
-rw-r--r-- | generator/feature_generator.cpp | 100 | ||||
-rw-r--r-- | generator/feature_generator.hpp | 2 | ||||
-rw-r--r-- | generator/generator_tool/generator_tool.cpp | 26 | ||||
-rw-r--r-- | generator/generator_tool/generator_tool.pro | 2 | ||||
-rw-r--r-- | generator/osm2type.cpp | 42 | ||||
-rw-r--r-- | generator/osm_decl.hpp | 18 | ||||
-rw-r--r-- | generator/point_storage.hpp | 448 |
9 files changed, 494 insertions, 213 deletions
diff --git a/generator/data_generator.cpp b/generator/data_generator.cpp index 003ec30116..9fb2d09195 100644 --- a/generator/data_generator.cpp +++ b/generator/data_generator.cpp @@ -7,7 +7,7 @@ #include "../base/logging.hpp" #include "../std/bind.hpp" - +#include "point_storage.hpp" namespace data { @@ -61,56 +61,6 @@ public: } }; - -class points_in_file_base -{ -protected: - FileWriter m_file; - progress_policy m_progress; - -public: - points_in_file_base(string const & name, size_t factor) : m_file(name.c_str()) - { - m_progress.Begin(name, factor); - } - - uint64_t GetCount() const { return m_progress.GetCount(); } -}; - -class points_in_file : public points_in_file_base -{ -public: - points_in_file(string const & name) : points_in_file_base(name, 1000) {} - - void AddPoint(uint64_t id, double lat, double lng) - { - LatLon ll; - ll.lat = lat; - ll.lon = lng; - m_file.Seek(id * sizeof(ll)); - m_file.Write(&ll, sizeof(ll)); - - m_progress.Inc(); - } -}; - -class points_in_file_light : public points_in_file_base -{ -public: - points_in_file_light(string const & name) : points_in_file_base(name, 10000) {} - - void AddPoint(uint64_t id, double lat, double lng) - { - LatLonPos ll; - ll.pos = id; - ll.lat = lat; - ll.lon = lng; - m_file.Write(&ll, sizeof(ll)); - - m_progress.Inc(); - } -}; - template <class TNodesHolder> bool GenerateImpl(string const & dir, string const & osmFileName = string()) { @@ -139,12 +89,19 @@ bool GenerateImpl(string const & dir, string const & osmFileName = string()) return true; } -bool GenerateToFile(string const & dir, bool lightNodes, string const & osmFileName) +bool GenerateToFile(string const & dir, string const & nodeStorage, string const & osmFileName) { - if (lightNodes) - return GenerateImpl<points_in_file_light>(dir, osmFileName); + if (nodeStorage == "raw") + return GenerateImpl<RawFilePointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName); + else if (nodeStorage == "map") + return GenerateImpl<MapFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName); + else if (nodeStorage == "sqlite") + return GenerateImpl<SQLitePointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName); + else if (nodeStorage == "mem") + return GenerateImpl<RawFileShortPointStorage<BasePointStorage::MODE_WRITE>>(dir, osmFileName); else - return GenerateImpl<points_in_file>(dir, osmFileName); + CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage)); + return false; } } diff --git a/generator/data_generator.hpp b/generator/data_generator.hpp index f51789d068..424308a8a6 100644 --- a/generator/data_generator.hpp +++ b/generator/data_generator.hpp @@ -4,5 +4,5 @@ namespace data { - bool GenerateToFile(string const & dir, bool lightNodes, string const & osmFileName = string()); + bool GenerateToFile(string const & dir, string const & nodeStorage, string const & osmFileName); } diff --git a/generator/feature_generator.cpp b/generator/feature_generator.cpp index 10946a7fdd..a24ff104ac 100644 --- a/generator/feature_generator.cpp +++ b/generator/feature_generator.cpp @@ -15,7 +15,6 @@ #include "../indexer/classificator.hpp" #include "../coding/varint.hpp" -#include "../coding/mmap_reader.hpp" #include "../base/assert.hpp" #include "../base/logging.hpp" @@ -25,6 +24,7 @@ #include "../std/unordered_map.hpp" #include "../std/target_os.hpp" +#include "point_storage.hpp" namespace feature { @@ -220,89 +220,6 @@ void FeaturesCollector::operator() (FeatureBuilder1 const & fb) namespace { -class points_in_file -{ -#ifdef OMIM_OS_WINDOWS - FileReader m_file; -#else - MmapReader m_file; -#endif - -public: - points_in_file(string const & name) : m_file(name) {} - - bool GetPoint(uint64_t id, double & lat, double & lng) const - { - // I think, it's not good idea to write this ugly code. - // memcpy isn't to slow for that. -//#ifdef OMIM_OS_WINDOWS - LatLon ll; - m_file.Read(id * sizeof(ll), &ll, sizeof(ll)); -//#else -// LatLon const & ll = *reinterpret_cast<LatLon const *>(m_file.Data() + id * sizeof(ll)); -//#endif - - // assume that valid coordinate is not (0, 0) - if (ll.lat != 0.0 || ll.lon != 0.0) - { - lat = ll.lat; - lng = ll.lon; - return true; - } - else - { - LOG(LERROR, ("Node with id = ", id, " not found!")); - return false; - } - } -}; - -class points_in_map -{ - typedef unordered_map<uint64_t, pair<double, double> > cont_t; - typedef cont_t::const_iterator iter_t; - cont_t m_map; - - static bool equal_coord(double d1, double d2) - { - return ::fabs(d1 - d2) < 1.0E-8; - } - -public: - points_in_map(string const & name) - { - LOG(LINFO, ("Nodes reading is started")); - - FileReader reader(name); - uint64_t const count = reader.Size(); - - uint64_t pos = 0; - while (pos < count) - { - LatLonPos ll; - reader.Read(pos, &ll, sizeof(ll)); - - (void)m_map.insert(make_pair(ll.pos, make_pair(ll.lat, ll.lon))); - - pos += sizeof(ll); - } - - LOG(LINFO, ("Nodes reading is finished")); - } - - bool GetPoint(uint64_t id, double & lat, double & lng) const - { - iter_t i = m_map.find(id); - if (i != m_map.end()) - { - lat = i->second.first; - lng = i->second.second; - return true; - } - return false; - } -}; - class MainFeaturesEmitter { typedef WorldMapGenerator<FeaturesCollector> WorldGenerator; @@ -509,12 +426,19 @@ bool GenerateImpl(GenerateInfo & info, string const & osmFileName = string()) return true; } -bool GenerateFeatures(GenerateInfo & info, bool lightNodes, string const & osmFileName) +bool GenerateFeatures(GenerateInfo & info, string const & nodeStorage, string const & osmFileName) { - if (lightNodes) - return GenerateImpl<points_in_map>(info, osmFileName); + if (nodeStorage == "raw") + return GenerateImpl<RawFilePointStorage<BasePointStorage::MODE_READ>>(info, osmFileName); + else if (nodeStorage == "map") + return GenerateImpl<MapFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileName); + else if (nodeStorage == "sqlite") + return GenerateImpl<SQLitePointStorage<BasePointStorage::MODE_READ>>(info, osmFileName); + else if (nodeStorage == "mem") + return GenerateImpl<RawFileShortPointStorage<BasePointStorage::MODE_READ>>(info, osmFileName); else - return GenerateImpl<points_in_file>(info, osmFileName); + CHECK(nodeStorage.empty(), ("Incorrect node_storage type:", nodeStorage)); + return false; } } diff --git a/generator/feature_generator.hpp b/generator/feature_generator.hpp index ecc4f1ebf2..c0323940f3 100644 --- a/generator/feature_generator.hpp +++ b/generator/feature_generator.hpp @@ -14,7 +14,7 @@ namespace feature { struct GenerateInfo; - bool GenerateFeatures(GenerateInfo & info, bool lightNodes, string const & osmFileName = string()); + bool GenerateFeatures(GenerateInfo & info, string const & nodeStorage, string const & osmFileName); // Writes features to dat file. class FeaturesCollector diff --git a/generator/generator_tool/generator_tool.cpp b/generator/generator_tool/generator_tool.cpp index 55fcad9abf..330375d818 100644 --- a/generator/generator_tool/generator_tool.cpp +++ b/generator/generator_tool/generator_tool.cpp @@ -44,7 +44,7 @@ DEFINE_bool(generate_geometry, false, "3rd pass - split and simplify geometry an DEFINE_bool(generate_index, false, "4rd pass - generate index"); DEFINE_bool(generate_search_index, false, "5th pass - generate search index"); DEFINE_bool(calc_statistics, false, "Calculate feature statistics for specified mwm bucket files"); -DEFINE_bool(use_light_nodes, false, "Use temporary vector of nodes, instead of huge temp file"); +DEFINE_string(node_storage, "raw", "Type of storage for intermediate points representation. Available: raw, map, sqlite, mem"); DEFINE_string(data_path, "", "Working directory, 'path_to_exe/../../data' if empty."); DEFINE_string(output, "", "File name for process (without 'mwm' ext)."); DEFINE_string(intermediate_data_path, "", "Path to stored nodes, ways, relations."); @@ -104,16 +104,8 @@ int main(int argc, char ** argv) if (FLAGS_preprocess_xml) { LOG(LINFO, ("Generating intermediate data ....")); - if (!FLAGS_osm_file_name.empty()) - { - if (!data::GenerateToFile(FLAGS_intermediate_data_path, FLAGS_use_light_nodes, FLAGS_osm_file_name)) - return -1; - } - else - { - if (!data::GenerateToFile(FLAGS_intermediate_data_path, FLAGS_use_light_nodes)) - return -1; - } + if (!data::GenerateToFile(FLAGS_intermediate_data_path, FLAGS_node_storage, FLAGS_osm_file_name)) + return -1; } feature::GenerateInfo genInfo; @@ -156,16 +148,8 @@ int main(int argc, char ** argv) if (!FLAGS_address_file_name.empty()) genInfo.m_addressFile = path + FLAGS_address_file_name; - if (!FLAGS_osm_file_name.empty()) - { - if (!feature::GenerateFeatures(genInfo, FLAGS_use_light_nodes, FLAGS_osm_file_name)) - return -1; - } - else - { - if (!feature::GenerateFeatures(genInfo, FLAGS_use_light_nodes)) - return -1; - } + if (!feature::GenerateFeatures(genInfo, FLAGS_node_storage, FLAGS_osm_file_name)) + return -1; // without --spit_by_polygons, we have empty name country as result - assign it if (genInfo.m_bucketNames.size() == 1 && genInfo.m_bucketNames[0].empty()) diff --git a/generator/generator_tool/generator_tool.pro b/generator/generator_tool/generator_tool.pro index 7a131662a2..3b7a9b7e1a 100644 --- a/generator/generator_tool/generator_tool.pro +++ b/generator/generator_tool/generator_tool.pro @@ -16,7 +16,7 @@ TEMPLATE = app QT *= core win32: LIBS *= -lShell32 -macx-*: LIBS *= "-framework Foundation" +macx-*: LIBS *= "-framework Foundation" -lsqlite3 SOURCES += \ generator_tool.cpp \ diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp index c29c03e089..eb599b9e68 100644 --- a/generator/osm2type.cpp +++ b/generator/osm2type.cpp @@ -247,13 +247,10 @@ namespace ftype ClassifObjectPtr operator() (string const & k, string const & v) const { - if (is_good_tag(k, v)) - { - ClassifObjectPtr p = m_parent->BinaryFind(m_isKey ? k : v); - if (p) - return p; - } - return ClassifObjectPtr(0, 0); + if (!is_good_tag(k, v)) + return ClassifObjectPtr(0, 0); + + return m_parent->BinaryFind(m_isKey ? k : v); } }; @@ -332,9 +329,12 @@ namespace ftype }; } - ClassifObjectPtr find_object(ClassifObject const * parent, XMLElement * p, bool isKey) + ClassifObjectPtr find_object(ClassifObject const * parent, XMLElement * p) { - return for_each_tag(p, do_find_obj(parent, isKey)); + // next objects trying to find by value first + ClassifObjectPtr pObj = for_each_tag(p, do_find_obj(parent, false)); + // if no - try find object by key (in case of k = "area", v = "yes") + return pObj ? pObj : for_each_tag(p, do_find_obj(parent, true)); } size_t ProcessCommonParams(XMLElement * p, FeatureParams & params) @@ -428,28 +428,14 @@ namespace ftype break; // continue find path from last element - do - { - // next objects trying to find by value first - ClassifObjectPtr pObj = find_object(path.back().get(), p, false); - if (!pObj) - { - // if no - try find object by key (in case of k = "area", v = "yes") - pObj = find_object(path.back().get(), p, true); - } - - // add to path or stop search - if (pObj) - path.push_back(pObj); - else - break; - - } while (true); + ClassifObjectPtr pObj; + while ((pObj = find_object(path.back().get(), p))) + path.push_back(pObj); // assign type uint32_t t = ftype::GetEmptyValue(); - for (size_t i = 0; i < path.size(); ++i) - ftype::PushValue(t, path[i].GetIndex()); + for (auto const & e : path) + ftype::PushValue(t, e.GetIndex()); // use features only with drawing rules if (feature::IsDrawableAny(t)) diff --git a/generator/osm_decl.hpp b/generator/osm_decl.hpp index 1bd3ba7e81..9e07884fa7 100644 --- a/generator/osm_decl.hpp +++ b/generator/osm_decl.hpp @@ -10,24 +10,6 @@ #include "../std/bind.hpp" -/// Used to store all world nodes inside temporary index file. -/// To find node by id, just calculate offset inside index file: -/// offset_in_file = sizeof(LatLon) * node_ID -struct LatLon -{ - double lat; - double lon; -}; -STATIC_ASSERT(sizeof(LatLon) == 16); - -struct LatLonPos -{ - uint64_t pos; - double lat; - double lon; -}; -STATIC_ASSERT(sizeof(LatLonPos) == 24); - #define NODES_FILE "nodes.dat" #define WAYS_FILE "ways.dat" #define RELATIONS_FILE "relations.dat" diff --git a/generator/point_storage.hpp b/generator/point_storage.hpp new file mode 100644 index 0000000000..d7e18da733 --- /dev/null +++ b/generator/point_storage.hpp @@ -0,0 +1,448 @@ +#pragma once + +#include "../coding/mmap_reader.hpp" +#include <sqlite3.h> + + +/// Used to store all world nodes inside temporary index file. +/// To find node by id, just calculate offset inside index file: +/// offset_in_file = sizeof(LatLon) * node_ID +struct LatLon +{ + double lat; + double lon; +}; +STATIC_ASSERT(sizeof(LatLon) == 16); + +struct ShortLatLon +{ + int32_t lat; + int32_t lon; +}; +STATIC_ASSERT(sizeof(ShortLatLon) == 8); + +struct LatLonPos +{ + uint64_t pos; + double lat; + double lon; +}; +STATIC_ASSERT(sizeof(LatLonPos) == 24); + +struct ShortLatLonPos +{ + uint64_t pos; + int32_t lat; + int32_t lon; +}; +STATIC_ASSERT(sizeof(ShortLatLonPos) == 16); + + +class BasePointStorage +{ +protected: + // helper for select right initialization function + template <int v> + struct EnableIf + { + enum { value = v }; + }; + + progress_policy m_progress; + +public: + enum EStorageMode {MODE_READ = false, MODE_WRITE = true}; + + BasePointStorage(string const & name, size_t factor) + { + m_progress.Begin(name, factor); + } + + uint64_t GetCount() const { return m_progress.GetCount(); } +}; + +template < BasePointStorage::EStorageMode ModeT > +class SQLitePointStorage : public BasePointStorage +{ + sqlite3 *m_db; + sqlite3_stmt *m_prepared_statement; + +public: + SQLitePointStorage(string const & name) : BasePointStorage(name, 1000) + { + if( sqlite3_open((name+".sqlite").c_str(), &m_db) != SQLITE_OK ){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + InitStorage(EnableIf<ModeT>()); + } + + ~SQLitePointStorage() + { + DoneStorage(EnableIf<ModeT>()); + sqlite3_finalize(m_prepared_statement); + sqlite3_close(m_db); + } + + void InitStorage(EnableIf<MODE_WRITE>) + { + string create_table("drop table if exists points; drop index if exists points_idx; create table points(id integer PRIMARY KEY, ll blob) WITHOUT ROWID;"); + if( sqlite3_exec(m_db, create_table.c_str(), NULL, NULL, NULL ) != SQLITE_OK ){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + + char* errorMessage; + sqlite3_exec(m_db, "PRAGMA synchronous=OFF", NULL, NULL, &errorMessage); + sqlite3_exec(m_db, "PRAGMA count_changes=OFF", NULL, NULL, &errorMessage); + sqlite3_exec(m_db, "PRAGMA journal_mode=MEMORY", NULL, NULL, &errorMessage); + sqlite3_exec(m_db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errorMessage); + + string insert("insert into points(id, ll) values(?,?);"); + if( sqlite3_prepare_v2(m_db, insert.c_str(), -1, &m_prepared_statement, NULL) != SQLITE_OK ){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + if( sqlite3_exec(m_db, "BEGIN TRANSACTION", NULL, NULL, NULL ) != SQLITE_OK ){ + fprintf(stderr, "Can't start transaction: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + } + + void InitStorage(EnableIf<MODE_READ>) + { + string select("select ll from points where id=?;"); + if( sqlite3_prepare_v2(m_db, select.c_str(), -1, &m_prepared_statement, NULL) != SQLITE_OK ){ + fprintf(stderr, "failed sqlite3_prepare_v2: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + } + + void DoneStorage(EnableIf<MODE_WRITE>) + { + if( sqlite3_exec(m_db, "COMMIT TRANSACTION", NULL, NULL, NULL ) != SQLITE_OK ){ + fprintf(stderr, "Can't end transaction: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + if( sqlite3_exec(m_db, "create unique index points_idx on points(id);", NULL, NULL, NULL ) != SQLITE_OK ){ + fprintf(stderr, "Can't end transaction: %s\n", sqlite3_errmsg(m_db)); + sqlite3_close(m_db); + exit(1); + } + } + + void DoneStorage(EnableIf<MODE_READ>) {} + + void AddPoint(uint64_t id, double lat, double lng) + { + LatLon ll = {lat, lng}; + + if (sqlite3_bind_int64(m_prepared_statement, 1, id) != SQLITE_OK) { + cerr << "bind1 failed: " << sqlite3_errmsg(m_db) << endl; + exit(1); + } + if (sqlite3_bind_blob(m_prepared_statement, 2, &ll, sizeof(ll), SQLITE_STATIC) != SQLITE_OK) { + cerr << "bind2 failed: " << sqlite3_errmsg(m_db) << endl; + exit(1); + } + + if (sqlite3_step(m_prepared_statement) != SQLITE_DONE) { + cerr << "execution failed: " << sqlite3_errmsg(m_db) << endl; + exit(1); + } + + sqlite3_reset(m_prepared_statement); + m_progress.Inc(); + } + + bool GetPoint(uint64_t id, double & lat, double & lng) const + { + bool found = true; + if (sqlite3_bind_int64(m_prepared_statement, 1, id) != SQLITE_OK) { + cerr << "bind1 failed: " << sqlite3_errmsg(m_db) << endl; + exit(1); + } + int rc = sqlite3_step(m_prepared_statement); + if (rc == SQLITE_DONE) + { + found = false; + } + else if (rc == SQLITE_ROW) + { + const void * data; + data = sqlite3_column_blob (m_prepared_statement, 0); + LatLon const &ll = *((LatLon const *)data); + lat = ll.lat; + lng = ll.lon; + } + else + { + cerr << "execution failed: " << sqlite3_errmsg(m_db) << endl; + exit(1); + } + + sqlite3_reset(m_prepared_statement); + return found; + } + +}; + +template < BasePointStorage::EStorageMode ModeT > +class RawFilePointStorage : public BasePointStorage +{ + +#ifdef OMIM_OS_WINDOWS + typedef FileReader FileReaderT; +#else + typedef MmapReader FileReaderT; +#endif + + typename std::conditional<ModeT, FileWriter, FileReaderT>::type m_file; + +public: + RawFilePointStorage(string const & name) : BasePointStorage(name, 1000), m_file(name) {} + + template <bool T = (ModeT == BasePointStorage::MODE_WRITE)> + typename std::enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng) + { + LatLon ll; + ll.lat = lat; + ll.lon = lng; + m_file.Seek(id * sizeof(ll)); + m_file.Write(&ll, sizeof(ll)); + + m_progress.Inc(); + } + + template <bool T = (ModeT == BasePointStorage::MODE_READ)> + typename std::enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const + { + // I think, it's not good idea to write this ugly code. + // memcpy isn't to slow for that. + //#ifdef OMIM_OS_WINDOWS + LatLon ll; + m_file.Read(id * sizeof(ll), &ll, sizeof(ll)); + //#else + // LatLon const & ll = *reinterpret_cast<LatLon const *>(m_file.Data() + id * sizeof(ll)); + //#endif + + // assume that valid coordinate is not (0, 0) + if (ll.lat != 0.0 || ll.lon != 0.0) + { + lat = ll.lat; + lng = ll.lon; + return true; + } + else + { + LOG(LERROR, ("Node with id = ", id, " not found!")); + return false; + } + } + +}; + +template < BasePointStorage::EStorageMode ModeT > +class RawFileShortPointStorage : public BasePointStorage +{ + +#ifdef OMIM_OS_WINDOWS + typedef FileReader FileReaderT; +#else + typedef MmapReader FileReaderT; +#endif + + typename std::conditional<ModeT, FileWriter, FileReaderT>::type m_file; + + double const m_precision = 10000000; + +public: + RawFileShortPointStorage(string const & name) : BasePointStorage(name, 1000), m_file(name) {} + + template <bool T = (ModeT == BasePointStorage::MODE_WRITE)> + typename std::enable_if<T, void>::type AddPoint(uint64_t id, double lat, double lng) + { + int64_t const lat64 = lat * m_precision; + int64_t const lng64 = lng * m_precision; + + ShortLatLon ll; + ll.lat = static_cast<int32_t>(lat64); + ll.lon = static_cast<int32_t>(lng64); + CHECK_EQUAL(static_cast<int64_t>(ll.lat), lat64, ("Latitude is out of 32bit boundary!")); + CHECK_EQUAL(static_cast<int64_t>(ll.lon), lng64, ("Longtitude is out of 32bit boundary!")); + + m_file.Seek(id * sizeof(ll)); + m_file.Write(&ll, sizeof(ll)); + + m_progress.Inc(); + } + + template <bool T = (ModeT == BasePointStorage::MODE_READ)> + typename std::enable_if<T, bool>::type GetPoint(uint64_t id, double & lat, double & lng) const + { + // I think, it's not good idea to write this ugly code. + // memcpy isn't to slow for that. + //#ifdef OMIM_OS_WINDOWS + ShortLatLon ll; + m_file.Read(id * sizeof(ll), &ll, sizeof(ll)); + //#else + // LatLon const & ll = *reinterpret_cast<LatLon const *>(m_file.Data() + id * sizeof(ll)); + //#endif + + // assume that valid coordinate is not (0, 0) + if (ll.lat != 0.0 || ll.lon != 0.0) + { + lat = static_cast<double>(ll.lat) / m_precision; + lng = static_cast<double>(ll.lon) / m_precision; + return true; + } + else + { + LOG(LERROR, ("Node with id = ", id, " not found!")); + return false; + } + } +}; + + +template < BasePointStorage::EStorageMode ModeT > +class MapFilePointStorage : public BasePointStorage +{ + typename std::conditional<ModeT, FileWriter, FileReader>::type m_file; + + + typedef unordered_map<uint64_t, pair<double, double> > ContainerT; + ContainerT m_map; + +public: + MapFilePointStorage(string const & name) : BasePointStorage(name, 10000), m_file(name) + { + InitStorage(EnableIf<ModeT>()); + } + + void InitStorage(EnableIf<MODE_WRITE>) {} + + void InitStorage(EnableIf<MODE_READ>) + { + LOG(LINFO, ("Nodes reading is started")); + + uint64_t const count = m_file.Size(); + + uint64_t pos = 0; + while (pos < count) + { + LatLonPos ll; + m_file.Read(pos, &ll, sizeof(ll)); + + (void)m_map.insert(make_pair(ll.pos, make_pair(ll.lat, ll.lon))); + + pos += sizeof(ll); + } + + LOG(LINFO, ("Nodes reading is finished")); + } + + void AddPoint(uint64_t id, double lat, double lng) + { + LatLonPos ll; + ll.pos = id; + ll.lat = lat; + ll.lon = lng; + m_file.Write(&ll, sizeof(ll)); + + m_progress.Inc(); + } + + bool GetPoint(uint64_t id, double & lat, double & lng) const + { + auto i = m_map.find(id); + if (i != m_map.end()) + { + lat = i->second.first; + lng = i->second.second; + return true; + } + return false; + } + +}; + +template < BasePointStorage::EStorageMode ModeT > +class MapFileShortPointStorage : public BasePointStorage +{ + typename std::conditional<ModeT, FileWriter, FileReader>::type m_file; + + + typedef unordered_map<uint64_t, pair<int32_t, int32_t> > ContainerT; + ContainerT m_map; + + double const m_precision = 10000000; + +public: + MapFileShortPointStorage(string const & name) : BasePointStorage(name, 10000), m_file(name+".short") + { + InitStorage(EnableIf<ModeT>()); + } + + void InitStorage(EnableIf<MODE_WRITE>) {} + + void InitStorage(EnableIf<MODE_READ>) + { + LOG(LINFO, ("Nodes reading is started")); + + uint64_t const count = m_file.Size(); + + uint64_t pos = 0; + while (pos < count) + { + ShortLatLonPos ll; + m_file.Read(pos, &ll, sizeof(ll)); + + (void)m_map.insert(make_pair(ll.pos, make_pair(ll.lat, ll.lon))); + + pos += sizeof(ll); + } + + LOG(LINFO, ("Nodes reading is finished")); + } + + void AddPoint(uint64_t id, double lat, double lng) + { + + int64_t const lat64 = lat * m_precision; + int64_t const lng64 = lng * m_precision; + + + + ShortLatLonPos ll; + ll.pos = id; + ll.lat = static_cast<int32_t>(lat64); + ll.lon = static_cast<int32_t>(lng64); + CHECK_EQUAL(static_cast<int64_t>(ll.lat), lat64, ("Latitude is out of 32bit boundary!")); + CHECK_EQUAL(static_cast<int64_t>(ll.lon), lng64, ("Longtitude is out of 32bit boundary!")); + m_file.Write(&ll, sizeof(ll)); + + m_progress.Inc(); + } + + bool GetPoint(uint64_t id, double & lat, double & lng) const + { + auto i = m_map.find(id); + if (i != m_map.end()) + { + lat = static_cast<double>(i->second.first) / m_precision; + lng = static_cast<double>(i->second.second) / m_precision; + return true; + } + return false; + } + +}; + + |