Osmium  0.1
include/osmium/handler/statistics.hpp
Go to the documentation of this file.
00001 #ifndef OSMIUM_HANDLER_STATISTICS_HPP
00002 #define OSMIUM_HANDLER_STATISTICS_HPP
00003 
00004 /*
00005 
00006 Copyright 2011 Jochen Topf <jochen@topf.org> and others (see README).
00007 
00008 This file is part of Osmium (https://github.com/joto/osmium).
00009 
00010 Osmium is free software: you can redistribute it and/or modify it under the
00011 terms of the GNU Lesser General Public License or (at your option) the GNU
00012 General Public License as published by the Free Software Foundation, either
00013 version 3 of the Licenses, or (at your option) any later version.
00014 
00015 Osmium is distributed in the hope that it will be useful, but WITHOUT ANY
00016 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
00017 PARTICULAR PURPOSE. See the GNU Lesser General Public License and the GNU
00018 General Public License for more details.
00019 
00020 You should have received a copy of the Licenses along with Osmium. If not, see
00021 <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 #include <osmium/utils/sqlite.hpp>
00026 
00027 namespace Osmium {
00028 
00029     namespace Handler {
00030 
00035         class Statistics : public Base {
00036 
00037         public:
00038 
00039             Statistics() : Base() {
00040                 // if you change anything in this array, also change the corresponding struct below
00041                 static const char *sn[] = {
00042                     "nodes",
00043                     "nodes_without_tags",
00044                     "node_tags",
00045                     "max_node_id",
00046                     "max_tags_on_node",
00047                     "ways",
00048                     "way_tags",
00049                     "way_nodes",
00050                     "max_way_id",
00051                     "max_tags_on_way",
00052                     "max_nodes_on_way",
00053                     "closed_ways",
00054                     "relations",
00055                     "relation_tags",
00056                     "relation_members",
00057                     "max_relation_id",
00058                     "max_tags_on_relation",
00059                     "max_members_on_relation",
00060                     "max_user_id",
00061                     "anon_user_objects",
00062                     "max_node_version",
00063                     "max_way_version",
00064                     "max_relation_version",
00065                     "sum_node_version",
00066                     "sum_way_version",
00067                     "sum_relation_version",
00068                     "max_changeset_id",
00069                     0    // last element (sentinel) must always be 0
00070                 };
00071                 m_stat_names = sn;
00072 
00073                 // initialize all statistics to zero
00074                 for (int i=0; m_stat_names[i]; ++i) {
00075                     ((uint64_t*) &m_stats)[i] = 0;
00076                 }
00077             }
00078 
00079             void node(const shared_ptr<Osmium::OSM::Node const>& node) {
00080                 update_common_stats(node);
00081                 m_stats.nodes++;
00082                 if (m_tag_count == 0) {
00083                     m_stats.nodes_without_tags++;
00084                 }
00085                 if (m_id > (int64_t) m_stats.max_node_id) {
00086                     m_stats.max_node_id = m_id;
00087                 }
00088                 m_stats.node_tags += m_tag_count;
00089                 if (m_tag_count > (int64_t) m_stats.max_tags_on_node) {
00090                     m_stats.max_tags_on_node = m_tag_count;
00091                 }
00092                 if (m_version > (int64_t) m_stats.max_node_version) {
00093                     m_stats.max_node_version = m_version;
00094                 }
00095                 m_stats.sum_node_version += m_version;
00096             }
00097 
00098             void way(const shared_ptr<Osmium::OSM::Way const>& way) {
00099                 update_common_stats(way);
00100                 m_stats.ways++;
00101                 if (way->is_closed()) {
00102                     m_stats.closed_ways++;
00103                 }
00104                 if (m_id > (int64_t) m_stats.max_way_id) {
00105                     m_stats.max_way_id = m_id;
00106                 }
00107                 m_stats.way_tags += m_tag_count;
00108                 m_stats.way_nodes += way->node_count();
00109                 if (m_tag_count > (int64_t) m_stats.max_tags_on_way) {
00110                     m_stats.max_tags_on_way = m_tag_count;
00111                 }
00112                 if (way->node_count() > (int64_t) m_stats.max_nodes_on_way) {
00113                     m_stats.max_nodes_on_way = way->node_count();
00114                 }
00115                 if (m_version > (int64_t) m_stats.max_way_version) {
00116                     m_stats.max_way_version = m_version;
00117                 }
00118                 m_stats.sum_way_version += m_version;
00119             }
00120 
00121             void relation(const shared_ptr<Osmium::OSM::Relation const>& relation) {
00122                 update_common_stats(relation);
00123                 m_stats.relations++;
00124                 if (m_id > (int64_t) m_stats.max_relation_id) {
00125                     m_stats.max_relation_id = m_id;
00126                 }
00127                 m_stats.relation_tags += m_tag_count;
00128                 osm_sequence_id_t member_count = relation->members().size();
00129                 m_stats.relation_members += member_count;
00130                 if (m_tag_count > (int64_t) m_stats.max_tags_on_relation) {
00131                     m_stats.max_tags_on_relation = m_tag_count;
00132                 }
00133                 if (member_count > (int64_t) m_stats.max_members_on_relation) {
00134                     m_stats.max_members_on_relation = member_count;
00135                 }
00136                 if (m_version > (int64_t) m_stats.max_relation_version) {
00137                     m_stats.max_relation_version = m_version;
00138                 }
00139                 m_stats.sum_relation_version += m_version;
00140             }
00141 
00142             void final() {
00143                 unlink("count.db");
00144                 Sqlite::Database db("count.db");
00145 
00146                 sqlite3* sqlite_db = db.get_sqlite3();
00147                 if (SQLITE_OK != sqlite3_exec(sqlite_db, \
00148                                               "CREATE TABLE stats (" \
00149                                               "  key    TEXT, " \
00150                                               "  value  INT64 " \
00151                                               ");", 0, 0, 0)) {
00152                     std::cerr << "Database error: " << sqlite3_errmsg(sqlite_db) << "\n";
00153                     sqlite3_close(sqlite_db);
00154                     exit(1);
00155                 }
00156 
00157                 Sqlite::Statement* statement_insert_into_main_stats = db.prepare("INSERT INTO stats (key, value) VALUES (?, ?);");
00158                 db.begin_transaction();
00159 
00160                 for (int i=0; m_stat_names[i]; ++i) {
00161                     statement_insert_into_main_stats
00162                     ->bind_text(m_stat_names[i])
00163                     ->bind_int64( ((uint64_t*) &m_stats)[i] )
00164                     ->execute();
00165                 }
00166                 statement_insert_into_main_stats
00167                 ->bind_text("nodes_with_tags")
00168                 ->bind_int64( ((uint64_t*) &m_stats)[0] - ((uint64_t*) &m_stats)[1] )
00169                 ->execute();
00170 
00171                 db.commit();
00172 
00173                 delete statement_insert_into_main_stats;
00174             }
00175 
00176         private:
00177 
00178             // if you change anything in this struct, also change the corresponding array above
00179             struct statistics {
00180                 uint64_t nodes;
00181                 uint64_t nodes_without_tags;
00182                 uint64_t node_tags;
00183                 uint64_t max_node_id;
00184                 uint64_t max_tags_on_node;
00185                 uint64_t ways;
00186                 uint64_t way_tags;
00187                 uint64_t way_nodes;
00188                 uint64_t max_way_id;
00189                 uint64_t max_tags_on_way;
00190                 uint64_t max_nodes_on_way;
00191                 uint64_t closed_ways;
00192                 uint64_t relations;
00193                 uint64_t relation_tags;
00194                 uint64_t relation_members;
00195                 uint64_t max_relation_id;
00196                 uint64_t max_tags_on_relation;
00197                 uint64_t max_members_on_relation;
00198                 uint64_t max_user_id;
00199                 uint64_t anon_user_objects;
00200                 uint64_t max_node_version;
00201                 uint64_t max_way_version;
00202                 uint64_t max_relation_version;
00203                 uint64_t sum_node_version;
00204                 uint64_t sum_way_version;
00205                 uint64_t sum_relation_version;
00206                 uint64_t max_changeset_id;
00207             } m_stats;
00208 
00209             const char **m_stat_names;
00210 
00211             osm_object_id_t m_id;
00212             osm_version_t   m_version;
00213             int             m_tag_count;
00214 
00215             void update_common_stats(const shared_ptr<Osmium::OSM::Object const>& object) {
00216                 m_id        = object->id();
00217                 m_version   = object->version();
00218                 m_tag_count = object->tags().size();
00219 
00220                 osm_user_id_t uid = object->uid();
00221                 if (uid == 0) {
00222                     m_stats.anon_user_objects++;
00223                 }
00224                 if (uid > (int64_t) m_stats.max_user_id) {
00225                     m_stats.max_user_id = uid;
00226                 }
00227 
00228                 osm_changeset_id_t changeset = object->changeset();
00229                 if (changeset > (int64_t) m_stats.max_changeset_id) {
00230                     m_stats.max_changeset_id = changeset;
00231                 }
00232             }
00233 
00234         }; // class Statistics
00235 
00236     } // namespace Handler
00237 
00238 } // namespace Osmium
00239 
00240 #endif // OSMIUM_HANDLER_STATISTICS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines