diff --git a/src/backend/cdb/executormgr.c b/src/backend/cdb/executormgr.c index 5a1c15d5c8..62473d77a5 100644 --- a/src/backend/cdb/executormgr.c +++ b/src/backend/cdb/executormgr.c @@ -1096,3 +1096,27 @@ executormgr_destory(SegmentDatabaseDescriptor *desc) pfree(desc); } +bool executormgr_has_cached_executor() +{ + return executor_cache.cached_num > 0; +} + +bool executormgr_clean_cached_executor_filter(PoolItem item) +{ + SegmentDatabaseDescriptor *desc = (SegmentDatabaseDescriptor *)item; + return desc->conn->asyncStatus == PGASYNC_IDLE; +} + +void executormgr_clean_cached_executor() +{ + /* go through each cached executor */ + int cleaned = 0; + if (!executor_cache.init) + { + return; + } + + cleaned = poolmgr_clean(executor_cache.pool, (PoolMgrIterateFilter) executormgr_clean_cached_executor_filter); + elog(DEBUG5, "cleaned %d idle executors", cleaned); +} + diff --git a/src/backend/cdb/poolmgr.c b/src/backend/cdb/poolmgr.c index eae0f041c1..f7194f657c 100644 --- a/src/backend/cdb/poolmgr.c +++ b/src/backend/cdb/poolmgr.c @@ -184,3 +184,45 @@ poolmgr_iterate(PoolMgrState *pool, PoolMgrIterateFilter filter, PoolMgrIterateC return; } +int poolmgr_clean(struct PoolMgrState *pool, PoolMgrIterateFilter filter) +{ + int res = 0; + HASH_SEQ_STATUS hash_seq; + PoolItemEntry *entry; + + if (!pool) + return res; + + hash_seq_init(&hash_seq, pool->hashtable); + while ((entry = hash_seq_search(&hash_seq))) + { + ListCell *curr = list_head(entry->list); + ListCell *prev = NULL; + while (curr != NULL) + { + PoolItem item = lfirst(curr); + if (filter && !filter(item)) + { + /* try next */ + prev = curr; + curr = lnext(prev); + continue; + } + + /* clean now */ + res++; + pool->callback(item); + entry->list = list_delete_cell(entry->list, curr, prev); + if (prev != NULL) + { + curr = lnext(prev); + } + else + { + curr = list_head(entry->list); + } + } + } + return res; +} + diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 2d3097f290..4fef10cd03 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -1399,9 +1399,9 @@ HandleClientWaitTimeout(void) /* * Free gangs to free up resources on the segDBs. */ - if (gangsExist()) + if (executormgr_has_cached_executor()) { - cleanupAllIdleGangs(); + executormgr_clean_cached_executor(); } } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index cf0123e347..c122280890 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4804,9 +4804,17 @@ PostgresMain(int argc, char *argv[], const char *username) * This means giving the end user enough time to type in the next SQL statement * */ - if (IdleSessionGangTimeout > 0 && gangsExist()) + if (IdleSessionGangTimeout > 0 && executormgr_has_cached_executor()) + { if (!enable_sig_alarm( IdleSessionGangTimeout /* ms */, false)) + { elog(FATAL, "could not set timer for client wait timeout"); + } + } + else if (IdleSessionGangTimeout == 0) + { + executormgr_clean_cached_executor(); + } } IdleTracker_DeactivateProcess(); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 0cf51df89b..b90f1ec9dd 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5067,7 +5067,7 @@ static struct config_int ConfigureNamesInt[] = { {"gp_vmem_idle_resource_timeout", PGC_USERSET, CLIENT_CONN_OTHER, gettext_noop("Sets the time a session can be idle (in milliseconds) before we release gangs on the segment DBs to free resources."), - gettext_noop("A value of 0 turns off the timeout."), + gettext_noop("A value of 0 closes idle gangs at once."), GUC_UNIT_MS | GUC_GPDB_ADDOPT }, &IdleSessionGangTimeout, diff --git a/src/include/cdb/executormgr.h b/src/include/cdb/executormgr.h index 31d44fa2ab..ce4442df19 100644 --- a/src/include/cdb/executormgr.h +++ b/src/include/cdb/executormgr.h @@ -98,5 +98,8 @@ extern bool executormgr_connect(struct SegmentDatabaseDescriptor *desc, bool is_writer, bool is_superuser); extern void executormgr_free_executor(struct SegmentDatabaseDescriptor *desc); +extern bool executormgr_has_cached_executor(); +extern void executormgr_clean_cached_executor(); + #endif /* EXECUTORMGR_H */ diff --git a/src/include/cdb/poolmgr.h b/src/include/cdb/poolmgr.h index 2821dd98b9..8408c250ef 100644 --- a/src/include/cdb/poolmgr.h +++ b/src/include/cdb/poolmgr.h @@ -32,6 +32,8 @@ typedef bool (*PoolMgrIterateFilter) (PoolItem item); extern struct PoolMgrState *poolmgr_create_pool(MemoryContext ctx, PoolMgrCleanCallback callback); extern bool poolmgr_drop_pool(struct PoolMgrState *pool); +extern int poolmgr_clean(struct PoolMgrState *pool, PoolMgrIterateFilter filter); + extern PoolItem poolmgr_get_item_by_name(struct PoolMgrState *pool, const char *name); extern PoolItem poolmgr_get_random_item(struct PoolMgrState *pool); extern void poolmgr_put_item(struct PoolMgrState *pool, const char *name, PoolItem item);