diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-10-06 23:21:45 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-10-06 23:21:45 +0000 |
| commit | 85801a4dbdee22f230637311681b8b03a72979db (patch) | |
| tree | 28054ba90fda332be0d5254e5bdaba5a2a51f1f2 /src/backend/utils | |
| parent | a965750abf2504e266e5071dc90365be9485395a (diff) | |
| download | postgresql-85801a4dbdee22f230637311681b8b03a72979db.tar.gz | |
Rearrange fmgr.c and relcache so that it's possible to keep FmgrInfo
lookup info in the relcache for index access method support functions.
This makes a huge difference for dynamically loaded support functions,
and should save a few cycles even for built-in ones. Also tweak dfmgr.c
so that load_external_function is called only once, not twice, when
doing fmgr_info for a dynamically loaded function. All per performance
gripe from Teodor Sigaev, 5-Oct-01.
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 7 | ||||
| -rw-r--r-- | src/backend/utils/adt/varbit.c | 7 | ||||
| -rw-r--r-- | src/backend/utils/adt/varchar.c | 6 | ||||
| -rw-r--r-- | src/backend/utils/cache/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/utils/cache/catcache.c | 23 | ||||
| -rw-r--r-- | src/backend/utils/cache/fcache.c | 14 | ||||
| -rw-r--r-- | src/backend/utils/cache/rel.c | 49 | ||||
| -rw-r--r-- | src/backend/utils/cache/relcache.c | 115 | ||||
| -rw-r--r-- | src/backend/utils/fmgr/dfmgr.c | 37 | ||||
| -rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 72 |
10 files changed, 186 insertions, 148 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index ebbb8b07ee..a03ca77440 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group * Copyright 1999 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.27 2001/10/05 17:28:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.28 2001/10/06 23:21:44 tgl Exp $ * * ---------- */ @@ -3243,7 +3243,6 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) { HeapTuple opr_tup; Oid opr_proc; - MemoryContext oldcontext; FmgrInfo finfo; opr_tup = SearchSysCache(OPERNAME, @@ -3265,9 +3264,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) * table entry, we must make sure any subsidiary structures of the * fmgr record are kept in TopMemoryContext. */ - oldcontext = MemoryContextSwitchTo(TopMemoryContext); - fmgr_info(opr_proc, &finfo); - MemoryContextSwitchTo(oldcontext); + fmgr_info_cxt(opr_proc, &finfo, TopMemoryContext); entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache, (void *) &typeid, diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index d75d05309d..a294bfc9ff 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -9,7 +9,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.18 2001/05/22 16:37:16 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.19 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "catalog/pg_type.h" #include "utils/array.h" #include "utils/fmgroids.h" +#include "utils/memutils.h" #include "utils/varbit.h" #define HEXDIG(z) ((z)<10 ? ((z)+'0') : ((z)-10+'A')) @@ -238,7 +239,7 @@ _bit(PG_FUNCTION_ARGS) static FmgrInfo bit_finfo; if (bit_finfo.fn_oid == InvalidOid) - fmgr_info(F_BIT, &bit_finfo); + fmgr_info_cxt(F_BIT, &bit_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &bit_finfo; @@ -452,7 +453,7 @@ _varbit(PG_FUNCTION_ARGS) static FmgrInfo varbit_finfo; if (varbit_finfo.fn_oid == InvalidOid) - fmgr_info(F_VARBIT, &varbit_finfo); + fmgr_info_cxt(F_VARBIT, &varbit_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &varbit_finfo; diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 7ed56e7962..c963709ac8 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.83 2001/10/03 05:29:24 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.84 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -285,7 +285,7 @@ _bpchar(PG_FUNCTION_ARGS) static FmgrInfo bpchar_finfo; if (bpchar_finfo.fn_oid == InvalidOid) - fmgr_info(F_BPCHAR, &bpchar_finfo); + fmgr_info_cxt(F_BPCHAR, &bpchar_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &bpchar_finfo; @@ -544,7 +544,7 @@ _varchar(PG_FUNCTION_ARGS) static FmgrInfo varchar_finfo; if (varchar_finfo.fn_oid == InvalidOid) - fmgr_info(F_VARCHAR, &varchar_finfo); + fmgr_info_cxt(F_VARCHAR, &varchar_finfo, TopMemoryContext); MemSet(&locfcinfo, 0, sizeof(locfcinfo)); locfcinfo.flinfo = &varchar_finfo; diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile index 01896efdd3..5ac5a06827 100644 --- a/src/backend/utils/cache/Makefile +++ b/src/backend/utils/cache/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/cache # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.14 2000/08/31 16:10:46 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.15 2001/10/06 23:21:44 tgl Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/utils/cache top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = catcache.o inval.o rel.o relcache.o syscache.o lsyscache.o \ +OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \ fcache.o temprel.o all: SUBSYS.o diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index ce4363706b..77112a694e 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.82 2001/08/21 16:36:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.83 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -269,23 +269,10 @@ CatalogCacheInitializeCache(CatCache *cache) */ cache->cc_skey[i].sk_procedure = EQPROC(keytype); - /* - * Note: to avoid any possible leakage of scan temporary data into - * the cache context, we do not switch into CacheMemoryContext while - * calling fmgr_info here. Instead set fn_mcxt on return. This - * would fail to work correctly if fmgr_info allocated any subsidiary - * data structures to attach to the FmgrInfo record; but it doesn't - * do so for built-in functions, and all the comparator functions - * for system caches should most assuredly be built-in functions. - * Currently there's no real need to fix fn_mcxt either, but let's do - * that anyway just to make sure it's not pointing to a dead context - * later on. - */ - - fmgr_info(cache->cc_skey[i].sk_procedure, - &cache->cc_skey[i].sk_func); - - cache->cc_skey[i].sk_func.fn_mcxt = CacheMemoryContext; + /* Do function lookup */ + fmgr_info_cxt(cache->cc_skey[i].sk_procedure, + &cache->cc_skey[i].sk_func, + CacheMemoryContext); /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */ cache->cc_skey[i].sk_attno = cache->cc_key[i]; diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c index bb1ac36f3e..92cf46a036 100644 --- a/src/backend/utils/cache/fcache.c +++ b/src/backend/utils/cache/fcache.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.40 2001/09/21 00:11:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.41 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,26 +23,22 @@ FunctionCachePtr init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt) { - MemoryContext oldcontext; FunctionCachePtr retval; /* Safety check (should never fail, as parser should check sooner) */ if (nargs > FUNC_MAX_ARGS) elog(ERROR, "init_fcache: too many arguments"); - /* Switch to a context long-lived enough for the fcache entry */ - oldcontext = MemoryContextSwitchTo(fcacheCxt); - - retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); + /* Create fcache entry in the desired context */ + retval = (FunctionCachePtr) MemoryContextAlloc(fcacheCxt, + sizeof(FunctionCache)); MemSet(retval, 0, sizeof(FunctionCache)); /* Set up the primary fmgr lookup information */ - fmgr_info(foid, &(retval->func)); + fmgr_info_cxt(foid, &(retval->func), fcacheCxt); /* Initialize additional info */ retval->setArgsValid = false; - MemoryContextSwitchTo(oldcontext); - return retval; } diff --git a/src/backend/utils/cache/rel.c b/src/backend/utils/cache/rel.c deleted file mode 100644 index 588566afc4..0000000000 --- a/src/backend/utils/cache/rel.c +++ /dev/null @@ -1,49 +0,0 @@ -/*------------------------------------------------------------------------- - * - * rel.c - * POSTGRES relation descriptor code. - * - * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.9 2001/01/24 19:43:15 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" -#include "access/istrat.h" - - -/* - * RelationIsValid is now a macro in rel.h -cim 4/27/91 - * - * All of the RelationGet...() functions are now macros in rel.h - * -mer 3/2/92 - */ - -/* - * RelationSetIndexSupport - * Sets index strategy and support info for a relation. - * - * This routine saves two pointers -- one to the IndexStrategy, and - * one to the RegProcs that support the indexed access method. - * - * Note: - * Assumes relation descriptor is valid. - * Assumes index strategy is valid. Assumes support is valid if non- - * NULL. - */ -void -RelationSetIndexSupport(Relation relation, - IndexStrategy strategy, - RegProcedure *support) -{ - Assert(PointerIsValid(relation)); - Assert(IndexStrategyIsValid(strategy)); - - relation->rd_istrat = strategy; - relation->rd_support = support; -} diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 8d85487139..c56d606076 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.145 2001/10/05 17:28:12 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.146 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -249,7 +249,6 @@ static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, Relation relation); static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, Relation oldrelation); -static void IndexedAccessMethodInitialize(Relation relation); static void AttrDefaultFetch(Relation relation); static void RelCheckFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); @@ -1044,7 +1043,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, * initialize index strategy and support information for this relation */ if (OidIsValid(relam)) - IndexedAccessMethodInitialize(relation); + RelationInitIndexAccessInfo(relation); /* * initialize the relation lock manager information @@ -1087,41 +1086,75 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, return relation; } -static void -IndexedAccessMethodInitialize(Relation relation) +/* + * Initialize index-access-method support data for an index relation + */ +void +RelationInitIndexAccessInfo(Relation relation) { + MemoryContext indexcxt; IndexStrategy strategy; RegProcedure *support; + FmgrInfo *supportinfo; int natts; - Size stratSize; - Size supportSize; uint16 amstrategies; uint16 amsupport; + Size stratSize; natts = relation->rd_rel->relnatts; amstrategies = relation->rd_am->amstrategies; amsupport = relation->rd_am->amsupport; + /* + * Make the private context to hold index access info. The reason + * we need a context, and not just a couple of pallocs, is so that + * we won't leak any subsidiary info attached to fmgr lookup records. + * + * Context parameters are set on the assumption that it'll probably not + * contain much data. + */ + indexcxt = AllocSetContextCreate(CacheMemoryContext, + RelationGetRelationName(relation), + 0, /* minsize */ + 512, /* initsize */ + 1024); /* maxsize */ + relation->rd_indexcxt = indexcxt; + + /* + * Allocate arrays to hold data + */ stratSize = AttributeNumberGetIndexStrategySize(natts, amstrategies); - strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext, - stratSize); + strategy = (IndexStrategy) MemoryContextAlloc(indexcxt, stratSize); if (amsupport > 0) { - supportSize = natts * (amsupport * sizeof(RegProcedure)); - support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext, - supportSize); + int nsupport = natts * amsupport; + + support = (RegProcedure *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(RegProcedure)); + supportinfo = (FmgrInfo *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo)); + MemSet(supportinfo, 0, nsupport * sizeof(FmgrInfo)); } else - support = (RegProcedure *) NULL; + { + support = NULL; + supportinfo = NULL; + } + /* + * Fill the strategy map and the support RegProcedure arrays. + * (supportinfo is left as zeroes, and is filled on-the-fly when used) + */ IndexSupportInitialize(strategy, support, &relation->rd_uniqueindex, RelationGetRelid(relation), relation->rd_rel->relam, amstrategies, amsupport, natts); - RelationSetIndexSupport(relation, strategy, support); + relation->rd_istrat = strategy; + relation->rd_support = support; + relation->rd_supportinfo = supportinfo; } /* @@ -1595,11 +1628,9 @@ RelationClearRelation(Relation relation, bool rebuildIt) pfree(relation->rd_am); if (relation->rd_rel) pfree(relation->rd_rel); - if (relation->rd_istrat) - pfree(relation->rd_istrat); - if (relation->rd_support) - pfree(relation->rd_support); freeList(relation->rd_indexlist); + if (relation->rd_indexcxt) + MemoryContextDelete(relation->rd_indexcxt); /* * If we're really done with the relcache entry, blow it away. But if @@ -2624,8 +2655,11 @@ init_irels(void) Relation ird; Form_pg_am am; Form_pg_class relform; + MemoryContext indexcxt; IndexStrategy strat; RegProcedure *support; + int nstrategies, + nsupport; int i; int relno; @@ -2646,6 +2680,13 @@ init_irels(void) return; } + /* safety check for incompatible relcache layout */ + if (len != sizeof(RelationData)) + { + write_irels(); + return; + } + ird = irel[relno] = (Relation) palloc(len); MemSet(ird, 0, len); @@ -2659,6 +2700,7 @@ init_irels(void) /* reset transient fields */ ird->rd_targblock = InvalidBlockNumber; ird->rd_fd = -1; + ird->rd_refcnt = 0; ird->rd_node.tblNode = MyDatabaseId; @@ -2716,6 +2758,17 @@ init_irels(void) } } + /* + * prepare index info context --- parameters should match + * RelationInitIndexAccessInfo + */ + indexcxt = AllocSetContextCreate(CacheMemoryContext, + RelationGetRelationName(ird), + 0, /* minsize */ + 512, /* initsize */ + 1024); /* maxsize */ + ird->rd_indexcxt = indexcxt; + /* next, read the index strategy map */ if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len)) { @@ -2723,27 +2776,18 @@ init_irels(void) return; } - strat = (IndexStrategy) palloc(len); + strat = (IndexStrategy) MemoryContextAlloc(indexcxt, len); if ((nread = FileRead(fd, (char *) strat, len)) != len) { write_irels(); return; } - /* oh, for god's sake... */ -#define SMD(i) strat->strategyMapData[i].entry[0] - - /* have to reinit the function pointers in the strategy maps */ - for (i = 0; i < am->amstrategies * relform->relnatts; i++) - { - fmgr_info(SMD(i).sk_procedure, - &(SMD(i).sk_func)); - } + /* have to invalidate any FmgrInfo data in the strategy maps */ + nstrategies = am->amstrategies * relform->relnatts; + for (i = 0; i < nstrategies; i++) + strat->strategyMapData[i].entry[0].sk_func.fn_oid = InvalidOid; - /* - * use a real field called rd_istrat instead of the bogosity of - * hanging invisible fields off the end of a structure - jolly - */ ird->rd_istrat = strat; /* finally, read the vector of support procedures */ @@ -2753,7 +2797,7 @@ init_irels(void) return; } - support = (RegProcedure *) palloc(len); + support = (RegProcedure *) MemoryContextAlloc(indexcxt, len); if ((nread = FileRead(fd, (char *) support, len)) != len) { write_irels(); @@ -2761,6 +2805,11 @@ init_irels(void) } ird->rd_support = support; + nsupport = relform->relnatts * am->amsupport; + ird->rd_supportinfo = (FmgrInfo *) + MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo)); + MemSet(ird->rd_supportinfo, 0, nsupport * sizeof(FmgrInfo)); + RelationInitLockInfo(ird); RelationCacheInsert(ird); diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index f46d40c5c4..3085187d8a 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.52 2001/10/04 19:13:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.53 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,14 +55,20 @@ static char * substitute_libpath_macro(const char * name); /* * Load the specified dynamic-link library file, and look for a function - * named funcname in it. If the function is not found, we raise an error - * if signalNotFound is true, else return (PGFunction) NULL. Note that - * errors in loading the library will provoke elog regardless of - * signalNotFound. - */ + * named funcname in it. (funcname can be NULL to just load the file.) + * + * If the function is not found, we raise an error if signalNotFound is true, + * else return (PGFunction) NULL. Note that errors in loading the library + * will provoke elog regardless of signalNotFound. + * + * If filehandle is not NULL, then *filehandle will be set to a handle + * identifying the library file. The filehandle can be used with + * lookup_external_function to lookup additional functions in the same file + * at less cost than repeating load_external_function. + */ PGFunction load_external_function(char *filename, char *funcname, - bool signalNotFound) + bool signalNotFound, void **filehandle) { DynamicFileList *file_scanner; PGFunction retval; @@ -130,6 +136,10 @@ load_external_function(char *filename, char *funcname, file_tail = file_scanner; } + /* Return handle if caller wants it. */ + if (filehandle) + *filehandle = file_scanner->handle; + /* * If funcname is NULL, we only wanted to load the file. */ @@ -201,11 +211,20 @@ load_file(char *filename) } } - load_external_function(fullname, (char *) NULL, false); + load_external_function(fullname, (char *) NULL, false, (void *) NULL); pfree(fullname); } +/* + * Lookup a function whose library file is already loaded. + * Return (PGFunction) NULL if not found. + */ +PGFunction +lookup_external_function(void *filehandle, char *funcname) +{ + return pg_dlsym(filehandle, funcname); +} static bool @@ -305,7 +324,7 @@ substitute_libpath_macro(const char * name) AssertArg(name != NULL); - if (strlen(name) == 0 || name[0] != '$') + if (name[0] != '$') return pstrdup(name); macroname_len = strcspn(name + 1, "/") + 1; diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 45ca532de2..5faa8a155c 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.54 2001/08/14 22:21:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.55 2001/10/06 23:21:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -121,12 +121,22 @@ fmgr_lookupByName(const char *name) * will be allocated in that context. The caller must ensure that this * context is at least as long-lived as the info struct itself. This is * not a problem in typical cases where the info struct is on the stack or - * in freshly-palloc'd space, but one must take extra care when the info - * struct is in a long-lived table. + * in freshly-palloc'd space. However, if one intends to store an info + * struct in a long-lived table, it's better to use fmgr_info_cxt. */ void fmgr_info(Oid functionId, FmgrInfo *finfo) { + fmgr_info_cxt(functionId, finfo, CurrentMemoryContext); +} + +/* + * Fill a FmgrInfo struct, specifying a memory context in which its + * subsidiary data should go. + */ +void +fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt) +{ const FmgrBuiltin *fbp; HeapTuple procedureTuple; Form_pg_proc procedureStruct; @@ -139,7 +149,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) */ finfo->fn_oid = InvalidOid; finfo->fn_extra = NULL; - finfo->fn_mcxt = CurrentMemoryContext; + finfo->fn_mcxt = mcxt; if ((fbp = fmgr_isbuiltin(functionId)) != NULL) { @@ -228,6 +238,7 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) probinattr; char *prosrcstring, *probinstring; + void *libraryhandle; PGFunction user_fn; Pg_finfo_record *inforec; Oldstyle_fnextra *fnextra; @@ -250,22 +261,19 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr)); /* Look up the function itself */ - user_fn = load_external_function(probinstring, prosrcstring, true); + user_fn = load_external_function(probinstring, prosrcstring, true, + &libraryhandle); /* Get the function information record (real or default) */ - inforec = fetch_finfo_record(probinstring, prosrcstring); + inforec = fetch_finfo_record(libraryhandle, prosrcstring); switch (inforec->api_version) { case 0: /* Old style: need to use a handler */ finfo->fn_addr = fmgr_oldstyle; - - /* - * OK to use palloc here because fn_mcxt is - * CurrentMemoryContext - */ - fnextra = (Oldstyle_fnextra *) palloc(sizeof(Oldstyle_fnextra)); + fnextra = (Oldstyle_fnextra *) + MemoryContextAlloc(finfo->fn_mcxt, sizeof(Oldstyle_fnextra)); finfo->fn_extra = (void *) fnextra; MemSet(fnextra, 0, sizeof(Oldstyle_fnextra)); fnextra->func = (func_ptr) user_fn; @@ -335,6 +343,8 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) /* * Fetch and validate the information record for the given external function. + * The function is specified by a handle for the containing library + * (obtained from load_external_function) as well as the function name. * * If no info function exists for the given name, it is not an error. * Instead we return a default info record for a version-0 function. @@ -346,7 +356,7 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple) * pg_proc. */ Pg_finfo_record * -fetch_finfo_record(char *filename, char *funcname) +fetch_finfo_record(void *filehandle, char *funcname) { char *infofuncname; PGFInfoFunction infofunc; @@ -355,12 +365,12 @@ fetch_finfo_record(char *filename, char *funcname) /* Compute name of info func */ infofuncname = (char *) palloc(strlen(funcname) + 10); - sprintf(infofuncname, "pg_finfo_%s", funcname); + strcpy(infofuncname, "pg_finfo_"); + strcat(infofuncname, funcname); /* Try to look up the info function */ - infofunc = (PGFInfoFunction) load_external_function(filename, - infofuncname, - false); + infofunc = (PGFInfoFunction) lookup_external_function(filehandle, + infofuncname); if (infofunc == (PGFInfoFunction) NULL) { /* Not found --- assume version 0 */ @@ -392,6 +402,34 @@ fetch_finfo_record(char *filename, char *funcname) /* + * Copy an FmgrInfo struct + * + * This is inherently somewhat bogus since we can't reliably duplicate + * language-dependent subsidiary info. We cheat by zeroing fn_extra, + * instead, meaning that subsidiary info will have to be recomputed. + */ +void +fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, + MemoryContext destcxt) +{ + memcpy(dstinfo, srcinfo, sizeof(FmgrInfo)); + dstinfo->fn_mcxt = destcxt; + if (dstinfo->fn_addr == fmgr_oldstyle) + { + /* For oldstyle functions we must copy fn_extra */ + Oldstyle_fnextra *fnextra; + + fnextra = (Oldstyle_fnextra *) + MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra)); + memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra)); + dstinfo->fn_extra = (void *) fnextra; + } + else + dstinfo->fn_extra = NULL; +} + + +/* * Specialized lookup routine for ProcedureCreate(): given the alleged name * of an internal function, return the OID of the function. * If the name is not recognized, return InvalidOid. |
