/* * _PG_init() - library load-time initialization * * DO NOT make this static nor change its name! */ void _PG_init(void) { /* Be sure we do initialization only once (should be redundant now) */ static bool inited = false; if (inited) return; pg_bindtextdomain(TEXTDOMAIN); DefineCustomEnumVariable("plpgsql.variable_conflict", gettext_noop("Sets handling of conflicts between PL/pgSQL variable names and table column names."), NULL, &plpgsql_variable_conflict, PLPGSQL_RESOLVE_ERROR, variable_conflict_options, PGC_SUSET, 0, NULL, NULL, NULL); EmitWarningsOnPlaceholders("plpgsql"); plpgsql_HashTableInit(); RegisterXactCallback(plpgsql_xact_cb, NULL); RegisterSubXactCallback(plpgsql_subxact_cb, NULL); /* Set up a rendezvous point with optional instrumentation plugin */ plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin"); inited = true; }
static void DtmInitialize() { bool found; static HASHCTL info; LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); dtm = ShmemInitStruct("dtm", sizeof(DtmState), &found); if (!found) { dtm->hashLock = LWLockAssign(); dtm->xidLock = LWLockAssign(); dtm->nReservedXids = 0; dtm->minXid = InvalidTransactionId; dtm->nNodes = MMNodes; dtm->disabledNodeMask = 0; pg_atomic_write_u32(&dtm->nReceivers, 0); dtm->initialized = false; BgwPoolInit(&dtm->pool, MMExecutor, MMDatabaseName, MMQueueSize); RegisterXactCallback(DtmXactCallback, NULL); RegisterSubXactCallback(DtmSubXactCallback, NULL); } LWLockRelease(AddinShmemInitLock); info.keysize = sizeof(TransactionId); info.entrysize = sizeof(TransactionId); info.hash = dtm_xid_hash_fn; info.match = dtm_xid_match_fn; xid_in_doubt = ShmemInitHash( "xid_in_doubt", DTM_HASH_SIZE, DTM_HASH_SIZE, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE ); info.keysize = sizeof(TransactionId); info.entrysize = sizeof(LocalTransaction); info.hash = dtm_xid_hash_fn; info.match = dtm_xid_match_fn; local_trans = ShmemInitHash( "local_trans", DTM_HASH_SIZE, DTM_HASH_SIZE, &info, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE ); MMDoReplication = true; TM = &DtmTM; }
/* * _PG_init() - library load-time initialization * * DO NOT make this static nor change its name! */ void _PG_init(void) { /* Be sure we do initialization only once (should be redundant now) */ static bool inited = false; if (inited) return; plpgsql_HashTableInit(); RegisterXactCallback(plpgsql_xact_cb, NULL); RegisterSubXactCallback(plpgsql_subxact_cb, NULL); /* Set up a rendezvous point with optional instrumentation plugin */ plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin"); inited = true; }
void _PG_init() { HASHCTL ctl; MemoryContext oldctx = MemoryContextSwitchTo(CacheMemoryContext); Py_Initialize(); RegisterXactCallback(multicorn_xact_callback, NULL); #if PG_VERSION_NUM >= 90300 RegisterSubXactCallback(multicorn_subxact_callback, NULL); #endif /* Initialize the global oid -> python instances hash */ MemSet(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(CacheEntry); ctl.hash = oid_hash; ctl.hcxt = CacheMemoryContext; InstancesHash = hash_create("multicorn instances", 32, &ctl, HASH_ELEM | HASH_FUNCTION); MemoryContextSwitchTo(oldctx); }
void start_transaction(PlxConn *plx_conn) { int curlevel; StringInfo sql = NULL; if (!strcmp(plx_conn->plx_cluster->isolation_level, "auto commit")) return; curlevel = GetCurrentTransactionNestLevel(); if (!is_remote_transaction) { RegisterXactCallback(xact_callback, NULL); RegisterSubXactCallback(subxact_callback, NULL); is_remote_transaction = true; } if (plx_conn->xlevel == 0) { sql = makeStringInfo(); appendStringInfo(sql, "start transaction isolation level %s;", plx_conn->plx_cluster->isolation_level); plx_conn->xlevel = 1; } while (plx_conn->xlevel < curlevel) { if (!sql) sql = makeStringInfo(); appendStringInfo(sql, "savepoint s%d; ", (int) ++(plx_conn->xlevel)); is_remote_subtransaction = true; } if (sql) PQclear(PQexec(plx_conn->pq_conn, sql->data)); }
/* * Get a PGconn which can be used to execute queries on the remote PostgreSQL * server with the user's authorization. A new connection is established * if we don't already have a suitable one, and a transaction is opened at * the right subtransaction nesting depth if we didn't do that already. * * will_prep_stmt must be true if caller intends to create any prepared * statements. Since those don't go away automatically at transaction end * (not even on error), we need this flag to cue manual cleanup. * * XXX Note that caching connections theoretically requires a mechanism to * detect change of FDW objects to invalidate already established connections. * We could manage that by watching for invalidation events on the relevant * syscaches. For the moment, though, it's not clear that this would really * be useful and not mere pedantry. We could not flush any active connections * mid-transaction anyway. */ PGconn * GetConnection(ForeignServer *server, UserMapping *user, bool will_prep_stmt) { bool found; ConnCacheEntry *entry; ConnCacheKey key; /* First time through, initialize connection cache hashtable */ if (ConnectionHash == NULL) { HASHCTL ctl; MemSet(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(ConnCacheKey); ctl.entrysize = sizeof(ConnCacheEntry); ctl.hash = tag_hash; /* allocate ConnectionHash in the cache context */ ctl.hcxt = CacheMemoryContext; ConnectionHash = hash_create("postgres_fdw connections", 8, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); /* * Register some callback functions that manage connection cleanup. * This should be done just once in each backend. */ RegisterXactCallback(pgfdw_xact_callback, NULL); RegisterSubXactCallback(pgfdw_subxact_callback, NULL); } /* Set flag that we did GetConnection during the current transaction */ xact_got_connection = true; /* Create hash key for the entry. Assume no pad bytes in key struct */ key.serverid = server->serverid; key.userid = user->userid; /* * Find or create cached entry for requested connection. */ entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found); if (!found) { /* initialize new hashtable entry (key is already filled in) */ entry->conn = NULL; entry->xact_depth = 0; entry->have_prep_stmt = false; entry->have_error = false; } /* * We don't check the health of cached connection here, because it would * require some overhead. Broken connection will be detected when the * connection is actually used. */ /* * If cache entry doesn't have a connection, we have to establish a new * connection. (If connect_pg_server throws an error, the cache entry * will be left in a valid empty state.) */ if (entry->conn == NULL) { entry->xact_depth = 0; /* just to be sure */ entry->have_prep_stmt = false; entry->have_error = false; entry->conn = connect_pg_server(server, user); elog(DEBUG3, "new postgres_fdw connection %p for server \"%s\"", entry->conn, server->servername); } /* * Start a new transaction or subtransaction if needed. */ begin_remote_xact(entry); /* Remember if caller will prepare statements */ entry->have_prep_stmt |= will_prep_stmt; return entry->conn; }