diff options
Diffstat (limited to 'tagstats')
-rw-r--r-- | tagstats/Makefile | 9 | ||||
-rw-r--r-- | tagstats/osmstats.cpp | 57 | ||||
-rw-r--r-- | tagstats/sqlite.hpp | 195 | ||||
-rw-r--r-- | tagstats/statistics_handler.hpp | 8 | ||||
-rw-r--r-- | tagstats/tagstats.cpp | 2 | ||||
-rw-r--r-- | tagstats/tagstats_handler.hpp | 20 |
6 files changed, 273 insertions, 18 deletions
diff --git a/tagstats/Makefile b/tagstats/Makefile index 04a453d..19e33cd 100644 --- a/tagstats/Makefile +++ b/tagstats/Makefile @@ -41,13 +41,16 @@ LDFLAGS = $(LIB_EXPAT) $(LIB_PBF) $(LIB_GD) $(LIB_SQLITE) .PHONY: all clean install -all: tagstats +all: tagstats osmstats + +osmstats: osmstats.cpp statistics_handler.hpp + $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) tagstats: tagstats.cpp tagstats_handler.hpp statistics_handler.hpp string_store.hpp geodistribution.hpp $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) check: - cppcheck --enable=all tagstats.cpp + cppcheck --enable=all tagstats.cpp osmstats.cpp indent: astyle --style=java --indent-namespaces --indent-switches --pad-header --suffix=none \*.hpp \*.cpp @@ -56,5 +59,5 @@ install: install -m 755 tagstats ../sources/db/tagstats clean: - rm -f *.o core tagstats + rm -f *.o core tagstats osmstats diff --git a/tagstats/osmstats.cpp b/tagstats/osmstats.cpp new file mode 100644 index 0000000..f2cdda2 --- /dev/null +++ b/tagstats/osmstats.cpp @@ -0,0 +1,57 @@ +/* + +Copyright 2012 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 <iostream> + +#define OSMIUM_WITH_PBF_INPUT +#define OSMIUM_WITH_XML_INPUT + +#include <osmium.hpp> +#include <osmium/handler.hpp> + +#include "statistics_handler.hpp" + +int main(int argc, char *argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " OSMFILE DATABASE" << std::endl; + exit(1); + } + + Osmium::OSMFile infile(argv[1]); + + Sqlite::Database db(argv[2]); + 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); + } + + StatisticsHandler handler(db); + Osmium::Input::read(infile, handler); + + google::protobuf::ShutdownProtobufLibrary(); +} + diff --git a/tagstats/sqlite.hpp b/tagstats/sqlite.hpp new file mode 100644 index 0000000..fac6bcf --- /dev/null +++ b/tagstats/sqlite.hpp @@ -0,0 +1,195 @@ +#ifndef TAGSTATS_SQLITE_HPP +#define TAGSTATS_SQLITE_HPP + +/* + +Copyright 2012 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 <iostream> +#include <stdexcept> +#include <stdint.h> +#include <string> + +#include <sqlite3.h> + +/** +* @brief The %Sqlite classes wrap the %Sqlite C library. +*/ +namespace Sqlite { + + /** + * Exception returned by Sqlite wrapper classes when there are errors in the Sqlite3 lib + */ + class Exception : public std::runtime_error { + + public: + + Exception(const std::string& msg, const std::string& error) : + std::runtime_error(msg + ": " + error + '\n') { + } + + }; + + class Statement; + + /** + * Wrapper class for Sqlite database + */ + class Database { + + private: + + sqlite3* m_db; + + public: + + Database(const char* filename) { + if (sqlite3_open_v2(filename, &m_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0)) { + sqlite3_close(m_db); + throw Sqlite::Exception("Can't open database", errmsg()); + } + } + + ~Database() { + sqlite3_close(m_db); + } + + const std::string& errmsg() const { + static std::string error = std::string(sqlite3_errmsg(m_db)); + return error; + } + + sqlite3* get_sqlite3() { + return m_db; + } + + void begin_transaction() { + if (SQLITE_OK != sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0)) { + std::cerr << "Database error: " << sqlite3_errmsg(m_db) << "\n"; + sqlite3_close(m_db); + throw std::runtime_error("Sqlite error"); + } + } + + void commit() { + if (SQLITE_OK != sqlite3_exec(m_db, "COMMIT;", 0, 0, 0)) { + std::cerr << "Database error: " << sqlite3_errmsg(m_db) << "\n"; + sqlite3_close(m_db); + throw std::runtime_error("Sqlite error"); + } + } + + Statement* prepare(const char* sql); + + }; // class Database + + /** + * Wrapper class for Sqlite prepared statement. + */ + class Statement { + + private: + + Database* m_db; + sqlite3_stmt* m_statement; + int m_bindnum; + + public: + + Statement(Database* db, const char* sql) : + m_db(db), + m_statement(0), + m_bindnum(1) { + sqlite3_prepare_v2(db->get_sqlite3(), sql, -1, &m_statement, 0); + if (m_statement == 0) { + throw Sqlite::Exception("Can't prepare statement", m_db->errmsg()); + } + } + + ~Statement() { + sqlite3_finalize(m_statement); + } + + Statement* bind_null() { + if (SQLITE_OK != sqlite3_bind_null(m_statement, m_bindnum++)) { + throw Sqlite::Exception("Can't bind null value", m_db->errmsg()); + } + return this; + } + + Statement* bind_text(const char* value) { + if (SQLITE_OK != sqlite3_bind_text(m_statement, m_bindnum++, value, -1, SQLITE_STATIC)) { + throw Sqlite::Exception("Can't bind text value", m_db->errmsg()); + } + return this; + } + + Statement* bind_text(const std::string& value) { + if (SQLITE_OK != sqlite3_bind_text(m_statement, m_bindnum++, value.c_str(), -1, SQLITE_STATIC)) { + throw Sqlite::Exception("Can't bind text value", m_db->errmsg()); + } + return this; + } + + Statement* bind_int(int value) { + if (SQLITE_OK != sqlite3_bind_int(m_statement, m_bindnum++, value)) { + throw Sqlite::Exception("Can't bind int value", m_db->errmsg()); + } + return this; + } + + Statement* bind_int64(int64_t value) { + if (SQLITE_OK != sqlite3_bind_int64(m_statement, m_bindnum++, value)) { + throw Sqlite::Exception("Can't bind int64 value", m_db->errmsg()); + } + return this; + } + + Statement* bind_double(double value) { + if (SQLITE_OK != sqlite3_bind_double(m_statement, m_bindnum++, value)) { + throw Sqlite::Exception("Can't bind double value", m_db->errmsg()); + } + return this; + } + + Statement* bind_blob(const void* value, int length) { + if (SQLITE_OK != sqlite3_bind_blob(m_statement, m_bindnum++, value, length, 0)) { + throw Sqlite::Exception("Can't bind blob value", m_db->errmsg()); + } + return this; + } + + void execute() { + sqlite3_step(m_statement); + if (SQLITE_OK != sqlite3_reset(m_statement)) { + throw Sqlite::Exception("Can't execute statement", m_db->errmsg()); + } + m_bindnum = 1; + } + + }; // class Statement + + inline Statement* Database::prepare(const char* sql) { + return new Statement(this, sql); + } + +} // namespace Sqlite + +#endif // TAGSTATS_SQLITE_HPP diff --git a/tagstats/statistics_handler.hpp b/tagstats/statistics_handler.hpp index f1ece07..89767bd 100644 --- a/tagstats/statistics_handler.hpp +++ b/tagstats/statistics_handler.hpp @@ -22,7 +22,7 @@ You should have received a copy of the Licenses along with Osmium. If not, see */ -#include <osmium/utils/sqlite.hpp> +#include "sqlite.hpp" /** * Osmium handler that collects basic statistics from OSM data and @@ -32,7 +32,7 @@ class StatisticsHandler : public Osmium::Handler::Base { public: - StatisticsHandler(Osmium::Sqlite::Database& database) : Base(), m_database(database) { + StatisticsHandler(Sqlite::Database& database) : Base(), m_database(database) { // if you change anything in this array, also change the corresponding struct below static const char *sn[] = { "nodes", @@ -136,7 +136,7 @@ public: } void final() { - Osmium::Sqlite::Statement* statement_insert_into_main_stats = m_database.prepare("INSERT INTO stats (key, value) VALUES (?, ?);"); + Sqlite::Statement* statement_insert_into_main_stats = m_database.prepare("INSERT INTO stats (key, value) VALUES (?, ?);"); m_database.begin_transaction(); for (int i=0; m_stat_names[i]; ++i) { @@ -190,7 +190,7 @@ private: const char **m_stat_names; - Osmium::Sqlite::Database& m_database; + Sqlite::Database& m_database; osm_object_id_t m_id; osm_version_t m_version; diff --git a/tagstats/tagstats.cpp b/tagstats/tagstats.cpp index e941c88..fcb8cc8 100644 --- a/tagstats/tagstats.cpp +++ b/tagstats/tagstats.cpp @@ -154,7 +154,7 @@ int main(int argc, char *argv[]) { GeoDistribution::set_dimensions(width, height); Osmium::OSMFile infile(argv[optind]); - Osmium::Sqlite::Database db(argv[optind+1]); + Sqlite::Database db(argv[optind+1]); MapToInt<rough_position_t> map_to_int(left, bottom, right, top, width, height); TagStatsHandler handler(db, tags_list, map_to_int); Osmium::Input::read(infile, handler); diff --git a/tagstats/tagstats_handler.hpp b/tagstats/tagstats_handler.hpp index 29858d0..6d99e75 100644 --- a/tagstats/tagstats_handler.hpp +++ b/tagstats/tagstats_handler.hpp @@ -31,7 +31,7 @@ You should have received a copy of the Licenses along with Osmium. If not, see #include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/classification.hpp> -#include <osmium/utils/sqlite.hpp> +#include "sqlite.hpp" #include "string_store.hpp" /** @@ -207,7 +207,7 @@ class TagStatsHandler : public Osmium::Handler::Base { static const int string_store_size = 1024 * 1024 * 10; StringStore m_string_store; - Osmium::Sqlite::Database& m_database; + Sqlite::Database& m_database; void _timer_info(const char *msg) { int duration = time(0) - timer; @@ -287,7 +287,7 @@ class TagStatsHandler : public Osmium::Handler::Base { void _print_and_clear_distribution_images(bool for_nodes) { int sum_size=0; - Osmium::Sqlite::Statement* statement_insert_into_key_distributions = m_database.prepare("INSERT INTO key_distributions (key, object_type, png) VALUES (?, ?, ?);"); + Sqlite::Statement* statement_insert_into_key_distributions = m_database.prepare("INSERT INTO key_distributions (key, object_type, png) VALUES (?, ?, ?);"); m_database.begin_transaction(); for (key_hash_map_t::const_iterator it = tags_stat.begin(); it != tags_stat.end(); it++) { @@ -400,7 +400,7 @@ class TagStatsHandler : public Osmium::Handler::Base { public: - TagStatsHandler(Osmium::Sqlite::Database& database, const std::string& tags_list, MapToInt<rough_position_t>& map_to_int) : + TagStatsHandler(Sqlite::Database& database, const std::string& tags_list, MapToInt<rough_position_t>& map_to_int) : Base(), m_max_timestamp(0), m_string_store(string_store_size), @@ -452,7 +452,7 @@ public: int size; void* ptr = GeoDistribution::create_empty_png(&size); - Osmium::Sqlite::Statement* statement_insert_into_key_distributions = m_database.prepare("INSERT INTO key_distributions (png) VALUES (?);"); + Sqlite::Statement* statement_insert_into_key_distributions = m_database.prepare("INSERT INTO key_distributions (png) VALUES (?);"); m_database.begin_transaction(); statement_insert_into_key_distributions ->bind_blob(ptr, size) // column: png @@ -510,29 +510,29 @@ public: _print_memory_usage(); timer = time(0); - Osmium::Sqlite::Statement *statement_insert_into_keys = m_database.prepare("INSERT INTO keys (key, " \ + Sqlite::Statement *statement_insert_into_keys = m_database.prepare("INSERT INTO keys (key, " \ " count_all, count_nodes, count_ways, count_relations, " \ "values_all, values_nodes, values_ways, values_relations, " \ " users_all, " \ "cells_nodes, cells_ways) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - Osmium::Sqlite::Statement *statement_insert_into_tags = m_database.prepare("INSERT INTO tags (key, value, " \ + Sqlite::Statement *statement_insert_into_tags = m_database.prepare("INSERT INTO tags (key, value, " \ "count_all, count_nodes, count_ways, count_relations) " \ "VALUES (?, ?, ?, ?, ?, ?);"); #ifdef TAGSTATS_COUNT_KEY_COMBINATIONS - Osmium::Sqlite::Statement* statement_insert_into_key_combinations = m_database.prepare("INSERT INTO keypairs (key1, key2, " \ + Sqlite::Statement* statement_insert_into_key_combinations = m_database.prepare("INSERT INTO keypairs (key1, key2, " \ "count_all, count_nodes, count_ways, count_relations) " \ "VALUES (?, ?, ?, ?, ?, ?);"); #endif // TAGSTATS_COUNT_KEY_COMBINATIONS #ifdef TAGSTATS_COUNT_TAG_COMBINATIONS - Osmium::Sqlite::Statement* statement_insert_into_tag_combinations = m_database.prepare("INSERT INTO tagpairs (key1, value1, key2, value2, " \ + Sqlite::Statement* statement_insert_into_tag_combinations = m_database.prepare("INSERT INTO tagpairs (key1, value1, key2, value2, " \ "count_all, count_nodes, count_ways, count_relations) " \ "VALUES (?, ?, ?, ?, ?, ?, ?, ?);"); #endif // TAGSTATS_COUNT_TAG_COMBINATIONS - Osmium::Sqlite::Statement* statement_update_meta = m_database.prepare("UPDATE source SET data_until=?"); + Sqlite::Statement* statement_update_meta = m_database.prepare("UPDATE source SET data_until=?"); m_database.begin_transaction(); |