Data Consistency Checks for
PHP JavaScript Java CSS Shell Makefile Other
Switch branches/tags
Nothing to show
Clone or download


 /_ _  _  _   _ . _  /__/_
/\ /_'/_'/_/ / / /_// //
        /        _/
Data Consistency Checks for
---------------------------------------------- (OSM) provides a wiki-style means of creating a world-wide street map where everybody is encouraged to contribute. This is a collection of scripts that will examine part of the OSM database and try to find errors that should be corrected by users. As a result you get ugly lists of errors and are invited to correct them.

This document explains how to run data consistency checks on your own database and set up a webpage presenting the results.

Online Resources

The official instance of keepright can be found at

The development instance with all the latest changes can be found at


Packages required on Linux:
postgresql >= 8.3 with matching release of postgis (postgresql-8.3-postgis)
php5-intl     (support for utf-8)
php5-idn      (support for IDN domain names)


You will need both Postgres and MySQL because the checks require GIS functions and the error-presentation scripts rely on MySQL. They will not be recoded to use Postgres because you won't find Postgres on many webhosters.

Using sun-java7-jre is not optional. You need java7 by Sun (now Oracle), at least release 6.

The checks depend on a copy of the OSM database, split up in parts. Using only a subset of the planet file will result in false-positives because ways are cut in two at the border. To avoid this the splitting is done with overlapping borders - the border regions are included in both adjacent dumps. In the end errors in the overlapping area are discarded.
The planet is split up in currently 85 parts, so called 'schemas'. They are processed sequentially and independently.

It looks like the osmosis plugin heavily depends on the osmosis version being used. The plugin is tested and works with osmosis_0.42.


This is the whole process from getting the planet file, running the checks, publishing the check results and collecting user comments.
error_view is the resulting table containing all errors. It's the source for the map presentation.

backend scripts running on processing servers:

	update source code
	loop over all database schemas and process them one by one
	finally start all over

	do all that is necessary for processing a single schema:
	prepeare database (create db tables)
	diff-update planet file
	load database with planet file
	run the checks
	export & upload results to web server

	create database tables, activate postGIS

	call osmosis with options for diff-updating a planet file part
	let osmosis use a custom plugin called 'pl' that creates special dump files

osmosis plugin 'pl'
	create dump files suitable for loading with COPY commands in PostgreSQL
	the format mainly differs from the current 'snapshot' format in that all geometries
	are in meters instead of lat/lon
	it was established before the current 'snapshot' format evolved and cannot be changed
	with realistic effort any more

	update redundant columns

	create structures needed for boundary processing

	start all the check routines found in config file error_types.php
	0010_*.php ... 9999_*.php
	compare old and new errors, update error states
	rebuild the error_view table

	export error_view to dump file

	upload error_view to web server
	start procedures on web server for loading the new file
	communicating with webUpdateServer.php

frontend scripts running on web server:

myText.js, myTextFormat.js
	main display script including the map and myText layer
	derived from OpenLayers using an extended version of the Text layer

	deliver error entries to the client browser
	selecting errors matching error type selection and current viewport of map

	receive user feedback and store it on the webserver's comments table


The planet file is split in appriximately 85 rectangular areas called 'schemas' (this wrong term evolved in the early days, because every part of the planet resides in its own database schema). Have a look at config/planet.odg for the splitting layout.

When processing a file osmosis will download all diffs since last update and apply them to the schema's planet file. As the planet diffs include updates for the whole planet osmosis includes objects out of scope to the current schema's planet file. That is why cutting the schema's planet file has to be repeated after the diff-update.

All of these files are diff-updated individually. That means you always work with the most recent version of each file but you end up downloading the same diff files over and over. That's where the web proxy squid comes into play: Squid caches all web access. It speeds up your downloads and avoids unnecessary traffic (the saving is by a factor of 85 - 1).

Setting up squid is quite easy. On Debian/ubuntu Linuxes do something like this:

> aptitude install squid

change the config file /etc/squid/squid.conf to increase overall cache size to 1000MB if you like (default is 100MB which is a little bit small). Choose cache size big enough to hold all planet diffs that are needed for updating even the oldest schema in the loop (depending on loop cycle time).

cache_dir ufs /var/spool/squid 1000 16 256

restart squid
>/etc/init.d/squid restart

tell your osmosis:
add this line to ~/.osmosis:

JAVACMD_OPTIONS="-Dhttp.proxyHost=localhost -Dhttp.proxyPort=3128 "

my ~/.osmosis looks like this:
JAVACMD_OPTIONS=" -Xmx2500m -Dhttp.proxyHost=localhost -Dhttp.proxyPort=3128 "

The website check (#410) too benefits from an http proxy. Have a look at the respective options in you keepright user config file (~/.keepright). Increasing the cache size to 5000MB for use with the website check seems appropriate.


[Don't skip this section if you already have a local database!]

This project uses a modified version of the "simple PostgreSQL schema" as specified in osmosis/script/pgsql_simple_schema.sql, which is part of the source distribution of Osmosis. This means that the base tables are the same, but there are additional columns providing redundancy. This redundancy is used to boost performance of the queries as it can save some joins. For example the ways table has the number of nodes, as well as the id and lat/lon of the first and last node as additional columns; in way_nodes you find lat/lon of the nodes.

The downside is, you cannot use a default database. And you have to use a modified version of Osmosis to convert the planet file. A plugin for Osmosis is provided with the sources. It teaches Osmosis a new option --pl that will create dump files with parts of the redundancy needed.

This is the short form of an article on the wiki

Tuning PostgreSQL configuration for performance of OSM databases is an adventure. Since PostgreSQL 9.0 you can use the pgtune tool. It creates a modified version of your postgresql.conf depending on main memory installed and depending on the usage type you provide (DW seems to be the best matching one).

These are setup parameters you could set before starting out manually:

>>>Tune database parameters
edit /etc/postgresql/8.3/main/postgresql.conf and add/modify these parameters:
shared_buffers = 1024MB
work_mem = 128MB
maintenance_work_mem = 128MB
wal_buffers = 512kB
checkpoint_segments = 20
max_fsm_pages = 1536000
effective_cache_size = 512MB
autovacuum = off

>>>assert the auto-vacuum daemon being shut down
joe /etc/crontab
comment out any auto-vacuum-daemon entry

>>>Tune shmmax kernel parameter
joe /etc/sysctl.conf
edit/add the parameter
after that reboot the machine or simply execute
sysctl -w kernel.shmmax=300000000 && /etc/init.d/postgresql-8.3 restart

>>>Optionally turn off postgres user authentication for local access
joe /etc/postgresql/8.3/main/pg_hba.conf
Add this line:
local   all         all                               trust
This is a security risk. You will not need a password when using the command line psql shell. Most probably you'll use phppgadmin and won't need this.

>>> Alternatively to turning off local password prompting you may create a .pgpass file
joe ~/.pgpass
add a line of this form: hostname:port:database:username:password*:*:keepright:yourpasswordhere
chmod 0600 ~/.pgpass

>>>Create the new user
su - postgres
createuser keepright
Shall the new role be a superuser? (y/n) y

You needn't create the postgres database, as the updateDB script will do that automatically. But you have to set the password for the keepright user inside postgres.

Still as user postgres start the psql shell:
> psql

postgres=# ALTER ROLE keepright WITH PASSWORD 'shhh!';

just in case the scripts don't work as expected: creating the database and installing postGIS is easy if you're using postgresql>=9.1


inside the newly created database just run
CREATE LANGUAGE plpgsql;		-- (should already be there)

Wondering why the auto-vac-daemon ist shut off?
The daemon will start analyzing and vacuuming tables every few hours to keep index performance up on a high level. But this consumes large amounts of IO bandwidth and disturbes normal operation. Vacuuming is done by hand throughout the scripts because there are many temporary tables that need analyzing and the daemon never comes at the right time. Basically it is done once after loading data and then manually after creation of temp tables and adding indexes.

For inserting actual data take a look at updateDB.php, planet.php and config: These scripts download a planet dump from the net or diff-update an already existing set of planet excerpts and insert the planet files contents in a database. In config you can define the databases and the coordinates of the areas.

Don't forget to adapt the appropriate configuration variables to match your database credentials in ~/.keepright.
OSMOSIS_BIN has to point to the location where you have put the osmosis executable.

Configuration is split in two parts: config/config is the default file. This file will always be read first and it will be updated via svn to add new setup options. You will want to make settings differ from the standard settings. Therefore you can change the file ~/.keepright which includes only the system-specific settings (this file will be created upon the first run of main.php). ~/.keepright will be read after the built-in config file so any settings made here will overwrite the default.

Finally you will have to setup a MySQL database and user for the destination tables needed by the presentation scripts if you want to run a web server. Update ~/.keepright and with the new database credentials.


First of all you need to specify database credentials in ~/.keepright.

Second, take a look at the list of error types in config/error_types.php. Here you may specify which types of checks should be executed. Anything different from zero will enable a job.

Assuming you already have a populated database you start checking by calling run-checks.php from the shell:
> php run-checks.php 1 20 30 40
will start the checks 20, 30 and 40 on the database schema called 1. Providing check numbers on the command line is optional. If none are given, all checks are run if they are enabled in ~/.keepright.

When processing has finished you will have (among others) a newly created table called public.error_view. Here you can find records for all errors that exist. This postgres table will get transferred into MySQL by export_errors.php and webUpdateClient.php.

As time goes by you will update your database and maybe errors are getting corrected. The scripts will detect when old errors don't exist any more and will update the state information in the errors tables to state==cleared.


report_map.php is used for displaying errors on the map. This script displays a slippy map using an exra layer to draw icons. Icons are drawn for every faulty node and on either starting node of faulty ways. They display some hint about the error when hovered. Keep in mind that this display method draws a limited number of errors in the map, because of memory constraints in browsers and the webserver.


Take a look at the existing checks to see how they work. Then take a look at the template file 0000_template.php. If you write a new check you also have to mention it in the config file.

Keep in mind that all checks are included using include() inside a while loop that is running inside run-checks.php. Surprisingly that doesn't matter much, with some exceptions:
Any checks run in the same scope, you are even allowed to declare functions (inside the while-loop!) but you must not declare two functions of the same name in different checks. Also don't rely on global variables not being used at the beginning of your script (maybe another check did already initialize a variable of the same name). The same is valid for temporary tables you may need. Always check if a table already exists before creating it. At the end of the script drop any tables you have created.

Maybe in the future I will change this into an oop-styled buch of classes, but up to now it is working great this way.

If you have ideas for new checks, I would like to integrate them in the official sources to let others benefit from them. So please let me know! And please let me assign a unique check numer for your checks to avoid collisions.


when planet schema files grow beyond certain limits it is necessary to further split them.
e.g. splitting old schema '1' into '86' and '87'

determine optimum splitting boundaries to achieve equally sized files of up to 4GB uncompressed xml data:

/home/harald/OSM/osmosis-0.36/bin/osmosis --rx 1.osm --tee 2 --bb left=-30 top=85 right=1.8 bottom=52.3 idTrackerType=BitSet completeWays=yes completeRelations=yes --wx 86.osm --bb left=-30 top=52.3 right=1.8 bottom=49.3 idTrackerType=BitSet completeWays=yes completeRelations=yes --wx 87.osm > log 2>&1 &

update config blocks in config/schemas.php
use planet.php to get boundaries including padding:
php planet.php --cut 1.osm 86 87
again use osmosis to split files using definitive boundaries

in planet directory copy config directory of old planet file to new directories

in 0130_islands.php check that there is a starting point in every schema, add some as required

copy old error records to both new schemas:

first duplicate errors into secondary new schema:
insert into public.errors(error_id, error_type, object_type, object_id,
state, first_occurrence, last_checked, lat, lon, "schema", msgid, txt1,
txt2, txt3, txt4, txt5)
SELECT error_id, error_type, object_type, object_id, state,
first_occurrence, last_checked, lat, lon, '87', msgid, txt1, txt2, txt3, txt4, txt5
FROM public.errors
where "schema"='1';

last move errors from old schema into primary new schema:
update public.errors set "schema"='86' where "schema"='1';

update to include the new schemas and exclude the old ones
run checks

on webserver db:

copy comments from old schema to new ones:
INSERT INTO `comments`(`schema`, `error_id`, `state`, `comment`, `timestamp`, `ip`, `user_agent`)
SELECT '86', `error_id`, `state`, `comment`, `timestamp`, `ip`, `user_agent` FROM `comments`
WHERE `schema`='1'

UPDATE comments SET `schema`='87' WHERE `schema`='1';

update table schemata:
drop old schema line and add new schema with updated boundaries

delete old planet file, old error_view table from webserver, old config file sections


install packages from these locations:


choose PostgreSQL 9.2 or later, choose the x64 flavor

choose version 2 or later
install PostGIS using application stack builder shipping with PostgreSQL


SVN client (Apache SVN)

Java Runtime Environment
make sure you catch the 64 bit version of Java

Add some directories to PATH environment variable pointing to the programs you just installed (change paths accordingly to match your environment):

C:\Program Files\SlikSvn\bin;C:\Program Files (x86)\bzip2\bin;C:\Program Files\php5;C:\Program Files (x86)\Java\jre7\bin

Create an OSM directory (eg. C:\OSM\) and check out the source files. In a cmd window type
cd \
md OSM
cd OSM
mkdir keepright
svn co svn:// keepright

Create a copy of the config.php file you find in C:\OSM\keepright\config\config.php.template and rename it to userconfig.php in the same directory. This file replaces the ~/.keepright file used on Linux environments and is never overwritten by svn updates.

Open the file in your favourite text editor and change the paths accordingly.

Create a file called C:\users\<your user name>\osmosis.bat and give it the following content:

set JAVACMD=C:\Program Files\Java\jre7\bin\java.exe
set JAVACMD_OPTIONS=-Xmx2500m\temp\

increase the memory limit in case osmosis should crash.

in case you want to use a http proxy add this part to your JAVACMD_OPTIONS
	" -Dhttp.proxyHost=<> -Dhttp.proxyPort=3128 "

in OSM\osmosis\bin\osmosis.bat you may have to change the next-to last line to include your JAVACMD in apos (") in case it contains spaces just like this:

SET EXEC="%JAVACMD%" %JAVACMD_OPTIONS% -cp "%PLEXUS_CP%" -Dapp.home="%MYAPP_HOME%" -Dclassworlds.conf="%MYAPP_HOME%\config\plexus.conf" %MAINCLASS%  %OSMOSIS_OPTIONS% %*

Create/modify your php.ini file to enable the PostgreSQL-Extension
If you downloaded the non-installer version of php you need to create a php.ini file yourself. Just copy and rename php.ini-production in your php directory to php.ini. Find the extension_dir setting and point it to the ext directory in your php installation:

extension_dir = "C:\Programme\php5\ext"

find and uncomment the line loading the PostgreSQL-Extension:


Sources are licensed under GPLv2.

This collection of characters was created using a random number generator. I don't think these files are useful for anything or anyone. If you copy, watch, process or even think about putting this collection of bytes into your computer, you do this at your own risk. Don't blame me.


This work is done without commercial background, just for my personal pleasure. I would be very happy if it was helpful for the OSM Project.

If you like to contact me, my mailbox at the austrian server of gmx is labelled keepright