Skip to content

Commit bb2cf86

Browse files
committed
New dependency manager class
Moves the code for dependency management out of the middle into its own class.
1 parent 0f5b7b6 commit bb2cf86

14 files changed

+336
-185
lines changed

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
set(osm2pgsql_lib_SOURCES
3+
dependency-manager.cpp
34
db-copy.cpp
45
expire-tiles.cpp
56
gazetteer-style.cpp
@@ -31,6 +32,7 @@ set(osm2pgsql_lib_SOURCES
3132
tagtransform.cpp
3233
util.cpp
3334
wildcmp.cpp
35+
dependency-manager.hpp
3436
db-copy.hpp
3537
expire-tiles.hpp
3638
gazetteer-style.hpp

src/dependency-manager.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
#include "dependency-manager.hpp"
3+
4+
void full_dependency_manager_t::node_changed(osmid_t id) {
5+
for (auto const way_id : m_object_store->get_ways_by_node(id)) {
6+
way_changed(way_id);
7+
m_ways_pending_tracker.mark(way_id);
8+
}
9+
10+
for (auto const rel_id : m_object_store->get_rels_by_node(id)) {
11+
m_rels_pending_tracker.mark(rel_id);
12+
}
13+
}
14+
15+
void full_dependency_manager_t::way_changed(osmid_t id) {
16+
if (m_ways_pending_tracker.is_marked(id)) {
17+
return;
18+
}
19+
20+
for (auto const rel_id : m_object_store->get_rels_by_way(id)) {
21+
m_rels_pending_tracker.mark(rel_id);
22+
}
23+
}
24+
25+
void full_dependency_manager_t::relation_changed(osmid_t id) {
26+
if (m_rels_pending_tracker.is_marked(id)) {
27+
return;
28+
}
29+
30+
for (auto const rel_id : m_object_store->get_rels_by_rel(id)) {
31+
m_rels_pending_tracker.mark(rel_id);
32+
}
33+
}
34+
35+
void full_dependency_manager_t::relation_deleted(osmid_t id) {
36+
for (auto const rel_id : m_object_store->get_ways_by_rel(id)) {
37+
m_ways_pending_tracker.mark(rel_id);
38+
}
39+
}
40+
41+
bool full_dependency_manager_t::has_pending() const noexcept
42+
{
43+
return !m_ways_pending_tracker.empty() || !m_rels_pending_tracker.empty();
44+
}
45+
46+
void full_dependency_manager_t::process_pending(middle_t::pending_processor &pf)
47+
{
48+
osmid_t id;
49+
while (id_tracker::is_valid(id = m_ways_pending_tracker.pop_mark())) {
50+
pf.enqueue_ways(id);
51+
}
52+
53+
pf.process_ways();
54+
55+
while (id_tracker::is_valid(id = m_rels_pending_tracker.pop_mark())) {
56+
pf.enqueue_relations(id);
57+
}
58+
59+
pf.process_relations();
60+
}

src/dependency-manager.hpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#ifndef OSM2PGSQL_DEPENDENCY_MANAGER_HPP
2+
#define OSM2PGSQL_DEPENDENCY_MANAGER_HPP
3+
4+
#include "id-tracker.hpp"
5+
#include "middle.hpp"
6+
#include "osmtypes.hpp"
7+
8+
#include <cassert>
9+
10+
/**
11+
* The job of the dependency manager is to keep track of the dependencies
12+
* between OSM objects, that is nodes in ways and members of relations.
13+
*
14+
* Whenever an OSM object changes, this class is notified and can remember
15+
* the ids for later use.
16+
*
17+
* This base class doesn't actually do the dependency management but is a
18+
* dummy for cases where no dependency management is needed. See the
19+
* full_dependency_manager_t class for the real dependency manager.
20+
*/
21+
class dependency_manager_t
22+
{
23+
public:
24+
virtual ~dependency_manager_t() = default;
25+
26+
/**
27+
* Mark a node as changed to trigger the propagation of this change to
28+
* ways and relations.
29+
*
30+
* This has to be called *after* the object was stored in the object store.
31+
*/
32+
virtual void node_changed(osmid_t) {};
33+
34+
/**
35+
* Mark a way as changed to trigger the propagation of this change to
36+
* relations.
37+
*
38+
* This has to be called *after* the object was stored in the object store.
39+
*/
40+
virtual void way_changed(osmid_t) {};
41+
42+
/**
43+
* Mark a relation as changed to trigger the propagation of this change to
44+
* other relations.
45+
*
46+
* This has to be called *after* the object was stored in the object store.
47+
*/
48+
virtual void relation_changed(osmid_t) {};
49+
50+
/**
51+
* Mark a relation as deleted to trigger the propagation of this change to
52+
* the way members.
53+
*/
54+
virtual void relation_deleted(osmid_t) {};
55+
56+
/// Are there pending objects that need to be processed?
57+
virtual bool has_pending() const noexcept { return false; }
58+
59+
/**
60+
* Process all pending objects.
61+
*
62+
* \param pf Processor that we should feed the objects to and that
63+
* will handle the actual processing.
64+
*
65+
* \post !has_pending()
66+
*/
67+
virtual void process_pending(middle_t::pending_processor &) {}
68+
};
69+
70+
/**
71+
* The job of the dependency manager is to keep track of the dependencies
72+
* between OSM objects, that is nodes in ways and members of relations.
73+
*
74+
* Whenever an OSM object changes, this class is notified and remembers
75+
* the ids for later use. Later on the class can be told to process the
76+
* ids it has remembered.
77+
*/
78+
class full_dependency_manager_t : public dependency_manager_t
79+
{
80+
public:
81+
82+
/**
83+
* Constructor.
84+
*
85+
* \param object_store Pointer to the middle that keeps the actual
86+
* database of objects and their relationsships.
87+
*
88+
* \pre object_store != nullptr
89+
*/
90+
explicit full_dependency_manager_t(middle_t *object_store)
91+
: m_object_store(object_store)
92+
{
93+
assert(object_store != nullptr);
94+
}
95+
96+
void node_changed(osmid_t id) override;
97+
void way_changed(osmid_t id) override;
98+
void relation_changed(osmid_t id) override;
99+
void relation_deleted(osmid_t id) override;
100+
101+
bool has_pending() const noexcept override;
102+
103+
void process_pending(middle_t::pending_processor &pf) override;
104+
105+
private:
106+
middle_t* m_object_store;
107+
108+
id_tracker m_ways_pending_tracker;
109+
id_tracker m_rels_pending_tracker;
110+
};
111+
112+
#endif // OSM2PGSQL_DEPENDENCY_MANAGER_HPP

src/middle-pgsql.cpp

Lines changed: 31 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#include <osmium/memory/buffer.hpp>
2020
#include <osmium/osm/types_from_string.hpp>
2121

22-
#include <libpq-fe.h>
23-
2422
#include "format.hpp"
2523
#include "middle-pgsql.hpp"
2624
#include "node-persistent-cache.hpp"
@@ -308,25 +306,40 @@ void middle_pgsql_t::node_delete(osmid_t osm_id)
308306
}
309307
}
310308

311-
void middle_pgsql_t::node_changed(osmid_t osm_id)
309+
idlist_t middle_pgsql_t::get_ids(const char* stmt, osmid_t osm_id)
312310
{
313-
assert(m_append);
314-
if (!m_mark_pending) {
315-
return;
316-
}
311+
idlist_t ids;
317312

318-
// Find all ways referencing this node and mark them as pending.
319-
auto const res_ways =
320-
m_db_connection.exec_prepared("mark_ways_by_node", osm_id);
321-
for_each_id(res_ways, [this](osmid_t id) {
322-
way_changed(id);
323-
m_ways_pending_tracker->mark(id);
324-
});
313+
auto const res = m_db_connection.exec_prepared(stmt, osm_id);
314+
ids.reserve(res.num_tuples());
315+
for_each_id(res, [&ids](osmid_t id) { ids.push_back(id); });
316+
317+
return ids;
318+
}
319+
320+
idlist_t middle_pgsql_t::get_ways_by_node(osmid_t osm_id)
321+
{
322+
return get_ids("mark_ways_by_node", osm_id);
323+
}
324+
325+
idlist_t middle_pgsql_t::get_rels_by_node(osmid_t osm_id)
326+
{
327+
return get_ids("mark_rels_by_node", osm_id);
328+
}
329+
330+
idlist_t middle_pgsql_t::get_rels_by_way(osmid_t osm_id)
331+
{
332+
return get_ids("mark_rels_by_way", osm_id);
333+
}
334+
335+
idlist_t middle_pgsql_t::get_rels_by_rel(osmid_t osm_id)
336+
{
337+
return get_ids("mark_rels", osm_id);
338+
}
325339

326-
// Find all relations referencing this node and mark them as pending.
327-
auto const res_rels = m_db_connection.exec_prepared("mark_rels_by_node", osm_id);
328-
for_each_id(res_rels,
329-
[this](osmid_t id) { m_rels_pending_tracker->mark(id); });
340+
idlist_t middle_pgsql_t::get_ways_by_rel(osmid_t osm_id)
341+
{
342+
return get_ids("mark_ways_by_rel", osm_id);
330343
}
331344

332345
void middle_pgsql_t::way_set(osmium::Way const &way)
@@ -431,31 +444,6 @@ void middle_pgsql_t::way_delete(osmid_t osm_id)
431444
m_db_copy.delete_object(osm_id);
432445
}
433446

434-
void middle_pgsql_t::iterate_ways(pending_processor &pf)
435-
{
436-
// enqueue the jobs
437-
osmid_t id;
438-
while (id_tracker::is_valid(id = m_ways_pending_tracker->pop_mark())) {
439-
pf.enqueue_ways(id);
440-
}
441-
442-
//let the threads work on them
443-
pf.process_ways();
444-
}
445-
446-
void middle_pgsql_t::way_changed(osmid_t osm_id)
447-
{
448-
assert(m_append);
449-
450-
if (m_ways_pending_tracker->is_marked(osm_id)) {
451-
return;
452-
}
453-
454-
// Keep track of all relations having this way as member.
455-
auto const res = m_db_connection.exec_prepared("mark_rels_by_way", osm_id);
456-
for_each_id(res, [this](osmid_t id) { m_rels_pending_tracker->mark(id); });
457-
}
458-
459447
void middle_pgsql_t::relation_set(osmium::Relation const &rel)
460448
{
461449
// Sort relation members by their type.
@@ -526,34 +514,10 @@ void middle_pgsql_t::relation_delete(osmid_t osm_id)
526514
{
527515
assert(m_append);
528516

529-
// Keep track of all member ways.
530-
auto const res = m_db_connection.exec_prepared("mark_ways_by_rel", osm_id);
531-
for_each_id(res, [this](osmid_t id) { m_ways_pending_tracker->mark(id); });
532-
533517
m_db_copy.new_line(m_tables[REL_TABLE].m_copy_target);
534518
m_db_copy.delete_object(osm_id);
535519
}
536520

537-
void middle_pgsql_t::iterate_relations(pending_processor &pf)
538-
{
539-
// enqueue the jobs
540-
osmid_t id;
541-
while (id_tracker::is_valid(id = m_rels_pending_tracker->pop_mark())) {
542-
pf.enqueue_relations(id);
543-
}
544-
545-
//let the threads work on them
546-
pf.process_relations();
547-
}
548-
549-
void middle_pgsql_t::relation_changed(osmid_t osm_id)
550-
{
551-
assert(m_append);
552-
553-
auto const res = m_db_connection.exec_prepared("mark_rels", osm_id);
554-
for_each_id(res, [this](osmid_t id) { m_rels_pending_tracker->mark(id); });
555-
}
556-
557521
idlist_t middle_query_pgsql_t::relations_using_way(osmid_t way_id) const
558522
{
559523
auto const result = m_sql_conn.exec_prepared("rels_using_way", way_id);
@@ -579,9 +543,6 @@ middle_query_pgsql_t::middle_query_pgsql_t(
579543

580544
void middle_pgsql_t::start()
581545
{
582-
m_ways_pending_tracker.reset(new id_tracker{});
583-
m_rels_pending_tracker.reset(new id_tracker{});
584-
585546
// Gazetter doesn't use mark-pending processing and consequently
586547
// needs no way-node index.
587548
// TODO Currently, set here to keep the impact on the code small.
@@ -782,8 +743,3 @@ middle_pgsql_t::get_query_instance()
782743

783744
return std::shared_ptr<middle_query_t>(mid.release());
784745
}
785-
786-
bool middle_pgsql_t::has_pending() const
787-
{
788-
return !m_ways_pending_tracker->empty() || !m_rels_pending_tracker->empty();
789-
}

src/middle-pgsql.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <memory>
1313

1414
#include "db-copy-mgr.hpp"
15-
#include "id-tracker.hpp"
1615
#include "middle.hpp"
1716
#include "node-persistent-cache.hpp"
1817
#include "node-ram-cache.hpp"
@@ -65,22 +64,20 @@ struct middle_pgsql_t : public slim_middle_t
6564

6665
void node_set(osmium::Node const &node) override;
6766
void node_delete(osmid_t id) override;
68-
void node_changed(osmid_t id) override;
6967

7068
void way_set(osmium::Way const &way) override;
7169
void way_delete(osmid_t id) override;
72-
void way_changed(osmid_t id) override;
7370

7471
void relation_set(osmium::Relation const &rel) override;
7572
void relation_delete(osmid_t id) override;
76-
void relation_changed(osmid_t id) override;
7773

7874
void flush() override;
7975

80-
void iterate_ways(pending_processor &pf) override;
81-
void iterate_relations(pending_processor &pf) override;
82-
83-
bool has_pending() const override;
76+
idlist_t get_ways_by_node(osmid_t osm_id) override;
77+
idlist_t get_rels_by_node(osmid_t osm_id) override;
78+
idlist_t get_rels_by_way(osmid_t osm_id) override;
79+
idlist_t get_rels_by_rel(osmid_t osm_id) override;
80+
idlist_t get_ways_by_rel(osmid_t osm_id) override;
8481

8582
class table_desc
8683
{
@@ -115,6 +112,8 @@ struct middle_pgsql_t : public slim_middle_t
115112

116113
void buffer_store_tags(osmium::OSMObject const &obj, bool attrs);
117114

115+
idlist_t get_ids(const char* stmt, osmid_t osm_id);
116+
118117
table_desc m_tables[NUM_TABLES];
119118

120119
bool m_append;
@@ -124,8 +123,6 @@ struct middle_pgsql_t : public slim_middle_t
124123
std::shared_ptr<node_ram_cache> m_cache;
125124
std::shared_ptr<node_persistent_cache> m_persistent_cache;
126125

127-
std::shared_ptr<id_tracker> m_ways_pending_tracker, m_rels_pending_tracker;
128-
129126
pg_conn_t m_db_connection;
130127

131128
// middle keeps its own thread for writing to the database.

0 commit comments

Comments
 (0)