/*
* This file is part of mapper
*
- * Copyright (C) 2007 Kaj-Michael Lang
+ * Copyright (C) 2008 Kaj-Michael Lang
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
/* Use g_convert to transliterate names.. my iconv seems to be fucked so this didn't work... */
/* #define TRANSLIT_NAMES */
-#define FILE_BUFFER 65535
+#define FILE_BUFFER (128*1024)
-static guint node_cnt=0;
-static guint node_skip_cnt=0;
-static guint noded_cnt=0;
-static guint way_cnt=0;
-static guint way_names=0;
-static guint way_refs=0;
+static guint node_cnt=0; /* Nodes */
+static guint node_skip_cnt=0; /* Skipped nodes */
+static guint noded_cnt=0; /* Nodes with (usable) data */
+static guint way_cnt=0; /* Ways */
+static guint way_names=0; /* Ways with name */
+static guint way_refs=0; /* Ways with ref or int_ref */
static guint dbnode_cnt=0;
static guint dbnoded_cnt=0;
static guint dbway_cnt=0;
+/* For threaded importing */
+static GThread* import_thread=NULL;
+static GSourceFunc osm_import_progress_cb=NULL;
+static osm_import_data_req osm_import_req;
+static guint import_sid=0;
+
static gboolean is_update=FALSE;
static XML_Parser xp;
-
/* XML tag IDs */
typedef enum {
START,
{ "amenity", "biergarten", NODE_AMENITY_PUB },
{ "amenity", "cafe", NODE_AMENITY_CAFE },
{ "amenity", "fast_food", NODE_AMENITY_FOOD },
- { "amenity", "restaurant", NODE_AMENITY_FOOD },
+ { "amenity", "restaurant", NODE_AMENITY_RESTAURANT },
{ "amenity", "telephone", NODE_AMENITY_TELEPHONE },
{ "amenity", "toilets", NODE_AMENITY_WC },
{ "amenity", "bank", NODE_AMENITY_BANK },
{ "amenity", "police", NODE_AMENITY_POLICE },
+
{ "amenity", "speed_trap", NODE_AMENITY_SPEEDCAM },
{ "amenity", "speed_camera", NODE_AMENITY_SPEEDCAM },
{ "amenity", "speed camera", NODE_AMENITY_SPEEDCAM },
{ "amenity", "college", NODE_AMENITY_COLLEGE },
{ "amenity", "university", NODE_AMENITY_COLLEGE },
- { "amenity", "library", NODE_AMENITY_LIBRARY },
+ { "amenity", "library", NODE_AMENITY_LIBRARY },
{ "amenity", "townhall", NODE_AMENITY_TOWNHALL },
- { "amenity", "supermarket", NODE_AMENITY_SHOP },
- { "amenity", "shopping_centre", NODE_AMENITY_SHOP },
+ { "amenity", "supermarket", NODE_AMENITY_SHOP_SUPERMARKET },
+ { "amenity", "shopping_centre", NODE_AMENITY_SHOPPING_CENTER },
{ "amenity", "shop", NODE_AMENITY_SHOP },
{ "amenity", "shops", NODE_AMENITY_SHOP },
- { "amenity", "shopping", NODE_AMENITY_SHOP },
- { "amenity", "shopping_mall",NODE_AMENITY_SHOP },
+ { "amenity", "shopping", NODE_AMENITY_SHOPPING_CENTER },
+ { "amenity", "shopping_mall",NODE_AMENITY_SHOPPING_CENTER },
{ "amenity", "cycle_shop", NODE_AMENITY_SHOP },
{ "amenity", "bike_shop", NODE_AMENITY_SHOP },
{ "amenity", "coffee_shop", NODE_AMENITY_SHOP },
{ "amenity", "tea_shop", NODE_AMENITY_SHOP },
/* Shops */
- { "shop", "supermarket", NODE_AMENITY_SHOP },
+ { "shop", "supermarket", NODE_AMENITY_SHOP_SUPERMARKET },
+ { "shop", "alcohol", NODE_AMENITY_SHOP_ALCOHOL },
+ { "shop", "flowers", NODE_AMENITY_SHOP_FLOWERS },
{ "shop", "bakery", NODE_AMENITY_SHOP },
- { "shop", "alcohol", NODE_AMENITY_SHOP },
{ "shop", "butcher", NODE_AMENITY_SHOP },
- { "shop", "flowers", NODE_AMENITY_SHOP },
{ "shop", "clothing", NODE_AMENITY_SHOP },
{ "shop", "souvenir", NODE_AMENITY_SHOP },
{ "shop", "bicycles", NODE_AMENITY_SHOP },
{ "shop", "general_store",NODE_AMENITY_SHOP },
{ "shop", "food", NODE_AMENITY_SHOP },
{ "shop", "drinks", NODE_AMENITY_SHOP },
+ { "shop", "sex", NODE_AMENITY_SHOP_ADULT },
+
{ "shop", "pharmacy", NODE_AMENITY_PHARMACY },
/* Sport */
{ "railway", "halt", NODE_RAILWAY_HALT },
{ "aeroway", "terminal", NODE_AIRPORT_TERMINAL },
+ { "aeroway", "aerodrome", NODE_AIRPORT_TERMINAL },
/* Places */
{ "place", "city", NODE_PLACE_CITY },
static way *cway=NULL;
struct sql_stmt {
+ /* POIs */
sqlite3_stmt *insert_poi;
sqlite3_stmt *delete_osm_poi;
+ /* Places */
+ sqlite3_stmt *insert_place;
+ sqlite3_stmt *delete_places;
+
+ /* Nodes */
sqlite3_stmt *insert_node;
sqlite3_stmt *delete_nodes;
sqlite3_stmt *select_node;
sqlite3_stmt *update_node;
+ /* Ways */
sqlite3_stmt *insert_way_data;
sqlite3_stmt *insert_way_ref;
sqlite3_stmt *insert_way_pc;
sqlite3_stmt *delete_way_names_nls;
sqlite3_stmt *delete_way_ref;
sqlite3_stmt *delete_way_pc;
-
- sqlite3_stmt *insert_place;
- sqlite3_stmt *delete_place;
};
static struct sql_stmt sql;
-
static struct map_bbox bbox;
static gboolean use_bbox;
-void osm_free_way_data(way *w);
-void print_way(way *w);
+static void osm_free_way_data(way *w);
+static void print_way(way *w);
-void db_prepare(sqlite3 *db);
-gboolean db_insert_node(node *n);
-guint32 osm_find_way_place(way *w, node_type_t nt);
+static gboolean osm_db_prepare(sqlite3 *db);
+static gboolean db_insert_node(node *n);
+static guint32 osm_find_way_place(way *w, node_type_t nt);
/****************************************************/
/* Functions */
sqlite3_finalize(sql.update_node);
sqlite3_finalize(sql.insert_place);
-sqlite3_finalize(sql.delete_place);
+sqlite3_finalize(sql.delete_places);
sqlite3_finalize(sql.delete_way);
sqlite3_finalize(sql.insert_way_data);
sqlite3_finalize(sql.insert_way_names_nls);
}
-void
-db_prepare(sqlite3 *db)
+static gboolean
+osm_db_prepare(sqlite3 *db)
{
/* Way nodes */
sqlite3_prepare_v2(db, "insert or replace into nodes (nid,ilat,ilon,rlat,rlon,l,f) values (?,?,?,?,?,0,?)", -1, &sql.insert_node, NULL);
/* Places */
sqlite3_prepare_v2(db, "insert or replace into places (nid,type,name,isin_c,isin_p) values (?, ?, ?, ?, ?)", -1, &sql.insert_place, NULL);
-sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_place, NULL);
+sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_places, NULL);
/* POI nodes */
if (sqlite3_prepare_v2(db, "insert or replace into poi (osm_id, lat, lon, label, cat_id, public, source, priority, isin_c, isin_p, desc, url, postal_code) "
/* Way ref and int_ref */
sqlite3_prepare_v2(db, "insert or replace into way_ref (rid,ref,int_ref) values (?, ?, ?)", -1, &sql.insert_way_ref, NULL);
sqlite3_prepare_v2(db, "delete from way_ref", -1, &sql.delete_way_ref, NULL);
+
+return TRUE;
}
/********************************************************************/
-void
+static void
print_way(way *w)
{
#ifdef VERBOSE
#endif
}
-void
+static void
print_node(node *n)
{
#ifdef VERBOSE
/********************************************************************/
-gboolean
+static gboolean
db_insert_node(node *n)
{
gint32 lat, lon;
static gboolean
db_insert_way_n2n(way *w, node *nf, node *nt)
{
-if (!w) {
- g_printf("NULL WAY\n");
- return FALSE;
-}
-
-if (!nf) {
- g_printf("NULL NODE 1\n");
- return FALSE;
-}
-
-if (!nt) {
- g_printf("NULL NODE 2\n");
- return FALSE;
-}
+g_return_val_if_fail(w, FALSE);
+g_return_val_if_fail(nf, FALSE);
+g_return_val_if_fail(nt, FALSE);
sqlite3_bind_int(sql.insert_way_n2n, 1, w->id);
sqlite3_bind_int(sql.insert_way_n2n, 2, nf->id);
/**
* Insert way ref and int_ref
*/
-static void
+static gboolean
db_insert_way_ref(way *w)
{
if (!w->data)
- return;
+ return TRUE;
if (!w->data->ref && !w->data->int_ref)
- return;
+ return TRUE;
way_refs++;
if (w->data->int_ref)
sqlite3_bind_text(sql.insert_way_ref, 3, w->data->int_ref, -1, SQLITE_TRANSIENT);
-db_exec(db,sql.insert_way_ref);
+return db_exec(db,sql.insert_way_ref);
}
/**
* Insert way name
*/
-static void
+static gboolean
db_insert_way_name(way *w)
{
-gchar *norm;
-
if (!w->data)
- return;
+ return TRUE;
if (!w->data->name)
- return;
+ return TRUE;
way_names++;
sqlite3_bind_text(sql.insert_way_name, 2, w->data->name, -1, SQLITE_TRANSIENT);
#ifdef TRANSLIT_NAMES
-norm=g_convert(w->data->name, -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
-if (norm && strcmp(w->data->name, norm)!=0) {
- sqlite3_bind_text(sql.insert_way_name, 3, norm, -1, SQLITE_TRANSIENT);
+{
+ gchar *norm;
+ norm=g_convert(w->data->name, -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
+ if (norm && strcmp(w->data->name, norm)!=0) {
+ sqlite3_bind_text(sql.insert_way_name, 3, norm, -1, SQLITE_TRANSIENT);
+ }
+ if (norm)
+ g_free(norm);
}
-if (norm)
- g_free(norm);
#endif
-db_exec(db,sql.insert_way_name);
+return db_exec(db,sql.insert_way_name);
}
-static void
+static gboolean
db_delete_way_names_nls(way *w)
{
sqlite3_bind_int(sql.delete_way_names_nls, 1, w->id);
-db_exec(db,sql.delete_way_names_nls);
+return db_exec(db,sql.delete_way_names_nls);
}
-static void
+static gboolean
db_insert_way_pc(way *w)
{
if (!w->data)
- return;
+ return TRUE;
if (!w->data->postal_code)
- return;
+ return TRUE;
sqlite3_bind_int(sql.insert_way_pc, 1, w->id);
sqlite3_bind_text(sql.insert_way_pc, 2, w->data->postal_code, -1, SQLITE_TRANSIENT);
-db_exec(db,sql.insert_way_pc);
+return db_exec(db,sql.insert_way_pc);
}
-static void
+static gboolean
db_delete_way_pc(way *w)
{
sqlite3_bind_int(sql.delete_way_pc, 1, w->id);
-db_exec(db,sql.delete_way_pc);
+return db_exec(db,sql.delete_way_pc);
}
static void
db_insert_way_names_nls_cb(gpointer key, gpointer value, gpointer user_data)
{
-gchar *norm;
-
way *w=(way *)user_data;
sqlite3_bind_int(sql.insert_way_names_nls, 1, w->id);
sqlite3_bind_text(sql.insert_way_names_nls, 2, (gchar *)key, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sql.insert_way_names_nls, 3, (gchar *)value, -1, SQLITE_TRANSIENT);
#ifdef TRANSLIT_NAMES
-norm=g_convert((gchar *value), -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
-if (norm && strcmp((gchar *)value, norm)!=0) {
- sqlite3_bind_text(sql.insert_way_names_nls, 4, norm, -1, SQLITE_TRANSIENT);
+{
+ gchar *norm;
+ norm=g_convert((gchar *value), -1, "ASCII//TRANSLIT//IGNORE", "utf8", NULL, NULL, NULL);
+ if (norm && strcmp((gchar *)value, norm)!=0) {
+ sqlite3_bind_text(sql.insert_way_names_nls, 4, norm, -1, SQLITE_TRANSIENT);
+ }
+ if (norm)
+ g_free(norm);
}
-if (norm)
- g_free(norm);
#endif
db_exec(db,sql.insert_way_names_nls);
}
print_way(w);
-/* Get middle node, use it as way location */
-ncnt=g_slist_length(w->nodes);
-if (ncnt>1)
- wmn=g_slist_nth_data(w->nodes, ncnt/2);
-else
- wmn=0;
-
sqlite3_bind_int(sql.insert_way_data, 1, w->id);
sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt);
sqlite3_bind_int(sql.insert_way_data, 3, w->type);
sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin_c);
sqlite3_bind_int(sql.insert_way_data, 7, w->data->isin_p);
}
-if (wmn) {
- sqlite3_bind_double(sql.insert_way_data, 8, wmn->lat);
- sqlite3_bind_double(sql.insert_way_data, 9, wmn->lon);
-} else {
- g_printerr("Failed to get way location node!\n");
+
+/* Get middle node, use it as a rough way location */
+ncnt=g_slist_length(w->nodes);
+if (ncnt>1) {
+ wmn=g_slist_nth_data(w->nodes, ncnt/2);
+ if (wmn) {
+ sqlite3_bind_double(sql.insert_way_data, 8, wmn->lat);
+ sqlite3_bind_double(sql.insert_way_data, 9, wmn->lon);
+ } else {
+ g_printerr("Failed to get way middlepoint node for location information!\n");
+ }
}
db_exec(db,sql.insert_way_data);
return;
if (n->data!=NULL)
return;
-n->data=g_slice_new(node_data);
-n->data->name=NULL;
-n->data->url=NULL;
-n->data->desc=NULL;
-n->data->postal_code=NULL;
+n->data=g_slice_new0(node_data);
n->type=NODE_PLAIN;
noded_cnt++;
}
{
node *n=NULL;
-n=g_slice_new(node);
+n=g_slice_new0(node);
g_assert(n);
n->id=id;
n->lat=lat;
n->lon=lon;
-n->data=(node_data *)NULL;
return n;
}
node *n;
g_assert(osm_nodes);
-n=g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
-#if 0
-if (!n)
- g_printerr("ERROR: Node %d not found!\n", nid);
-#endif
-return n;
+return g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
}
static void
if (w->data!=NULL)
return;
-w->data=g_slice_new(way_data);
-w->data->name=NULL;
-w->data->names=NULL;
-w->data->ref=NULL;
-w->data->int_ref=NULL;
-w->data->postal_code=NULL;
-w->data->layer=0;
-w->data->speed=0;
+w->data=g_slice_new0(way_data);
}
-void
+static void
osm_free_way_data(way *w)
{
g_assert(w);
{
way *w;
-w=g_slice_new(way);
+w=g_slice_new0(way);
g_assert(w);
w->id=id;
-w->nodes=NULL;
w->type=WAY_UNWAYED;
-w->data=NULL;
-w->ncnt=0;
-w->flags=0;
/* Add to list of ways */
return w;
}
+static void
+osm_free_way(way *w)
+{
+if (w->nodes)
+ g_slist_free(w->nodes);
+g_slice_free(way, w);
+}
+
static void
osm_way_add_to_list(way *w)
{
return 0;
}
-guint32
+static guint32
osm_find_way_place(way *w, node_type_t nt)
{
gchar **isin;
dbnode_cnt++;
db_insert_node(n);
-if (dbnode_cnt % 26214==0)
- g_printf("\rNodes: %f%%\n",((float)dbnode_cnt/(float)node_cnt)*100);
+if (dbnode_cnt % 20000==0)
+ g_printf("\rNodes: %f%% (%u/%u)\n",
+ ((float)dbnode_cnt/(float)(node_cnt-node_skip_cnt))*100,
+ dbnode_cnt, node_cnt);
}
/**
g_print("Removing old OSM POIs...\n");
db_transaction_begin(db);
sqlite3_step(sql.delete_osm_poi);
-sqlite3_step(sql.delete_place);
+sqlite3_step(sql.delete_places);
return db_transaction_commit(db);
}
/*********************************************************************/
-static void
+static gboolean
osm_planet_clear_nodes(void)
{
-g_print("Clearing old nodes\n");
+g_print("Clearing old nodes...\n");
+db_transaction_begin(db);
sqlite3_step(sql.delete_nodes);
+return db_transaction_commit(db);
}
static gboolean
osm_planet_save_nodes(void)
{
-g_print("Storing nodes\n");
+g_print("Storing new nodes...\n");
db_transaction_begin(db);
g_hash_table_foreach(osm_nodes, osm_node_save_node, NULL);
return db_transaction_commit(db);
osm_way_save(way *value, gpointer user_data)
{
dbway_cnt++;
+db_transaction_begin(db);
db_insert_way(value);
-if (dbway_cnt % 16384==0 && dbway_cnt>0) {
- g_printf("\rWays: %f%%\n",(((float)dbway_cnt/(float)way_cnt)*100));
+db_transaction_commit(db);
+if (dbway_cnt % 15000==0 && dbway_cnt>0) {
+ g_printf("\rWays: %f%% (%u/%u)\n",
+ (((float)dbway_cnt/(float)way_cnt)*100),
+ dbway_cnt, way_cnt);
print_way(value);
}
}
static void
osm_planet_clear_ways(void)
{
-g_print("Clearing old data\n");
+g_print("Clearing old way data...\n");
+db_transaction_begin(db);
sqlite3_step(sql.delete_way);
sqlite3_step(sql.delete_way_name);
sqlite3_step(sql.delete_way_ref);
sqlite3_step(sql.delete_way_n2n);
+db_transaction_commit(db);
}
static gboolean
osm_planet_save_ways(void)
{
g_print("Inserting new ways\n");
-db_transaction_begin(db);
g_slist_foreach(osm_ways, osm_way_save, NULL);
-return db_transaction_commit(db);
}
/*********************************************************************/
}
}
+#define GET_NODE_KEY(key, nfield) { \
+ gchar *_kv; \
+ _kv=g_hash_table_lookup(osm_node_tags, key); \
+ if (_kv) { \
+ if (!nfield) { \
+ nfield=g_strstrip(g_utf8_normalize(_kv, -1, G_NORMALIZE_ALL_COMPOSE)); \
+ } else { \
+ gchar *_tmp=nfield; \
+ gchar *_norm=g_utf8_normalize(_kv, -1, G_NORMALIZE_ALL_COMPOSE); \
+ nfield=g_strdup_printf("%s %s", _tmp, g_strstrip(_norm)); \
+ g_free(_tmp); \
+ g_free(_norm); \
+ } \
+ } \
+}
+
+
static void
_osm_tag_end(void *userData, const char *name)
{
switch (t) {
case IN_NODE_TAG:
- if (node_cnt % 262140==0) {
- g_printf("Nodes: %d of %d, POIs: %d, Outside box: %d\n", node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
+ if (node_cnt % 25000==0) {
+ g_printf("Nodes: %u of %u, POIs: %u, Outside box: %u\n",
+ node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
}
if (!osm_node_tags)
* - Places (for is_in)
* - ...
*/
- if ((osm_node_check_box(cnode->lat, cnode->lon)==FALSE) &&
- (cnode->type<NODE_PLACE_START)) {
+ if ((osm_node_check_box(cnode->lat, cnode->lon)==FALSE) && (cnode->type<NODE_PLACE_START)) {
osm_free_node_data(cnode);
osm_free_node(cnode);
g_hash_table_destroy(osm_node_tags);
v=g_hash_table_lookup(osm_node_tags, "name");
if (v)
cnode->data->name=g_strstrip(g_utf8_normalize(v, -1, G_NORMALIZE_ALL_COMPOSE));
- v=g_hash_table_lookup(osm_node_tags, "note");
- if (v)
- cnode->data->desc=g_strstrip(g_strdup(v));
- v=g_hash_table_lookup(osm_node_tags, "postal_code");
- if (v)
- cnode->data->postal_code=g_strstrip(g_strdup(v));
+
+ GET_NODE_KEY("description", cnode->data->desc);
+ GET_NODE_KEY("note", cnode->data->desc);
+ GET_NODE_KEY("postal_code", cnode->data->postal_code);
+ GET_NODE_KEY("address", cnode->data->desc);
/* Links */
v=g_hash_table_lookup(osm_node_tags, "url");
if (v)
cway->data->postal_code=g_strdup(v);
- /* XXX: somehow handle the silly -1 'reversed' oneway */
v=g_hash_table_lookup(osm_way_tags, "oneway");
- if (v)
+ if (v) {
cway->flags|=W_ONEWAY;
+ if (strcmp(v, "-1")==0)
+ cway->nodes=g_slist_reverse(cway->nodes);
+ }
v=g_hash_table_lookup(osm_way_tags, "noexit");
if (v)
if (v)
cway->data->speed=atoi(v);
-#if 0
v=g_hash_table_lookup(osm_way_tags, "layer");
if (v)
cway->data->layer=atoi(v);
-#endif
v=g_hash_table_lookup(osm_way_tags, "junction");
if (v && strcasecmp(v,"roundabout")==0) {
if (cway->id!=0)
osm_way_add_to_list(cway);
+ else
+ osm_free_way(cway);
cway=NULL;
g_hash_table_destroy(osm_way_tags);
g_hash_table_destroy(osm_node_isin);
}
-
/************************************************************************/
static gint
}
gboolean
-osm_planet_parse_buffer(gchar *buffer, size_t r)
+osm_planet_parse_buffer(const gchar *buffer, size_t r)
{
if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) {
g_printerr("Parse error at line %d:\n%s\n",
- XML_GetCurrentLineNumber(xp),
- XML_ErrorString(XML_GetErrorCode(xp)));
+ (gint)XML_GetCurrentLineNumber(xp),
+ XML_ErrorString(XML_GetErrorCode(xp)));
return FALSE;
}
return TRUE;
return res;
}
+/**
+ * Set up bounding box for import.
+ *
+ */
void
osm_import_set_bbox(gboolean use_bb, gdouble latmin, gdouble lonmin, gdouble latmax, gdouble lonmax)
{
bbox.lat_min, bbox.lon_min, bbox.lat_max, bbox.lon_max);
}
+static void
+osm_print_import_stats(void)
+{
+g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt);
+g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
+g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
+g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
+g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes));
+}
+
+/**
+ * Simple helper to do all preparations and importing from planet -> database
+ *
+ */
gboolean
osm_import(const gchar *planet, const gchar *database)
{
return FALSE;
}
-db_create_tables(db);
-db_create_indexes(db);
-db_prepare(db);
+/* Set some sqlite PRAGMAs to speed up import */
+sqlite3_exec(db, "PRAGMA cache_size=16000;", NULL, NULL, NULL);
+sqlite3_exec(db, "PRAGMA locking_mode=EXCLUSIVE;", NULL, NULL, NULL);
+sqlite3_exec(db, "PRAGMA journal_mode=PERSIST;", NULL, NULL, NULL);
+sqlite3_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL);
+
+if (!osm_db_create(db)) {
+ g_printerr("Failed to create osm tables or indexes\n");
+ return FALSE;
+}
+
+if (!osm_db_prepare(db)) {
+ g_printerr("Failed to prepare sql statements\n");
+ return FALSE;
+}
osm_planet_parser_init();
return FALSE;
}
-g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt);
-g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
-g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
-g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
-g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes));
+osm_print_import_stats();
osm_planet_save_all_nodes();
osm_planet_save_all_ways();
osm_planet_parser_deinit();
+db_finalize();
db_close(&db);
+g_printf("All done.\n");
+return TRUE;
+}
+
+static gpointer
+osm_import_thread(gpointer user_data)
+{
+gboolean r;
+osm_import_data_req *req=(osm_import_data_req *)user_data;
+
+g_assert(req);
+g_assert(req->planet);
+g_assert(req->db);
+
+osm_import_progress_cb=req->progress_cb!=NULL ? req->progress_cb : NULL;
+
+r=osm_import(req->planet, req->db);
+g_debug("OSM import result: %d", r);
+
+g_free(req->planet);
+g_free(req->db);
+
+if (req->done_cb!=NULL)
+ g_idle_add(req->done_cb, GINT_TO_POINTER(r==TRUE ? 0 : 1));
+
+return r==TRUE ? 0 : 1;
+}
+
+/**
+ * Helper to start an import in the background using a thread.
+ *
+ * Two callback can be given, one for progress feedback and one when the operation is done.
+ * Done callback must call the join function.
+ * Only one import thread can run at a time.
+ *
+ */
+gboolean
+osm_import_bg(const gchar *planet, const gchar *database, GSourceFunc progress_cb, GSourceFunc done_cb)
+{
+GError *error=NULL;
+
+g_return_val_if_fail(import_thread==NULL, FALSE);
+
+osm_import_req.planet=g_strdup(planet);
+osm_import_req.db=g_strdup(database);
+osm_import_req.progress_cb=progress_cb;
+osm_import_req.done_cb=done_cb;
+
+import_thread=g_thread_create(osm_import_thread, &osm_import_req, TRUE, &error);
+if (import_thread==NULL) {
+ g_free(osm_import_req.planet);
+ g_free(osm_import_req.db);
+ g_printerr("Import thread creation failed.\n");
+ return FALSE;
+}
+if (osm_import_progress_cb!=NULL)
+ import_sid=g_timeout_add(1000, osm_import_progress_cb, NULL);
return TRUE;
}
+gint
+osm_import_join_bg(void)
+{
+gint ret;
+g_assert(import_thread!=NULL);
+
+if (import_sid!=0)
+ g_source_remove(import_sid);
+ret=g_thread_join(import_thread);
+import_thread=NULL;
+return ret;
+}