#!/bin/bash
#
# First argument : number of tables
# Second argument : size[Byte] of each tables
# Third argument : parallelism
# Fourth argument : execution numbers
#

port_pub=5431
data_pub=datapub

port_sub=5432
data_sub=datasub

echo '########################'
echo '# Check configurations #'
echo '########################'

declare num_tables
if [ -n "$1" ]; then
    num_tables=$1
else
    num_tables=10
fi

echo "$num_tables tables will be used while testing"

declare table_size
if [ -n "$2" ]; then
    table_size=$2
else
    table_size=0
fi

# logname must be defined here

log_pub=pub_${num_tables}_${table_size}_$3_$4.log
log_sub=sub_${num_tables}_${table_size}_$3_$4.log

#
# Convert from table_size to number of tuples. The equation was
# found by my tests...
#

declare num_tuples
if [ $table_size == "10kB" ]
then
    num_tuples=3250
else
    num_tuples=0
fi

echo "$num_tuples tuples will be inserted to each tables"


echo '############'
echo '# Clean up #'
echo '############'

pg_ctl stop -D $data_pub -w
pg_ctl stop -D $data_sub -w

rm -rf $data_pub $data_sub

echo '##########'
echo '# Set up #'
echo '##########'

initdb -D $data_pub -U postgres
initdb -D $data_sub -U postgres

cat << EOF >> $data_pub/postgresql.conf
wal_level = logical
port = $port_pub
shared_buffers = 40GB
max_worker_processes = 32
max_parallel_maintenance_workers = 24
max_parallel_workers = 32
synchronous_commit = off
checkpoint_timeout = 1d
max_wal_size = 24GB
min_wal_size = 15GB
autovacuum = off
max_sync_workers_per_subscription = 8
log_line_prefix = '%n [%p] '
max_wal_senders = 200
max_replication_slots = 200
EOF

cat << EOF >> $data_sub/postgresql.conf
wal_level = logical
port = $port_sub
shared_buffers = 40GB
max_worker_processes = 32
max_parallel_maintenance_workers = 24
max_parallel_workers = 32
synchronous_commit = off
checkpoint_timeout = 1d
max_wal_size = 24GB
min_wal_size = 15GB
autovacuum = off
max_sync_workers_per_subscription = $3
max_logical_replication_workers = 50
log_line_prefix = '%n [%p] '
max_replication_slots = 200
EOF

pg_ctl -D $data_pub start -w -l $log_pub
pg_ctl -D $data_sub start -w -l $log_sub

(
    echo -e "SELECT 'CREATE TABLE manytables_'||i||'(i int);' FROM generate_series(1, $num_tables) g(i) \gexec"
    echo -e "SELECT 'INSERT INTO manytables_'||i||' VALUES (generate_series(1, $num_tuples))' FROM generate_series(1, $num_tables) g(i) \gexec"
) | psql -U postgres -p $port_pub

psql -U postgres -p $port_pub -c "SELECT pg_create_logical_replication_slot('mysub_slot', 'pgoutput');"
psql -U postgres -p $port_pub -c "CREATE PUBLICATION mypub FOR ALL TABLES;"

(
    echo -e "SELECT 'CREATE TABLE manytables_'||i||'(i int);' FROM generate_series(1, $num_tables) g(i) \gexec"
    echo -e "CREATE OR REPLACE PROCEDURE log_rep_test(max INTEGER) AS \$\$
DECLARE
    counter INTEGER := 1;
    total_duration INTERVAL := '0';
    avg_duration FLOAT := 0.0;
    start_time TIMESTAMP;
    end_time TIMESTAMP;
BEGIN
    WHILE counter <= max LOOP
        
        EXECUTE 'DROP SUBSCRIPTION IF EXISTS mysub;';

        start_time := clock_timestamp();
        EXECUTE 'CREATE SUBSCRIPTION mysub CONNECTION ''user=postgres port=$port_pub'' PUBLICATION mypub WITH (create_slot=false, slot_name=''mysub_slot'');';
        COMMIT;

        WHILE EXISTS (SELECT 1 FROM pg_subscription_rel WHERE srsubstate != 'r') LOOP
            COMMIT;
        END LOOP;

        end_time := clock_timestamp();


        EXECUTE 'ALTER SUBSCRIPTION mysub DISABLE;';
        EXECUTE 'ALTER SUBSCRIPTION mysub SET (slot_name = none);';

        
        total_duration := total_duration + (end_time - start_time);
        
        counter := counter + 1;
    END LOOP;
    
    IF max > 0 THEN
        avg_duration := EXTRACT(EPOCH FROM total_duration) / max * 1000;
    END IF;
    
    RAISE NOTICE '%', avg_duration;
END;
\$\$ LANGUAGE plpgsql;
"
) | psql -U postgres -p $port_sub

psql -U postgres -p $port_sub -c "call log_rep_test(1)"
