= Setting up Londiste3 replication to partitions =

== Introduction ==

This sample shows how to use Londiste `part` handler module to split
one big table between two databases.

The target databases will have `partconf` schema which is usually
used to drive PL/Proxy.  Here it is used simply to provide
configuration to `part` handler.

== Prerequisites ==

Obviously skytools must be installed but in addition we need pghashlib and 
pgbench.

== Setting up the Root Database ==

=== Create databases ===

Create root database that will contain all data and two shard databases.

Run the following SQL: 
----
psql -c "CREATE DATABASE rootdb;"
psql -c "CREATE DATABASE sharddb_0;"
psql -c "CREATE DATABASE sharddb_1;"
----

Deploy hash function everywhere. This is needed because internal hashtext
function was changed between 8.3 and 8.4 versions and may be changed again
in future without consideration for its users.

---
psql rootdb < /usr/share/postgresql/8.4/contrib/hashlib.sql 
psql sharddb_0 < /usr/share/postgresql/8.4/contrib/hashlib.sql 
psql sharddb_1 < /usr/share/postgresql/8.4/contrib/hashlib.sql 
---

=== Set up pgbench schema ===

In this HowTo we are using pgbench for setting up the schema,
populating it with sample data and later running SQL loads to be replicated.

This command will create pgbench tables and fill them with data:
----
/usr/lib/postgresql/8.4/bin/pgbench -i -s 2 -F 80 rootdb
----

Write partconf.sql that will be deployed to all databases:
----
CREATE SCHEMA partconf;
CREATE TABLE partconf.conf (
    part_nr integer,
    max_part integer,
    db_code bigint,
    is_primary boolean,
    max_slot integer,
    cluster_name text
);

CREATE FUNCTION partconf.get_hash_raw
( i_input integer
) RETURNS integer
AS
$_$
-- used to wrap hashtext so that we can replace it in 8.4 with 
-- older implementation to keep compatibility
select hash_string($1::text, 'lookup2');
$_$ 
LANGUAGE sql;
----

Populate shard configuration tables. These values are used inside part.py.

----
psql rootdb < partconf.sql
psql sharddb_0 < partconf.sql
psql sharddb_1 < partconf.sql
psql sharddb_0 -c "insert into partconf.conf(part_nr, max_part) values(0,1);"
psql sharddb_1 -c "insert into partconf.conf(part_nr, max_part) values(1,1);"
----

Next create configuration files for root node and both partitions.

st3partsplit/st3_rootdb.ini
----
[londiste3]
job_name = st3_rootdb
db = dbname=rootdb
queue_name = replika
logfile = st3partsplit/log/st3_rootdb.log
pidfile = st3partsplit/pid/st3_rootdb.pid
----

st3partsplit/st3_sharddb_0.ini
----
[londiste3]
job_name = st3_sharddb_0
db = dbname=sharddb_0
queue_name = replika
logfile = st3partsplit/log/st3_sharddb_0.log
pidfile = st3partsplit/pid/st3_sharddb_0.pid
----

st3partsplit/st3_sharddb_1.ini
----
[londiste3]
job_name = st3_sharddb_1
db = dbname=sharddb_1
queue_name = replika
logfile = st3partsplit/log/st3_sharddb_1.log
pidfile = st3partsplit/pid/st3_sharddb_1.pid
----

Then create root node:

----
londiste3 st3partsplit/st3_rootdb.ini create-root node1 dbname=rootdb
----

And start the worker on root:
----
londiste3 -d st3partsplit/st3_rootdb.ini worker
----

And create leaf nodes and start the workers on partitions:

----
londiste3 st3partsplit/st3_sharddb_0.ini create-leaf node2_0 dbname=sharddb_0 --provider=dbname=rootdb
londiste3 -d st3partsplit/st3_sharddb_0.ini worker
----

Second node:
----
londiste3 st3partsplit/st3_sharddb_1.ini create-leaf node2_1 dbname=sharddb_1 --provider=dbname=rootdb
londiste3 -d st3partsplit/st3_sharddb_1.ini worker
----

Create config file st3partsplit/pgqd.ini for `pgqd` ("the ticker"):
----
[pgqd]

logfile = st3partsplit/log/pgqd.log
pidfile = st3partsplit/pid/pgqd.pid

----

Start the ticker process:
----
pgqd -d st3partsplit/pgqd.ini
----

Now add the replicated tables to root and partitions.
Here we use `--create` switch to add them to partition,
which means Londiste takes schema from root node and
creates tables on target nodes automatically.

The `--handler=part` tells londiste to use the `part` handler for replication,
the `--handler-arg=key=*id` specifies which key field to partition on.


Run command the following commands :
----
londiste3 st3partsplit/st3_rootdb.ini add-table pgbench_accounts --handler=part --handler-arg=key=aid
londiste3 st3partsplit/st3_sharddb_0.ini add-table pgbench_accounts --create --handler=part --handler-arg=key=aid
londiste3 st3partsplit/st3_sharddb_1.ini add-table pgbench_accounts --create --handler=part --handler-arg=key=aid

londiste3 st3partsplit/st3_rootdb.ini add-table pgbench_branches --handler=part --handler-arg=key=bid
londiste3 st3partsplit/st3_sharddb_0.ini add-table pgbench_branches --create --handler=part --handler-arg=key=bid
londiste3 st3partsplit/st3_sharddb_1.ini add-table pgbench_branches --create --handler=part --handler-arg=key=bid

londiste3 st3partsplit/st3_rootdb.ini add-table pgbench_tellers --handler=part --handler-arg=key=tid
londiste3 st3partsplit/st3_sharddb_0.ini add-table pgbench_tellers --create --handler=part --handler-arg=key=tid
londiste3 st3partsplit/st3_sharddb_1.ini add-table pgbench_tellers --create --handler=part --handler-arg=key=tid
----

The following command will run pgbench full speed with 5 parallel
database connections for 10 seconds.

----
/usr/lib/postgresql/8.4/bin/pgbench -T 10 -c 5 rootdb
----

After this is done, you can check that the tables on both sides have the same data:

----
londiste3 st3partsplit/st3_sharddb_0.ini compare
londiste3 st3partsplit/st3_sharddb_0.ini compare
----

Except of course that they don't - each partition will only have roughly half
the data from the root. But the row counts and checksums of the partitions
should both add up to the numbers on the master.
