#include <libpq-fe.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

/*
 * A quick and dirty way to generate a lot of pg_multixact/members segments.
 * First, CREATE TABLE foo AS SELECT 42.  Then run with two numeric arguments:
 * sessions (= number of connections) and loops (= number of repetitions).
 *
 * Each loop should generate sessions multixacts (because each session that
 * share-locks the row creates a new multixact) and sessions * (sessions - 1)
 * / 2 member entries (because each multixact created gets all the members
 * from the previous one plus the new one, so we finish up with a total of 1 +
 * 2 + ... + sessions member entries per loop, a triangular number, probably
 * order n^2).
 *
 * On my Mac laptop, run with 500 100000 (after increasing max_connections and
 * shared_buffers appropriately), this generates 2^32 multixact members in
 * under a couple of hours.
 */

int main(int argc, char **argv)
{
	int i;
	int sessions;
	int loop;
	int loops;
	PGconn **conns;
	PGresult *res;
	const char *conninfo = "dbname = postgres";
	
	assert(argc == 3);
	sessions = atoi(argv[1]);
	loops = atoi(argv[2]);
	conns = malloc(sizeof(PGconn *) * sessions);
	assert(conns);

	for (i = 0; i < sessions; ++i)
	{
		conns[i] = PQconnectdb(conninfo);
		assert(PQstatus(conns[i]) == CONNECTION_OK);
	}
	printf("%d sessions connected...\n", sessions);

	for (loop = 0; loop < loops; ++loop)
	{
		printf("Loop %d...\n", loop);
		for (i = 0; i < sessions; ++i)
		{
			res = PQexec(conns[i], "BEGIN");
			assert(PQresultStatus(res) == PGRES_COMMAND_OK);
			res = PQexec(conns[i], "SELECT * FROM foo WHERE id = 42 FOR SHARE");
			assert(PQresultStatus(res) == PGRES_TUPLES_OK);
			PQclear(res);
		}
		for (i = 0; i < sessions; ++i)
		{
			res = PQexec(conns[i], "ROLLBACK");
			assert(PQresultStatus(res) == PGRES_COMMAND_OK);
			PQclear(res);
		}
	}

	for (i = 0; i < sessions; ++i)
	{		
		PQfinish(conns[i]);
	}
	printf("Disconnected.\n");
	free(conns);
	return 0;
}
