How to deinitialize a connection for background worker

From: "ISHAN CHHANGANI (dot)" <f20200230h(at)alumni(dot)bits-pilani(dot)ac(dot)in>
To: "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>
Subject: How to deinitialize a connection for background worker
Date: 2025-01-20 12:34:23
Message-ID: SEYPR01MB5313F08A8E70B8FBFF2938E2A7E72@SEYPR01MB5313.apcprd01.prod.exchangelabs.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I am working on a project which requires me to create a background worker. This worker checks some array(shared memory) every second and then connects to the database mentioned within the array. That is I want to connect to different databases using the same background worker without killing it.
Here is what I tried:
            BackgroundWorkerInitializeConnection(“db1", NULL, 0);

            //reconnect to another database for that first cleanup
            if (IsTransactionState())
            {
                  ereport(LOG, (errmsg("aborting current transaction")));
                  AbortCurrentTransaction();
            }

            if (MyProcPort)
            {
                  ereport(LOG, (errmsg("closing connection")));
                  closesocket(MyProcPort->sock);
                  MyProcPort = NULL;
            }

            AtEOXact_Files(false);
            AtEOXact_Buffers(false);

            MyDatabaseId = InvalidOid;
            MyDatabaseTableSpace = InvalidOid;

            InitializeTimeouts();
            ResetCatalogCaches();
            DeinitCatalogCache();
            DisablePortalManager();

            BackgroundWorkerInitializeConnection(“db2", NULL, 0);

==================

* DisablePortalManager
* Clean up the portal manager by destroying the hash table and memory context.
*/
void
DisablePortalManager(void)
{
if (PortalHashTable)
{
hash_destroy(PortalHashTable);
PortalHashTable = NULL;
}

if (TopPortalContext)
{
MemoryContextDelete(TopPortalContext);
TopPortalContext = NULL;
}
}

===================

* DeinitCatCache
* Releases all memory associated with a catalog cache entry
*/
void
DeinitCatCache(CatCache *cache)
{
if (!cache)
return;

/* Free all the cached tuples */
for (uint32 i = 0; i < cache->cc_nbuckets; i++)
{
            dlist_mutable_iter iter;
            dlist_foreach_modify(iter, &cache->cc_bucket[i])
            {
                  CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
                  dlist_delete(iter.cur);
                  pfree(ct);
            }
}

/* Free the bucket array */
if (cache->cc_bucket)
pfree(cache->cc_bucket);
cache->cc_bucket = NULL;

/* Free all CatCList entries */
dlist_mutable_iter list_iter;
dlist_foreach_modify(list_iter, &cache->cc_lists)
{
CatCList *cl = dlist_container(CatCList, cache_elem, list_iter.cur);
dlist_delete(&cl->cache_elem);
pfree(cl);
}

/* Reset other fields */
cache->cc_ntup = 0;
cache->cc_nbuckets = 0;
cache->cc_nkeys = 0;
      cache->cc_tupdesc = NULL;
      memset(cache->cc_skey, 0, sizeof(cache->cc_skey));
      cache->cc_reloid = InvalidOid;
      cache->cc_indexoid = InvalidOid;
      cache->yb_cc_is_fully_loaded = false;
/* Don't free cache itself - that's handled by the memory context */
}

/*
* DeinitCatalogCache
* Deinitialize the catalog cache system, freeing allocated memory
* and resetting state to allow reinitialization.
*/
void
DeinitCatalogCache(void)
{
int cacheId;

/* Only proceed if cache is actually initialized */
if (!CacheInitialized)
return;

/* Free each individual cache */
for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
{
if (SysCache[cacheId])
{
DeinitCatCache(SysCache[cacheId]);
SysCache[cacheId] = NULL;
}
}

/* Reset OID arrays */
SysCacheRelationOidSize = 0;
SysCacheSupportingRelOidSize = 0;

/* Mark cache as uninitialized */
CacheInitialized = false;
}
Wrote this by manually resolving errors one by one from InitPostgresImpl​
This still does not work completely. Does anyone know a simpler way which doesn’t require me to manually write all this?
I feel frontend(libpq) must have this functionality as when I do \c db2​ then it conection to it without killing the session.
How can we do this from backend?

--
The information contained in this electronic communication is intended
solely for the individual(s) or entity to which it is addressed. It may
contain proprietary, confidential and/or legally privileged information.
Any review, retransmission, dissemination, printing, copying or other use
of, or taking any action in reliance on the contents of this information by
person(s) or entities other than the intended recipient is strictly
prohibited and may be unlawful. If you have received this communication in
error, please notify us by responding to this email or telephone and
immediately and permanently delete all copies of this message and any
attachments from your system(s). The contents of this message do not
necessarily represent the views or policies of BITS Pilani.

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message vignesh C 2025-01-20 12:44:40 Re: create subscription with (origin = none, copy_data = on)
Previous Message Michael Paquier 2025-01-20 12:11:16 Re: per backend I/O statistics