diff options
author | Jochen Topf <jochen@topf.org> | 2011-10-15 23:00:38 +0200 |
---|---|---|
committer | Jochen Topf <jochen@topf.org> | 2011-10-15 23:00:38 +0200 |
commit | c9b9a1b03efa73e28fb8929272d464c1684e9d8f (patch) | |
tree | 16cd0ae926b07dbf377a55b386130e2774216340 /tagstats/statistics_handler.hpp | |
parent | 8d1d99e8e85e1796da25556fb5760fde875cfe68 (diff) | |
download | taginfo-c9b9a1b03efa73e28fb8929272d464c1684e9d8f.tar taginfo-c9b9a1b03efa73e28fb8929272d464c1684e9d8f.tar.gz |
Moved statistics handler over from Osmium
The statistics handler was kept in the Osmium distribution, but it makes more
sense here.
Diffstat (limited to 'tagstats/statistics_handler.hpp')
-rw-r--r-- | tagstats/statistics_handler.hpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/tagstats/statistics_handler.hpp b/tagstats/statistics_handler.hpp new file mode 100644 index 0000000..7f5587e --- /dev/null +++ b/tagstats/statistics_handler.hpp @@ -0,0 +1,232 @@ +#ifndef TAGSTATS_HANDLER_STATISTICS_HPP +#define TAGSTATS_HANDLER_STATISTICS_HPP + +/* + +Copyright 2011 Jochen Topf <jochen@topf.org> and others (see README). + +This file is part of Taginfo (https://github.com/joto/taginfo). + +Osmium is free software: you can redistribute it and/or modify it under the +terms of the GNU Lesser General Public License or (at your option) the GNU +General Public License as published by the Free Software Foundation, either +version 3 of the Licenses, or (at your option) any later version. + +Osmium is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU +General Public License for more details. + +You should have received a copy of the Licenses along with Osmium. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#include <osmium/utils/sqlite.hpp> + +/** + * Osmium handler that collects basic statistics from OSM data and + * writes it to a Sqlite database. + */ +class StatisticsHandler : public Osmium::Handler::Base { + +public: + + StatisticsHandler() : Base() { + // if you change anything in this array, also change the corresponding struct below + static const char *sn[] = { + "nodes", + "nodes_without_tags", + "node_tags", + "max_node_id", + "max_tags_on_node", + "ways", + "way_tags", + "way_nodes", + "max_way_id", + "max_tags_on_way", + "max_nodes_on_way", + "closed_ways", + "relations", + "relation_tags", + "relation_members", + "max_relation_id", + "max_tags_on_relation", + "max_members_on_relation", + "max_user_id", + "anon_user_objects", + "max_node_version", + "max_way_version", + "max_relation_version", + "sum_node_version", + "sum_way_version", + "sum_relation_version", + "max_changeset_id", + 0 // last element (sentinel) must always be 0 + }; + m_stat_names = sn; + + // initialize all statistics to zero + for (int i=0; m_stat_names[i]; ++i) { + ((uint64_t *) &m_stats)[i] = 0; + } + } + + void node(const Osmium::OSM::Node* node) { + update_common_stats(node); + m_stats.nodes++; + if (m_tag_count == 0) { + m_stats.nodes_without_tags++; + } + if (m_id > (int64_t) m_stats.max_node_id) { + m_stats.max_node_id = m_id; + } + m_stats.node_tags += m_tag_count; + if (m_tag_count > (int64_t) m_stats.max_tags_on_node) { + m_stats.max_tags_on_node = m_tag_count; + } + if (m_version > (int64_t) m_stats.max_node_version) { + m_stats.max_node_version = m_version; + } + m_stats.sum_node_version += m_version; + } + + void way(const Osmium::OSM::Way* way) { + update_common_stats(way); + m_stats.ways++; + if (way->is_closed()) { + m_stats.closed_ways++; + } + if (m_id > (int64_t) m_stats.max_way_id) { + m_stats.max_way_id = m_id; + } + m_stats.way_tags += m_tag_count; + m_stats.way_nodes += way->node_count(); + if (m_tag_count > (int64_t) m_stats.max_tags_on_way) { + m_stats.max_tags_on_way = m_tag_count; + } + if (way->node_count() > (int64_t) m_stats.max_nodes_on_way) { + m_stats.max_nodes_on_way = way->node_count(); + } + if (m_version > (int64_t) m_stats.max_way_version) { + m_stats.max_way_version = m_version; + } + m_stats.sum_way_version += m_version; + } + + void relation(const Osmium::OSM::Relation* relation) { + update_common_stats(relation); + m_stats.relations++; + if (m_id > (int64_t) m_stats.max_relation_id) { + m_stats.max_relation_id = m_id; + } + m_stats.relation_tags += m_tag_count; + osm_sequence_id_t member_count = relation->members().size(); + m_stats.relation_members += member_count; + if (m_tag_count > (int64_t) m_stats.max_tags_on_relation) { + m_stats.max_tags_on_relation = m_tag_count; + } + if (member_count > (int64_t) m_stats.max_members_on_relation) { + m_stats.max_members_on_relation = member_count; + } + if (m_version > (int64_t) m_stats.max_relation_version) { + m_stats.max_relation_version = m_version; + } + m_stats.sum_relation_version += m_version; + } + + void final() { + unlink("count.db"); + Osmium::Sqlite::Database db("count.db"); + + sqlite3 *sqlite_db = db.get_sqlite3(); + if (SQLITE_OK != sqlite3_exec(sqlite_db, \ + "CREATE TABLE stats (" \ + " key TEXT, " \ + " value INT64 " \ + ");", 0, 0, 0)) { + std::cerr << "Database error: " << sqlite3_errmsg(sqlite_db) << "\n"; + sqlite3_close(sqlite_db); + exit(1); + } + + Osmium::Sqlite::Statement *statement_insert_into_main_stats = db.prepare("INSERT INTO stats (key, value) VALUES (?, ?);"); + db.begin_transaction(); + + for (int i=0; m_stat_names[i]; ++i) { + statement_insert_into_main_stats + ->bind_text(m_stat_names[i]) + ->bind_int64( ((uint64_t *) &m_stats)[i] ) + ->execute(); + } + statement_insert_into_main_stats + ->bind_text("nodes_with_tags") + ->bind_int64( ((uint64_t *) &m_stats)[0] - ((uint64_t *) &m_stats)[1] ) + ->execute(); + + db.commit(); + + delete statement_insert_into_main_stats; + } + +private: + + // if you change anything in this struct, also change the corresponding array above + struct statistics { + uint64_t nodes; + uint64_t nodes_without_tags; + uint64_t node_tags; + uint64_t max_node_id; + uint64_t max_tags_on_node; + uint64_t ways; + uint64_t way_tags; + uint64_t way_nodes; + uint64_t max_way_id; + uint64_t max_tags_on_way; + uint64_t max_nodes_on_way; + uint64_t closed_ways; + uint64_t relations; + uint64_t relation_tags; + uint64_t relation_members; + uint64_t max_relation_id; + uint64_t max_tags_on_relation; + uint64_t max_members_on_relation; + uint64_t max_user_id; + uint64_t anon_user_objects; + uint64_t max_node_version; + uint64_t max_way_version; + uint64_t max_relation_version; + uint64_t sum_node_version; + uint64_t sum_way_version; + uint64_t sum_relation_version; + uint64_t max_changeset_id; + } m_stats; + + const char **m_stat_names; + + osm_object_id_t m_id; + osm_version_t m_version; + int m_tag_count; + + void update_common_stats(const Osmium::OSM::Object* object) { + m_id = object->id(); + m_version = object->version(); + m_tag_count = object->tags().size(); + + osm_user_id_t uid = object->uid(); + if (uid == 0) { + m_stats.anon_user_objects++; + } + if (uid > (int64_t) m_stats.max_user_id) { + m_stats.max_user_id = uid; + } + + osm_changeset_id_t changeset = object->changeset(); + if (changeset > (int64_t) m_stats.max_changeset_id) { + m_stats.max_changeset_id = changeset; + } + } + +}; // class StatisticsHandler + +#endif // TAGSTATS_HANDLER_STATISTICS_HPP |