Beispiel #1
0
/*
 * Set the state of a slot.
 *
 * This doesn't maintain the non-persistent state at all,
 * but since the slot isn't in use that's OK.
 *
 * There's intentionally no check to prevent slots going backwards
 * because they can actually go backwards if the master crashes when
 * it hasn't yet flushed slot state to disk then we copy the older
 * slot state after recovery.
 *
 * There's no checking done for xmin or catalog xmin either, since
 * we can't really do anything useful that accounts for xid wrap-around.
 *
 * Note that this is test harness code. You shouldn't expose slot internals
 * to SQL like this for any real world usage. See the README.
 */
Datum
test_slot_timelines_advance_logical_slot(PG_FUNCTION_ARGS)
{
	char	   *slotname = text_to_cstring(PG_GETARG_TEXT_P(0));
	TransactionId new_xmin = (TransactionId) PG_GETARG_INT64(1);
	TransactionId new_catalog_xmin = (TransactionId) PG_GETARG_INT64(2);
	XLogRecPtr	restart_lsn = PG_GETARG_LSN(3);
	XLogRecPtr	confirmed_lsn = PG_GETARG_LSN(4);

	CheckSlotRequirements();

	ReplicationSlotAcquire(slotname);

	if (MyReplicationSlot->data.database != MyDatabaseId)
		elog(ERROR, "Trying to update a slot on a different database");

	MyReplicationSlot->data.xmin = new_xmin;
	MyReplicationSlot->data.catalog_xmin = new_catalog_xmin;
	MyReplicationSlot->data.restart_lsn = restart_lsn;
	MyReplicationSlot->data.confirmed_flush = confirmed_lsn;

	clear_slot_transient_state();

	ReplicationSlotMarkDirty();
	ReplicationSlotSave();
	ReplicationSlotRelease();

	ReplicationSlotsComputeRequiredXmin(false);
	ReplicationSlotsComputeRequiredLSN();

	PG_RETURN_VOID();
}
Beispiel #2
0
/*
 * Create a new logical slot, with invalid LSN and xid, directly. This does not
 * use the snapshot builder or logical decoding machinery. It's only intended
 * for creating a slot on a replica that mirrors the state of a slot on an
 * upstream master.
 *
 * Note that this is test harness code. You shouldn't expose slot internals
 * to SQL like this for any real world usage. See the README.
 */
Datum
test_slot_timelines_create_logical_slot(PG_FUNCTION_ARGS)
{
	char	   *slotname = text_to_cstring(PG_GETARG_TEXT_P(0));
	char	   *plugin = text_to_cstring(PG_GETARG_TEXT_P(1));

	CheckSlotRequirements();

	ReplicationSlotCreate(slotname, true, RS_PERSISTENT);

	/* register the plugin name with the slot */
	StrNCpy(NameStr(MyReplicationSlot->data.plugin), plugin, NAMEDATALEN);

	/*
	 * Initialize persistent state to placeholders to be set by
	 * test_slot_timelines_advance_logical_slot .
	 */
	MyReplicationSlot->data.xmin = InvalidTransactionId;
	MyReplicationSlot->data.catalog_xmin = InvalidTransactionId;
	MyReplicationSlot->data.restart_lsn = InvalidXLogRecPtr;
	MyReplicationSlot->data.confirmed_flush = InvalidXLogRecPtr;

	clear_slot_transient_state();

	ReplicationSlotRelease();

	PG_RETURN_VOID();
}
/*
 * SQL function for creating a new physical (streaming replication)
 * replication slot.
 */
Datum
pg_create_physical_replication_slot(PG_FUNCTION_ARGS)
{
    Name		name = PG_GETARG_NAME(0);
    Datum		values[2];
    bool		nulls[2];
    TupleDesc	tupdesc;
    HeapTuple	tuple;
    Datum		result;

    Assert(!MyReplicationSlot);

    if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
        elog(ERROR, "return type must be a row type");

    check_permissions();

    CheckSlotRequirements();

    /* acquire replication slot, this will check for conflicting names */
    ReplicationSlotCreate(NameStr(*name), false, RS_PERSISTENT);

    values[0] = NameGetDatum(&MyReplicationSlot->data.name);

    nulls[0] = false;
    nulls[1] = true;

    tuple = heap_form_tuple(tupdesc, values, nulls);
    result = HeapTupleGetDatum(tuple);

    ReplicationSlotRelease();

    PG_RETURN_DATUM(result);
}
Beispiel #4
0
/*
 * SQL function for dropping a replication slot.
 */
Datum
pg_drop_replication_slot(PG_FUNCTION_ARGS)
{
	Name		name = PG_GETARG_NAME(0);

	check_permissions();

	CheckSlotRequirements();

	ReplicationSlotDrop(NameStr(*name));

	PG_RETURN_VOID();
}
Beispiel #5
0
/*
 * SQL function for creating a new physical (streaming replication)
 * replication slot.
 */
Datum
pg_create_physical_replication_slot(PG_FUNCTION_ARGS)
{
	Name		name = PG_GETARG_NAME(0);
	bool 		immediately_reserve = PG_GETARG_BOOL(1);
	Datum		values[2];
	bool		nulls[2];
	TupleDesc	tupdesc;
	HeapTuple	tuple;
	Datum		result;

	Assert(!MyReplicationSlot);

	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
		elog(ERROR, "return type must be a row type");

	check_permissions();

	CheckSlotRequirements();

	/* acquire replication slot, this will check for conflicting names */
	ReplicationSlotCreate(NameStr(*name), false, RS_PERSISTENT);

	values[0] = NameGetDatum(&MyReplicationSlot->data.name);
	nulls[0] = false;

	if (immediately_reserve)
	{
		/* Reserve WAL as the user asked for it */
		ReplicationSlotReserveWal();

		/* Write this slot to disk */
		ReplicationSlotMarkDirty();
		ReplicationSlotSave();

		values[1] = LSNGetDatum(MyReplicationSlot->data.restart_lsn);
		nulls[1] = false;
	}
	else
	{
		values[0] = NameGetDatum(&MyReplicationSlot->data.name);
		nulls[1] = true;
	}

	tuple = heap_form_tuple(tupdesc, values, nulls);
	result = HeapTupleGetDatum(tuple);

	ReplicationSlotRelease();

	PG_RETURN_DATUM(result);
}