Skip to content

Commit f4c7b33

Browse files
committed
2 parents a795247 + 70466b5 commit f4c7b33

File tree

11 files changed

+132
-217
lines changed

11 files changed

+132
-217
lines changed

src/backend/catalog/pg_db_role_setting.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "catalog/indexing.h"
1717
#include "catalog/objectaccess.h"
1818
#include "catalog/pg_db_role_setting.h"
19+
#include "storage/proc.h"
1920
#include "utils/fmgroids.h"
2021
#include "utils/rel.h"
2122
#include "utils/tqual.h"
@@ -33,6 +34,7 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
3334

3435
/* Get the old tuple, if any. */
3536

37+
IsDedicatedBackend = true;
3638
rel = heap_open(DbRoleSettingRelationId, RowExclusiveLock);
3739
ScanKeyInit(&scankey[0],
3840
Anum_pg_db_role_setting_setdatabase,

src/backend/commands/copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2412,7 +2412,7 @@ CopyFrom(CopyState cstate)
24122412
* registers the snapshot it uses.
24132413
*/
24142414
InvalidateCatalogSnapshot();
2415-
if (!ThereAreNoPriorRegisteredSnapshots() || !ThereAreNoReadyPortals())
2415+
if (!ThereAreNoPriorRegisteredSnapshots() || (SessionPoolSize == 0 && !ThereAreNoReadyPortals()))
24162416
ereport(ERROR,
24172417
(errcode(ERRCODE_INVALID_TRANSACTION_STATE),
24182418
errmsg("cannot perform FREEZE because of prior transaction activity")));

src/backend/postmaster/postmaster.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ typedef struct bkend
178178
*/
179179
int bkend_type;
180180
bool dead_end; /* is it going to send an error and quit? */
181-
bool bgworker_notify; /* gets bgworker start/stop notifications */
181+
bool bgworker_notify;/* gets bgworker start/stop notifications */
182182
dlist_node elem; /* list link in BackendList */
183-
int session_pool_id; /* identifier of backends session pool */
183+
int session_pool_id;/* identifier of backends session pool */
184184
int worker_id; /* identifier of worker within session pool */
185185
} Backend;
186186

@@ -3273,11 +3273,18 @@ static void UnlinkBackend(Backend* bp)
32733273
if (--pool->n_workers != 0)
32743274
{
32753275
pool->workers[bp->worker_id] = pool->workers[pool->n_workers];
3276+
pool->workers[bp->worker_id]->worker_id = bp->worker_id;
32763277
pool->rr_index %= pool->n_workers;
32773278
}
32783279
closesocket(bp->session_send_sock);
3280+
bp->session_send_sock = PGINVALID_SOCKET;
32793281
elog(DEBUG2, "Cleanup backend %d", bp->pid);
32803282
}
3283+
}
3284+
3285+
static void DeleteBackend(Backend* bp)
3286+
{
3287+
UnlinkBackend(bp);
32813288
dlist_delete(&bp->elem);
32823289
free(bp);
32833290
}
@@ -3359,7 +3366,7 @@ CleanupBackend(int pid,
33593366
*/
33603367
BackgroundWorkerStopNotifications(bp->pid);
33613368
}
3362-
UnlinkBackend(bp);
3369+
DeleteBackend(bp);
33633370
break;
33643371
}
33653372
}
@@ -3461,7 +3468,7 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
34613468
ShmemBackendArrayRemove(bp);
34623469
#endif
34633470
}
3464-
UnlinkBackend(bp);
3471+
DeleteBackend(bp);
34653472
/* Keep looping so we can signal remaining backends */
34663473
}
34673474
else
@@ -4066,19 +4073,25 @@ BackendStartup(Port *port, int session_pool_id)
40664073
PostmasterSessionPool* pool = &SessionPools[session_pool_id];
40674074
bool dedicated_backend = SessionPoolSize == 0 || (SessionPoolPorts != 0 && session_pool_id == 0);
40684075

4069-
if (!dedicated_backend && pool->n_workers >= SessionPoolSize)
4076+
/* In case of session pooling instead of spawning new backend open new session at one of the existed backends. */
4077+
while (!dedicated_backend && pool->n_workers >= SessionPoolSize)
40704078
{
40714079
Backend* worker = pool->workers[pool->rr_index];
4072-
/* In case of session pooling instead of spawning new backend open new session at one of the existed backends. */
4073-
elog(DEBUG2, "Start new session in pool %d for socket %d at backend %d",
4074-
session_pool_id, port->sock, worker->pid);
4080+
pool->rr_index = (pool->rr_index + 1) % pool->n_workers; /* round-robin */
4081+
40754082
/* Send connection socket to the worker backend */
40764083
if (pg_send_sock(worker->session_send_sock, port->sock, worker->pid) < 0)
4077-
elog(FATAL, "Failed to send session socket: %m");
4078-
4079-
pool->rr_index = (pool->rr_index + 1) % pool->n_workers; /* round-robin */
4084+
{
4085+
elog(LOG, "Failed to send session socket: %m");
4086+
UnlinkBackend(worker);
4087+
}
4088+
else
4089+
{
4090+
elog(DEBUG2, "Start new session in pool %d for socket %d at backend %d",
4091+
session_pool_id, port->sock, worker->pid);
40804092

4081-
return STATUS_OK;
4093+
return STATUS_OK;
4094+
}
40824095
}
40834096

40844097

src/backend/tcop/postgres.c

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "utils/timeout.h"
7878
#include "utils/timestamp.h"
7979
#include "utils/builtins.h"
80+
#include "utils/varlena.h"
8081
#include "mb/pg_wchar.h"
8182

8283
/* ----------------
@@ -103,7 +104,7 @@ int PostAuthDelay = 0;
103104
pgsocket SessionPoolSock = PGINVALID_SOCKET;
104105
/* Pointer to the active session */
105106
SessionContext* ActiveSession;
106-
107+
bool IsDedicatedBackend;
107108

108109
/* ----------------
109110
* private variables
@@ -179,7 +180,7 @@ static int64 SessionCount; /* Number of sessions */
179180
static Port* BackendPort; /* Reference to the original port of this backend created when this backend was launched.
180181
* Session using this port may be already terminated, but since it is allocated in TopMemoryContext,
181182
* its content is still valid and is used as template for ports of new sessions */
182-
183+
static int nPooledSessions;/* Number of pooled sessions in this backend */
183184
static bool IdleInTransactionSessionError;
184185

185186
/* ----------------------------------------------------------------
@@ -214,6 +215,7 @@ static char* CreateSessionId(void)
214215
{
215216
char buf[64];
216217
pg_lltoa(++SessionCount, buf);
218+
nPooledSessions += 1;
217219
return pstrdup(buf);
218220
}
219221

@@ -223,6 +225,7 @@ static char* CreateSessionId(void)
223225
static void DeleteSession(SessionContext* session)
224226
{
225227
elog(DEBUG1, "Delete session %p, id=%s, memory context=%p", session, session->id, session->memory);
228+
nPooledSessions -= 1;
226229
FreeWaitEventSet(session->eventSet);
227230
RestoreSessionGUCs(session);
228231
ReleaseSessionGUCs(session);
@@ -2960,7 +2963,7 @@ ProcessInterrupts(void)
29602963
LockErrorCleanup();
29612964
/* don't send to client, we already know the connection to be dead. */
29622965
whereToSendOutput = DestNone;
2963-
ereport(FATAL,
2966+
ereport(ActiveSession ? ERROR : FATAL,
29642967
(errcode(ERRCODE_CONNECTION_FAILURE),
29652968
errmsg("connection to client lost")));
29662969
}
@@ -3646,6 +3649,35 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
36463649
#endif
36473650
}
36483651

3652+
static bool
3653+
IsDedicatedDatabase(char const* dbname)
3654+
{
3655+
List *namelist;
3656+
ListCell *l;
3657+
char *databases;
3658+
bool found = false;
3659+
3660+
/* Need a modifiable copy of namespace_search_path string */
3661+
databases = pstrdup(DedicatedDatabases);
3662+
3663+
if (!SplitIdentifierString(databases, ',', &namelist)) {
3664+
elog(ERROR, "invalid list syntax");
3665+
}
3666+
foreach(l, namelist)
3667+
{
3668+
char *curname = (char *) lfirst(l);
3669+
if (strcmp(curname, dbname) == 0)
3670+
{
3671+
found = true;
3672+
break;
3673+
}
3674+
}
3675+
list_free(namelist);
3676+
pfree(databases);
3677+
3678+
return found;
3679+
}
3680+
36493681
/* ----------------------------------------------------------------
36503682
* PostgresMain
36513683
* postgres main loop -- all backends, interactive or otherwise start here
@@ -3696,6 +3728,14 @@ PostgresMain(int argc, char *argv[],
36963728
progname)));
36973729
}
36983730

3731+
/* Serve all conections to "postgres" database by dedicated backends */
3732+
if (SessionPoolSize != 0 && IsDedicatedDatabase(dbname))
3733+
{
3734+
elog(LOG, "Backend is dedicated");
3735+
SessionPoolSize = 0;
3736+
closesocket(SessionPoolSock);
3737+
SessionPoolSock = PGINVALID_SOCKET;
3738+
}
36993739
/* Assign session for this backend in case of session pooling */
37003740
if (SessionPoolSize != 0)
37013741
{
@@ -3978,7 +4018,8 @@ PostgresMain(int argc, char *argv[],
39784018
pq_comm_reset();
39794019

39804020
/* Report the error to the client and/or server log */
3981-
EmitErrorReport();
4021+
if (MyProcPort)
4022+
EmitErrorReport();
39824023

39834024
/*
39844025
* Make sure debug_query_string gets reset before we possibly clobber
@@ -4223,12 +4264,12 @@ PostgresMain(int argc, char *argv[],
42234264
* TODO: Currently we assume that all sessions are accessing the same database under the same user.
42244265
* Just report an error if it is not true
42254266
*/
4226-
if (strcmp(port->database_name, MyProcPort->database_name) ||
4227-
strcmp(port->user_name, MyProcPort->user_name))
4267+
if (strcmp(port->database_name, BackendPort->database_name) ||
4268+
strcmp(port->user_name, BackendPort->user_name))
42284269
{
42294270
elog(FATAL, "Failed to open session (dbname=%s user=%s) in backend %d (dbname=%s user=%s)",
42304271
port->database_name, port->user_name,
4231-
MyProcPid, MyProcPort->database_name, MyProcPort->user_name);
4272+
MyProcPid, BackendPort->database_name, BackendPort->user_name);
42324273
}
42334274
else if (status == STATUS_OK)
42344275
{
@@ -4246,6 +4287,7 @@ PostgresMain(int argc, char *argv[],
42464287
StartTransactionCommand();
42474288
PerformAuthentication(MyProcPort);
42484289
CommitTransactionCommand();
4290+
SetTempNamespaceState(InvalidOid, InvalidOid);
42494291

42504292
/*
42514293
* Send GUC options to the client
@@ -4330,6 +4372,8 @@ PostgresMain(int argc, char *argv[],
43304372
*/
43314373
if (ConfigReloadPending)
43324374
{
4375+
if (ActiveSession && RestartPoolerOnReload)
4376+
proc_exit(0);
43334377
ConfigReloadPending = false;
43344378
ProcessConfigFile(PGC_SIGHUP);
43354379
}
@@ -4570,7 +4614,7 @@ PostgresMain(int argc, char *argv[],
45704614
* scenarios.
45714615
*/
45724616

4573-
if (SessionPool)
4617+
if (SessionPool && (!IsDedicatedBackend || SessionCount > 1))
45744618
{
45754619
CloseSession:
45764620
/* In case of session pooling close the session, but do not terminate the backend

src/backend/utils/cache/relcache.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include "rewrite/rewriteDefine.h"
7575
#include "rewrite/rowsecurity.h"
7676
#include "storage/lmgr.h"
77+
#include "storage/proc.h"
7778
#include "storage/smgr.h"
7879
#include "utils/array.h"
7980
#include "utils/builtins.h"
@@ -2059,6 +2060,13 @@ RelationIdGetRelation(Oid relationId)
20592060
RelationClearRelation(rd, true);
20602061
Assert(rd->rd_isvalid);
20612062
}
2063+
/*
2064+
* In case of session pooling, relation descriptor can be constructed by some other session,
2065+
* so we need to recheck rd_islocaltemp value
2066+
*/
2067+
if (ActiveSession && RELATION_IS_OTHER_TEMP(rd) && isTempOrTempToastNamespace(rd->rd_rel->relnamespace))
2068+
rd->rd_islocaltemp = true;
2069+
20622070
return rd;
20632071
}
20642072

src/backend/utils/init/globals.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,6 @@ int VacuumPageDirty = 0;
140140

141141
int VacuumCostBalance = 0; /* working state for vacuum */
142142
bool VacuumCostActive = false;
143+
144+
bool RestartPoolerOnReload = false;
145+
char *DedicatedDatabases;

0 commit comments

Comments
 (0)