00001
00002
00003
00004
00005
00006
00007
00008 #include <boost/program_options.hpp>
00009 #include <iostream>
00010 #include "../osmdb/osmdb.h"
00011 #include "../xmlparse/xmlparse.h"
00012 #include <functional>
00013
00014 void progress(int& i)
00015 {
00016 i++;
00017 if (i % 100000 == 0)
00018 std::cout << "Processed approximately " << i << " elements" << std::endl;
00019 }
00020
00021 void action_handler(osmdb::ImportTableAction act, int64_t amount)
00022 {
00023 using osmdb::ImportTableAction;
00024 switch (act)
00025 {
00026 case ImportTableAction::ANALYZE:
00027 std::cout << "Done analyzing" << std::endl;
00028 break;
00029 case ImportTableAction::CLEAR_IMPORT:
00030 std::cout << "Done cleaning up" << std::endl;
00031 break;
00032 case ImportTableAction::CREATE_IMPORT_INDEX:
00033 std::cout << "Created import indexes" << std::endl;
00034 break;
00035 case ImportTableAction::CREATE_IMPORT_PKEY:
00036 std::cout << "Created import primary key" << std::endl;
00037 break;
00038 case ImportTableAction::DELETE_DUPLICIT_NODE:
00039 std::cout << "Deleted " << amount << " duplicit nodes in import" << std::endl;
00040 break;
00041 case ImportTableAction::DELETE_DUPLICIT_RELATION:
00042 std::cout << "Deleted " << amount << " duplicit relations in import" << std::endl;
00043 break;
00044 case ImportTableAction::DELETE_DUPLICIT_WAY:
00045 std::cout << "Deleted " << amount << " duplicit ways in import" << std::endl;
00046 break;
00047 case ImportTableAction::DELETE_IMPORT_ORPHANS:
00048 std::cout << "Deleted " << amount << " orphan elements in import" << std::endl;
00049 break;
00050 case ImportTableAction::DELETE_INCOMPLETE_RELATION:
00051 std::cout << "Deleted " << amount << " incomplete relations in import" << std::endl;
00052 break;
00053 case ImportTableAction::DELETE_INCOMPLETE_WAY:
00054 std::cout << "Deleted " << amount << " incomplete ways in import" << std::endl;
00055 break;
00056 case ImportTableAction::DELETE_NODE_TO_DELETE:
00057 std::cout << "Deleted " << amount << " nodes which should be deleted" << std::endl;
00058 break;
00059 case ImportTableAction::DELETE_NODE_TO_UPDATE:
00060 std::cout << "Deleted " << amount << " nodes which should be updated" << std::endl;
00061 break;
00062 case ImportTableAction::DELETE_ORPHAN:
00063 std::cout << "Deleted " << amount << " orphan elements" << std::endl;
00064 break;
00065 case ImportTableAction::DELETE_RELATION_TO_DELETE:
00066 std::cout << "Deleted " << amount << " relations which should be deleted" << std::endl;
00067 break;
00068 case ImportTableAction::DELETE_RELATION_TO_UPDATE:
00069 std::cout << "Deleted " << amount << " relations which should be updated" << std::endl;
00070 break;
00071 case ImportTableAction::DELETE_WAY_TO_DELETE:
00072 std::cout << "Deleted " << amount << " ways which should be deleted" << std::endl;
00073 break;
00074 case ImportTableAction::DELETE_WAY_TO_UPDATE:
00075 std::cout << "Deleted " << amount << " ways which should be updated" << std::endl;
00076 break;
00077 case ImportTableAction::IMPORT_EDGES:
00078 std::cout << "Imported " << amount << " edges" << std::endl;
00079 break;
00080 case ImportTableAction::IMPORT_MEMBER_NODE:
00081 std::cout << "Imported " << amount << " member nodes" << std::endl;
00082 break;
00083 case ImportTableAction::IMPORT_MEMBER_REL:
00084 std::cout << "Imported " << amount << " member relations" << std::endl;
00085 break;
00086 case ImportTableAction::IMPORT_MEMBER_WAY:
00087 std::cout << "Imported " << amount << " member ways" << std::endl;
00088 break;
00089 case ImportTableAction::IMPORT_NODE:
00090 std::cout << "Imported " << amount << " nodes" << std::endl;
00091 break;
00092 case ImportTableAction::IMPORT_NODE_ATTR:
00093 std::cout << "Imported " << amount << " node attributes" << std::endl;
00094 break;
00095 case ImportTableAction::IMPORT_RELATION:
00096 std::cout << "Imported " << amount << " relations" << std::endl;
00097 break;
00098 case ImportTableAction::IMPORT_REL_ATTR:
00099 std::cout << "Imported " << amount << " relation attributes" << std::endl;
00100 break;
00101 case ImportTableAction::IMPORT_WAY:
00102 std::cout << "Imported " << amount << " ways" << std::endl;
00103 break;
00104 case ImportTableAction::IMPORT_WAY_ATTR:
00105 std::cout << "Imported " << amount << " way attributes" << std::endl;
00106 break;
00107 case ImportTableAction::IMPORT_WAY_NODE:
00108 std::cout << "Imported " << amount << " way nodes" << std::endl;
00109 break;
00110 case ImportTableAction::DELETE_DUPLICIT_ATTR:
00111 std::cout << "Deleted " << amount << " duplicit attributes in import" << std::endl;
00112 break;
00113 case ImportTableAction::DELETE_DUPLICIT_WAYNODE:
00114 std::cout << "Deleted " << amount << " duplicit waynodes in import" << std::endl;
00115 break;
00116 case ImportTableAction::DELETE_DUPLICIT_MEMBER:
00117 std::cout << "Deleted " << amount << " duplicit member elements in import" << std::endl;
00118 break;
00119 }
00120 }
00121
00122 bool proceed_handler()
00123 {
00124 while (true)
00125 {
00126 std::cout << "Proceed? (y/n)" << std::endl;
00127 std::string s;
00128 std::cin >> s;
00129 if (s == "y" || s == "yes")
00130 {
00131 return true;
00132 }
00133 if (s == "n" || s == "no")
00134 {
00135 return false;
00136 }
00137 std::cout << "Sorry, didn't understand, try again" << std::endl;
00138 }
00139 return true;
00140 }
00141
00142 void copy_to_db(std::string const& filename, osmdb::OsmDatabase& db)
00143 {
00144 osmdb::ElementCopy ins(db);
00145 osmxml::XmlParser pars;
00146 int done = 0;
00147 pars.node_handler = [&ins](osm::Node const & n)
00148 {
00149 ins.insert_node(n);
00150 };
00151 pars.way_handler = [&ins](osm::Way const & w)
00152 {
00153 ins.insert_way(w);
00154 };
00155 pars.relation_handler = [&ins](osm::Relation const & r)
00156 {
00157 ins.insert_relation(r);
00158 };
00159 pars.progress_handler = [&done]()
00160 {
00161 progress(done);
00162 };
00163 std::cout << "Starting copy" << std::endl;
00164 ins.start_copy();
00165 pars.parse_file(filename);
00166 ins.end_copy();
00167 std::cout << "Done copying" << std::endl;
00168 }
00169
00170 bool process_import_table(osmdb::OsmDatabase& db, bool quiet, bool recreate)
00171 {
00172 osmdb::ImportTableProcessor proc(db);
00173 bool status = false;
00174 proc.proceed_signal.connect([&]()
00175 {
00176 if (quiet)
00177 status = true;
00178 else
00179 status = proceed_handler();
00180 if (status && recreate)
00181 db.drop_primary_keys();
00182 return status;
00183 });
00184 proc.action_signal.connect(action_handler);
00185 proc.process();
00186 return status;
00187 }
00188
00189 int import(std::string const& inp, std::string const& dbname, std::string const& schema, bool init, bool recreate, bool copy, bool import, bool quiet, bool analyze)
00190 {
00191 try
00192 {
00193 std::string connstr;
00194 if (dbname != "")
00195 connstr = "dbname=" + dbname;
00196 psql::Database pdb(connstr, true);
00197 if (init && schema != "")
00198 pdb.create_schema(schema);
00199 if (schema != "")
00200 pdb.set_schema(schema);
00201 osmdb::OsmDatabase db(pdb);
00202 if (init)
00203 {
00204 db.create_tables();
00205 db.create_indexes_and_keys();
00206 }
00207 pdb.begin_transaction();
00208 if (recreate)
00209 {
00210 std::cout << "Dropping foreign keys and indexes" << std::endl;
00211 db.drop_foreign_keys();
00212 db.drop_indexes();
00213 }
00214 std::cout << "Starting import" << std::endl;
00215 bool status = true;
00216 if (copy)
00217 copy_to_db(inp, db);
00218 if (import)
00219 status = process_import_table(db, quiet, recreate);
00220 if (recreate)
00221 {
00222 std::cout << "Recreating indexes and keys" << std::endl;
00223 db.create_indexes_and_keys();
00224 }
00225 if (status)
00226 {
00227 pdb.commit_transaction();
00228 if (analyze)
00229 {
00230 std::cout << "Running analyze" << std::endl;
00231 pdb.analyze();
00232 }
00233 std::cout << "Success" << std::endl;
00234 }
00235 else
00236 {
00237 std::cout << "Cancelling changes" << std::endl;
00238 pdb.rollback_transaction();
00239 }
00240 }
00241 catch (xml_schema::parsing& p)
00242 {
00243 std::cout << "Error parsing input document" << std::endl << p;
00244 return 1;
00245 }
00246 catch (std::exception& ex)
00247 {
00248 std::cout << "Error occured" << std::endl << ex.what() << std::endl;
00249 return 1;
00250 }
00251 return 0;
00252 }
00253
00254 int main(int argc, char** argv)
00255 {
00256 boost::program_options::options_description desc("Utility to import data from xml file and do related tasks. Allowed options");
00257 desc.add_options()
00258 ("help,h", "print this help")
00259 ("input,i", boost::program_options::value<std::string>(), "input xml file")
00260 ("output-db,d", boost::program_options::value<std::string>(), "output postgresql database name")
00261 ("output-schema,s", boost::program_options::value<std::string>(), "output postgresql database schema")
00262 ("initialize,I", "create schema, tables keys and indexes")
00263 ("recreate-indexes,r", "drop indexes and keys before import and recreate afterward")
00264 ("no-questions,q", "do not ask questions")
00265 ("do-import,e", "execute import procedure (put data into appropriate tables)")
00266 ("analyze,a", "run analyze on database");
00267 boost::program_options::variables_map vm;
00268 boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
00269 boost::program_options::notify(vm);
00270 if (vm.count("help"))
00271 {
00272 std::cout << desc << std::endl;
00273 return 0;
00274 }
00275 bool proc_inp = false;
00276 std::string inp;
00277 if (vm.count("input"))
00278 {
00279 inp = vm["input"].as<std::string>();
00280 proc_inp = true;
00281 }
00282 std::string db;
00283 if (vm.count("output-db"))
00284 {
00285 db = vm["output-db"].as<std::string>();
00286 }
00287 std::string sch;
00288 if (vm.count("output-schema"))
00289 sch = vm["output-schema"].as<std::string>();
00290 bool init = vm.count("initialize");
00291 bool recreate = vm.count("recreate-indexes");
00292 bool quiet = vm.count("no-questions");
00293 bool process = vm.count("do-import");
00294 bool analyze = vm.count("analyze");
00295 if (!init && !analyze && !process && !proc_inp)
00296 {
00297 std::cout << "No action to be done" << std::endl;
00298 std::cout << desc << std::endl;
00299 return 0;
00300 }
00301 return import(inp, db, sch, init, recreate, proc_inp, process, quiet, analyze);
00302
00303 }