Re: Logical Replication WIP

From: Andres Freund <andres(at)anarazel(dot)de>
To: Petr Jelinek <petr(at)2ndquadrant(dot)com>
Cc: Steve Singer <steve(at)ssinger(dot)info>, Peter Eisentraut <peter(dot)eisentraut(at)2ndquadrant(dot)com>, Craig Ringer <craig(at)2ndquadrant(dot)com>, Simon Riggs <simon(at)2ndquadrant(dot)com>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Logical Replication WIP
Date: 2016-11-04 12:07:48
Message-ID: 20161104120748.wziuf72y22peeund@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

/*
* Replication slot on-disk data structure.
@@ -225,10 +226,25 @@ ReplicationSlotCreate(const char *name, bool db_specific,
ReplicationSlot *slot = NULL;
int i;

- Assert(MyReplicationSlot == NULL);
+ /* Only aka ephemeral slots can survive across commands. */

What does this comment mean?

+ Assert(!MyReplicationSlot ||
+ MyReplicationSlot->data.persistency == RS_EPHEMERAL);

+ if (MyReplicationSlot)
+ {
+ /* Already acquired? Nothis to do. */

typo.

+ if (namestrcmp(&MyReplicationSlot->data.name, name) == 0)
+ return;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot create replication slot %s, another slot %s is "
+ "already active in this session",
+ name, NameStr(MyReplicationSlot->data.name))));
+ }
+

Why do we now create slots that are already created? That seems like an
odd API change.

/*
* If some other backend ran this code concurrently with us, we'd likely
* both allocate the same slot, and that would be bad. We'd also be at
@@ -331,10 +347,25 @@ ReplicationSlotAcquire(const char *name)
int i;
int active_pid = 0;

- Assert(MyReplicationSlot == NULL);
+ /* Only aka ephemeral slots can survive across commands. */
+ Assert(!MyReplicationSlot ||
+ MyReplicationSlot->data.persistency == RS_EPHEMERAL);

ReplicationSlotValidateName(name, ERROR);

+ if (MyReplicationSlot)
+ {
+ /* Already acquired? Nothis to do. */
+ if (namestrcmp(&MyReplicationSlot->data.name, name) == 0)
+ return;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot acquire replication slot %s, another slot %s is "
+ "already active in this session",
+ name, NameStr(MyReplicationSlot->data.name))));
+ }
+
/* Search for the named slot and mark it active if we find it. */
LWLockAcquire(ReplicationSlotControlLock, LW_SHARED);
for (i = 0; i < max_replication_slots; i++)
@@ -406,12 +437,26 @@ ReplicationSlotRelease(void)
}

Uh? We shouldn't ever have to acquire ephemeral

/*
+ * Same as above but only if currently acquired slot is peristent one.
+ */

s/peristent/persistent/

+void
+ReplicationSlotReleasePersistent(void)
+{
+ Assert(MyReplicationSlot);
+
+ if (MyReplicationSlot->data.persistency == RS_PERSISTENT)
+ ReplicationSlotRelease();
+}

Ick.

Hm. I think I have to agree a bit with Peter here. Overloading
MyReplicationSlot this way seems ugly, and I think there's a bunch of
bugs around it too.

Sounds what we really want is a) two different lifetimes for ephemeral
slots, session and "command" b) have a number of slots that are released
either after a failed transaction / command or at session end. The
easiest way for that appears to have a list of slots to be checked at
end-of-xact and backend shutdown.

Regards,

Andres

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Karl O. Pinc 2016-11-04 12:15:38 Re: Patch to implement pg_current_logfile() function
Previous Message Etsuro Fujita 2016-11-04 11:20:16 Re: Typo in comment in contrib/postgres_fdw/deparse.c