mirror of https://github.com/citusdata/citus.git
Support for maintenance quota
parent
0bb5876a87
commit
4d775ab361
|
@ -327,7 +327,7 @@ StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ConnectionHashEntry *entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
|
ConnectionHashEntry *entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
|
||||||
if (!found || !entry->isValid)
|
if (!(found && entry->isValid))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We are just building hash entry or previously it was left in an
|
* We are just building hash entry or previously it was left in an
|
||||||
|
@ -377,11 +377,11 @@ StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
|
||||||
/* these two flags are by nature cannot happen at the same time */
|
/* these two flags are by nature cannot happen at the same time */
|
||||||
Assert(!((flags & WAIT_FOR_CONNECTION) && (flags & OPTIONAL_CONNECTION)));
|
Assert(!((flags & WAIT_FOR_CONNECTION) && (flags & OPTIONAL_CONNECTION)));
|
||||||
|
|
||||||
|
int sharedCounterFlags = (flags & REQUIRE_MAINTENANCE_CONNECTION)
|
||||||
|
? MAINTENANCE_CONNECTION
|
||||||
|
: 0;
|
||||||
if (flags & WAIT_FOR_CONNECTION)
|
if (flags & WAIT_FOR_CONNECTION)
|
||||||
{
|
{
|
||||||
int sharedCounterFlags = (flags & REQUIRE_MAINTENANCE_CONNECTION)
|
|
||||||
? MAINTENANCE_CONNECTION_POOL
|
|
||||||
: 0;
|
|
||||||
WaitLoopForSharedConnection(sharedCounterFlags, hostname, port);
|
WaitLoopForSharedConnection(sharedCounterFlags, hostname, port);
|
||||||
}
|
}
|
||||||
else if (flags & OPTIONAL_CONNECTION)
|
else if (flags & OPTIONAL_CONNECTION)
|
||||||
|
@ -392,7 +392,6 @@ StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
|
||||||
* cannot reserve the right to establish a connection, we prefer to
|
* cannot reserve the right to establish a connection, we prefer to
|
||||||
* error out.
|
* error out.
|
||||||
*/
|
*/
|
||||||
int sharedCounterFlags = 0;
|
|
||||||
if (!TryToIncrementSharedConnectionCounter(sharedCounterFlags, hostname, port))
|
if (!TryToIncrementSharedConnectionCounter(sharedCounterFlags, hostname, port))
|
||||||
{
|
{
|
||||||
/* do not track the connection anymore */
|
/* do not track the connection anymore */
|
||||||
|
@ -413,7 +412,6 @@ StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
|
||||||
*
|
*
|
||||||
* Still, we keep track of the connection counter.
|
* Still, we keep track of the connection counter.
|
||||||
*/
|
*/
|
||||||
int sharedCounterFlags = 0;
|
|
||||||
IncrementSharedConnectionCounter(sharedCounterFlags, hostname, port);
|
IncrementSharedConnectionCounter(sharedCounterFlags, hostname, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "distributed/worker_manager.h"
|
#include "distributed/worker_manager.h"
|
||||||
#include "distributed/tuplestore.h"
|
#include "distributed/tuplestore.h"
|
||||||
#include "distributed/worker_manager.h"
|
#include "distributed/worker_manager.h"
|
||||||
|
#include "math.h"
|
||||||
|
|
||||||
#define REMOTE_CONNECTION_STATS_COLUMNS 4
|
#define REMOTE_CONNECTION_STATS_COLUMNS 4
|
||||||
|
|
||||||
|
@ -104,9 +104,11 @@ typedef struct SharedWorkerNodeDatabaseConnStatsHashEntry
|
||||||
int MaxSharedPoolSize = 0;
|
int MaxSharedPoolSize = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
* Controlled via a GUC, never access directly, use GetSharedPoolSizeMaintenanceQuota().
|
||||||
|
* Percent of MaxSharedPoolSize reserved for maintenance operations.
|
||||||
|
* "0" effectively means that regular and maintenance connection will compete over the common pool
|
||||||
*/
|
*/
|
||||||
float SharedPoolSizeMaintenancePercent = 10.0f;
|
double SharedPoolSizeMaintenanceQuota = 0.1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Controlled via a GUC, never access directly, use GetLocalSharedPoolSize().
|
* Controlled via a GUC, never access directly, use GetLocalSharedPoolSize().
|
||||||
|
@ -140,7 +142,7 @@ static int SharedConnectionHashCompare(const void *a, const void *b, Size keysiz
|
||||||
static uint32 SharedWorkerNodeDatabaseHashHash(const void *key, Size keysize);
|
static uint32 SharedWorkerNodeDatabaseHashHash(const void *key, Size keysize);
|
||||||
static int SharedWorkerNodeDatabaseHashCompare(const void *a, const void *b, Size keysize);
|
static int SharedWorkerNodeDatabaseHashCompare(const void *a, const void *b, Size keysize);
|
||||||
static bool IsConnectionToLocalNode(SharedWorkerNodeConnStatsHashKey *connKey);
|
static bool IsConnectionToLocalNode(SharedWorkerNodeConnStatsHashKey *connKey);
|
||||||
static bool isConnectionSlotAvailable(SharedWorkerNodeConnStatsHashKey *connKey,
|
static bool isConnectionSlotAvailable(uint32 flags, SharedWorkerNodeConnStatsHashKey *connKey,
|
||||||
const SharedWorkerNodeConnStatsHashEntry *connectionEntry);
|
const SharedWorkerNodeConnStatsHashEntry *connectionEntry);
|
||||||
static bool
|
static bool
|
||||||
IncrementSharedConnectionCounterInternal(uint32 externalFlags, bool checkLimits, const char *hostname, int port,
|
IncrementSharedConnectionCounterInternal(uint32 externalFlags, bool checkLimits, const char *hostname, int port,
|
||||||
|
@ -256,10 +258,10 @@ GetMaxSharedPoolSize(void)
|
||||||
return MaxSharedPoolSize;
|
return MaxSharedPoolSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
double
|
||||||
GetSharedPoolSizeMaintenancePercent(void)
|
GetSharedPoolSizeMaintenanceQuota(void)
|
||||||
{
|
{
|
||||||
return SharedPoolSizeMaintenancePercent;
|
return SharedPoolSizeMaintenanceQuota;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -352,29 +354,6 @@ IncrementSharedConnectionCounter(uint32 flags, const char *hostname, int port)
|
||||||
IncrementSharedConnectionCounterInternal(flags, false, hostname, port, MyDatabaseId);
|
IncrementSharedConnectionCounterInternal(flags, false, hostname, port, MyDatabaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SharedWorkerNodeConnStatsHashKey PrepareWorkerNodeHashKey(const char *hostname, int port)
|
|
||||||
{
|
|
||||||
SharedWorkerNodeConnStatsHashKey key;
|
|
||||||
strlcpy(key.hostname, hostname, MAX_NODE_LENGTH);
|
|
||||||
if (strlen(hostname) > MAX_NODE_LENGTH)
|
|
||||||
{
|
|
||||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("hostname exceeds the maximum length of %d",
|
|
||||||
MAX_NODE_LENGTH)));
|
|
||||||
}
|
|
||||||
key.port = port;
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SharedWorkerNodeDatabaseConnStatsHashKey PrepareWorkerNodeDatabaseHashKey(const char *hostname,
|
|
||||||
int port,
|
|
||||||
Oid database)
|
|
||||||
{
|
|
||||||
SharedWorkerNodeDatabaseConnStatsHashKey workerNodeDatabaseKey;
|
|
||||||
workerNodeDatabaseKey.workerNodeKey = PrepareWorkerNodeHashKey(hostname, port);
|
|
||||||
workerNodeDatabaseKey.database = database;
|
|
||||||
return workerNodeDatabaseKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IncrementSharedConnectionCounterInternal(uint32 externalFlags,
|
IncrementSharedConnectionCounterInternal(uint32 externalFlags,
|
||||||
|
@ -437,10 +416,13 @@ IncrementSharedConnectionCounterInternal(uint32 externalFlags,
|
||||||
workerNodeDatabaseEntry->count = 0;
|
workerNodeDatabaseEntry->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment counter if possible */
|
/* Increment counter if a slot available */
|
||||||
bool connectionSlotAvailable = true;
|
bool connectionSlotAvailable = true;
|
||||||
connectionSlotAvailable = !checkLimits ||
|
connectionSlotAvailable =
|
||||||
isConnectionSlotAvailable(&workerNodeKey, workerNodeConnectionEntry);
|
!checkLimits ||
|
||||||
|
isConnectionSlotAvailable(externalFlags,
|
||||||
|
&workerNodeKey,
|
||||||
|
workerNodeConnectionEntry);
|
||||||
|
|
||||||
if (connectionSlotAvailable)
|
if (connectionSlotAvailable)
|
||||||
{
|
{
|
||||||
|
@ -460,11 +442,19 @@ static bool IsConnectionToLocalNode(SharedWorkerNodeConnStatsHashKey *connKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isConnectionSlotAvailable(SharedWorkerNodeConnStatsHashKey *connKey,
|
static bool isConnectionSlotAvailable(uint32 flags,
|
||||||
|
SharedWorkerNodeConnStatsHashKey *connKey,
|
||||||
const SharedWorkerNodeConnStatsHashEntry *connectionEntry)
|
const SharedWorkerNodeConnStatsHashEntry *connectionEntry)
|
||||||
{
|
{
|
||||||
bool connectionSlotAvailable = true;
|
bool connectionSlotAvailable = true;
|
||||||
bool connectionToLocalNode = IsConnectionToLocalNode(connKey);
|
bool connectionToLocalNode = IsConnectionToLocalNode(connKey);
|
||||||
|
/*
|
||||||
|
* Use full capacity for maintenance connections,
|
||||||
|
*/
|
||||||
|
int maintenanceConnectionsQuota =
|
||||||
|
(flags & MAINTENANCE_CONNECTION)
|
||||||
|
? 0
|
||||||
|
: (int) floor((double) GetMaxSharedPoolSize() * GetSharedPoolSizeMaintenanceQuota());
|
||||||
if (connectionToLocalNode)
|
if (connectionToLocalNode)
|
||||||
{
|
{
|
||||||
bool remoteConnectionsForLocalQueriesDisabled =
|
bool remoteConnectionsForLocalQueriesDisabled =
|
||||||
|
@ -489,7 +479,7 @@ static bool isConnectionSlotAvailable(SharedWorkerNodeConnStatsHashKey *connKey,
|
||||||
connectionSlotAvailable = false;
|
connectionSlotAvailable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (connectionEntry->count + 1 > GetMaxSharedPoolSize())
|
else if (connectionEntry->count + 1 > (GetMaxSharedPoolSize() - maintenanceConnectionsQuota))
|
||||||
{
|
{
|
||||||
connectionSlotAvailable = false;
|
connectionSlotAvailable = false;
|
||||||
}
|
}
|
||||||
|
@ -862,6 +852,30 @@ ShouldWaitForConnection(int currentConnectionCount)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SharedWorkerNodeConnStatsHashKey PrepareWorkerNodeHashKey(const char *hostname, int port)
|
||||||
|
{
|
||||||
|
SharedWorkerNodeConnStatsHashKey key;
|
||||||
|
strlcpy(key.hostname, hostname, MAX_NODE_LENGTH);
|
||||||
|
if (strlen(hostname) > MAX_NODE_LENGTH)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("hostname exceeds the maximum length of %d",
|
||||||
|
MAX_NODE_LENGTH)));
|
||||||
|
}
|
||||||
|
key.port = port;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SharedWorkerNodeDatabaseConnStatsHashKey PrepareWorkerNodeDatabaseHashKey(const char *hostname,
|
||||||
|
int port,
|
||||||
|
Oid database)
|
||||||
|
{
|
||||||
|
SharedWorkerNodeDatabaseConnStatsHashKey workerNodeDatabaseKey;
|
||||||
|
workerNodeDatabaseKey.workerNodeKey = PrepareWorkerNodeHashKey(hostname, port);
|
||||||
|
workerNodeDatabaseKey.database = database;
|
||||||
|
return workerNodeDatabaseKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
SharedConnectionHashHash(const void *key, Size keysize)
|
SharedConnectionHashHash(const void *key, Size keysize)
|
||||||
|
|
|
@ -125,6 +125,11 @@ enum MultiConnectionMode
|
||||||
*/
|
*/
|
||||||
REQUIRE_REPLICATION_CONNECTION_PARAM = 1 << 8,
|
REQUIRE_REPLICATION_CONNECTION_PARAM = 1 << 8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This flag specifies that connection is required for maintenance operations, e.g.
|
||||||
|
* transaction recovery, distributed deadlock detection. Such connections may have
|
||||||
|
* special treatment, like dedicated share of pool, etc.
|
||||||
|
*/
|
||||||
REQUIRE_MAINTENANCE_CONNECTION = 1 << 9
|
REQUIRE_MAINTENANCE_CONNECTION = 1 << 9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,10 @@
|
||||||
|
|
||||||
enum SharedPoolCounterMode
|
enum SharedPoolCounterMode
|
||||||
{
|
{
|
||||||
MAINTENANCE_CONNECTION_POOL = 1 << 0
|
/*
|
||||||
|
* Use this flag to reserve a connection from a maintenance quota
|
||||||
|
*/
|
||||||
|
MAINTENANCE_CONNECTION = 1 << 0
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int MaxSharedPoolSize;
|
extern int MaxSharedPoolSize;
|
||||||
|
@ -34,6 +37,7 @@ extern size_t SharedConnectionStatsShmemSize(void);
|
||||||
extern void SharedConnectionStatsShmemInit(void);
|
extern void SharedConnectionStatsShmemInit(void);
|
||||||
extern int GetMaxClientConnections(void);
|
extern int GetMaxClientConnections(void);
|
||||||
extern int GetMaxSharedPoolSize(void);
|
extern int GetMaxSharedPoolSize(void);
|
||||||
|
extern double GetSharedPoolSizeMaintenanceQuota(void);
|
||||||
extern int GetLocalSharedPoolSize(void);
|
extern int GetLocalSharedPoolSize(void);
|
||||||
extern bool TryToIncrementSharedConnectionCounter(uint32 flags, const char *hostname, int port);
|
extern bool TryToIncrementSharedConnectionCounter(uint32 flags, const char *hostname, int port);
|
||||||
extern void WaitLoopForSharedConnection(uint32 flags, const char *hostname, int port);
|
extern void WaitLoopForSharedConnection(uint32 flags, const char *hostname, int port);
|
||||||
|
|
Loading…
Reference in New Issue