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:
authorSergey Yershov <yershov@corp.mail.ru>2015-01-27 20:14:23 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:38:04 +0300
commit9372d0a8ca30aa4e497ed677e155b9e6ed040b75 (patch)
tree27b1983ca34d30dd4b132eec883b52a1c9de8fcb /generator
parent418ef1202ff93eec26b2aa0c5c3a63df0ab8c3c6 (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.cpp67
-rw-r--r--generator/data_generator.hpp2
-rw-r--r--generator/feature_generator.cpp100
-rw-r--r--generator/feature_generator.hpp2
-rw-r--r--generator/generator_tool/generator_tool.cpp26
-rw-r--r--generator/generator_tool/generator_tool.pro2
-rw-r--r--generator/osm2type.cpp42
-rw-r--r--generator/osm_decl.hpp18
-rw-r--r--generator/point_storage.hpp448
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;
+ }
+
+};
+
+