📄 portalmem.c
字号:
/*------------------------------------------------------------------------- * * portalmem.c * backend portal memory context management stuff * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.23.2.2 1999/09/09 16:29:16 tgl Exp $ * *------------------------------------------------------------------------- *//* * NOTES * Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer"). * When a PQexec() routine is run, the resulting tuples * find their way into a "PortalEntry". The contents of the resulting * "PortalEntry" can then be inspected by other PQxxx functions. * * A "Portal" is a structure used to keep track of queries of the * form: * retrieve portal FOO ( blah... ) where blah... * * When the backend sees a "retrieve portal" query, it allocates * a "PortalD" structure, plans the query and then stores the query * in the portal without executing it. Later, when the backend * sees a * fetch 1 into FOO * * the system looks up the portal named "FOO" in the portal table, * gets the planned query and then calls the executor with a feature of * '(EXEC_FOR 1). The executor then runs the query and returns a single * tuple. The problem is that we have to hold onto the state of the * portal query until we see a "close p". This means we have to be * careful about memory management. * * Having said all that, here is what a PortalD currently looks like: * * struct PortalD { * char* name; * classObj(PortalVariableMemory) variable; * classObj(PortalHeapMemory) heap; * List queryDesc; * EState state; * void (*cleanup) ARGS((Portal portal)); * }; * * I hope this makes things clearer to whoever reads this -cim 2/22/91 * * Here is an old comment taken from nodes/memnodes.h * * MemoryContext * A logical context in which memory allocations occur. * * The types of memory contexts can be thought of as members of the * following inheritance hierarchy with properties summarized below. * * Node * | * MemoryContext___ * / \ * GlobalMemory PortalMemoryContext * / \ * PortalVariableMemory PortalHeapMemory * * Flushed at Flushed at Checkpoints * Transaction Portal * Commit Close * * GlobalMemory n n n * PortalVariableMemory n y n * PortalHeapMemory y y y * * */#include "postgres.h"#include "lib/hasht.h"#include "utils/module.h"#include "utils/portal.h"static void CollectNamedPortals(Portal *portalP, int destroy);static Portal PortalHeapMemoryGetPortal(PortalHeapMemory context);static PortalVariableMemory PortalHeapMemoryGetVariableMemory(PortalHeapMemory context);static Portal PortalVariableMemoryGetPortal(PortalVariableMemory context);/* ---------------- * ALLOCFREE_ERROR_ABORT * define this if you want a core dump when you try to * free memory already freed -cim 2/9/91 * ---------------- */#undef ALLOCFREE_ERROR_ABORT/* ---------------- * Global state * ---------------- */static int PortalManagerEnableCount = 0;#define MAX_PORTALNAME_LEN 64 /* XXX LONGALIGNable value */typedef struct portalhashent{ char portalname[MAX_PORTALNAME_LEN]; Portal portal;} PortalHashEnt;#define PortalManagerEnabled (PortalManagerEnableCount >= 1)static HTAB *PortalHashTable = NULL;#define PortalHashTableLookup(NAME, PORTAL) \do { \ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ \ MemSet(key, 0, MAX_PORTALNAME_LEN); \ snprintf(key, MAX_PORTALNAME_LEN - 1, "%s", NAME); \ hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ key, HASH_FIND, &found); \ if (hentry == NULL) \ elog(FATAL, "error in PortalHashTable"); \ if (found) \ PORTAL = hentry->portal; \ else \ PORTAL = NULL; \} while(0)#define PortalHashTableInsert(PORTAL) \do { \ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ \ MemSet(key, 0, MAX_PORTALNAME_LEN); \ snprintf(key, MAX_PORTALNAME_LEN - 1, "%s", PORTAL->name); \ hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ key, HASH_ENTER, &found); \ if (hentry == NULL) \ elog(FATAL, "error in PortalHashTable"); \ if (found) \ elog(NOTICE, "trying to insert a portal name that exists."); \ hentry->portal = PORTAL; \} while(0)#define PortalHashTableDelete(PORTAL) \{ \ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \ \ MemSet(key, 0, MAX_PORTALNAME_LEN); \ snprintf(key, MAX_PORTALNAME_LEN - 1, "%s", PORTAL->name); \ hentry = (PortalHashEnt*)hash_search(PortalHashTable, \ key, HASH_REMOVE, &found); \ if (hentry == NULL) \ elog(FATAL, "error in PortalHashTable"); \ if (!found) \ elog(NOTICE, "trying to delete portal name that does not exist."); \} while(0)static GlobalMemory PortalMemory = NULL;static char PortalMemoryName[] = "Portal";static Portal BlankPortal = NULL;/* ---------------- * Internal class definitions * ---------------- */typedef struct HeapMemoryBlockData{ AllocSetData setData; FixedItemData itemData;} HeapMemoryBlockData;typedef HeapMemoryBlockData *HeapMemoryBlock;#define HEAPMEMBLOCK(context) \ ((HeapMemoryBlock)(context)->block)/* ---------------------------------------------------------------- * Variable and heap memory methods * ---------------------------------------------------------------- *//* ---------------- * PortalVariableMemoryAlloc * ---------------- */static PointerPortalVariableMemoryAlloc(PortalVariableMemory this, Size size){ return AllocSetAlloc(&this->setData, size);}/* ---------------- * PortalVariableMemoryFree * ---------------- */static voidPortalVariableMemoryFree(PortalVariableMemory this, Pointer pointer){ AllocSetFree(&this->setData, pointer);}/* ---------------- * PortalVariableMemoryRealloc * ---------------- */static PointerPortalVariableMemoryRealloc(PortalVariableMemory this, Pointer pointer, Size size){ return AllocSetRealloc(&this->setData, pointer, size);}/* ---------------- * PortalVariableMemoryGetName * ---------------- */static char *PortalVariableMemoryGetName(PortalVariableMemory this){ return vararg_format("%s-var", PortalVariableMemoryGetPortal(this)->name);}/* ---------------- * PortalVariableMemoryDump * ---------------- */static voidPortalVariableMemoryDump(PortalVariableMemory this){ printf("--\n%s:\n", PortalVariableMemoryGetName(this)); AllocSetDump(&this->setData); /* XXX is this the right interface */}/* ---------------- * PortalHeapMemoryAlloc * ---------------- */static PointerPortalHeapMemoryAlloc(PortalHeapMemory this, Size size){ HeapMemoryBlock block = HEAPMEMBLOCK(this); AssertState(PointerIsValid(block)); return AllocSetAlloc(&block->setData, size);}/* ---------------- * PortalHeapMemoryFree * ---------------- */static voidPortalHeapMemoryFree(PortalHeapMemory this, Pointer pointer){ HeapMemoryBlock block = HEAPMEMBLOCK(this); AssertState(PointerIsValid(block)); if (AllocSetContains(&block->setData, pointer)) AllocSetFree(&block->setData, pointer); else { elog(NOTICE, "PortalHeapMemoryFree: 0x%x not in alloc set!", pointer);#ifdef ALLOCFREE_ERROR_ABORT Assert(AllocSetContains(&block->setData, pointer));#endif /* ALLOCFREE_ERROR_ABORT */ }}/* ---------------- * PortalHeapMemoryRealloc * ---------------- */static PointerPortalHeapMemoryRealloc(PortalHeapMemory this, Pointer pointer, Size size){ HeapMemoryBlock block = HEAPMEMBLOCK(this); AssertState(PointerIsValid(block)); return AllocSetRealloc(&block->setData, pointer, size);}/* ---------------- * PortalHeapMemoryGetName * ---------------- */static char *PortalHeapMemoryGetName(PortalHeapMemory this){ return vararg_format("%s-heap", PortalHeapMemoryGetPortal(this)->name);}/* ---------------- * PortalHeapMemoryDump * ---------------- */static voidPortalHeapMemoryDump(PortalHeapMemory this){ HeapMemoryBlock block; printf("--\n%s:\n", PortalHeapMemoryGetName(this)); /* XXX is this the right interface */ if (PointerIsValid(this->block)) AllocSetDump(&HEAPMEMBLOCK(this)->setData); /* dump the stack too */ for (block = (HeapMemoryBlock) FixedStackGetTop(&this->stackData); PointerIsValid(block); block = (HeapMemoryBlock) FixedStackGetNext(&this->stackData, (Pointer) block)) { printf("--\n"); AllocSetDump(&block->setData); }}/* ---------------------------------------------------------------- * variable / heap context method tables * ---------------------------------------------------------------- */static struct MemoryContextMethodsData PortalVariableContextMethodsData = { PortalVariableMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ PortalVariableMemoryFree, /* void (*)(this, Pointer) pfree */ PortalVariableMemoryRealloc,/* Pointer (*)(this, Pointer) repalloc */ PortalVariableMemoryGetName,/* char* (*)(this) getName */ PortalVariableMemoryDump /* void (*)(this) dump */};static struct MemoryContextMethodsData PortalHeapContextMethodsData = { PortalHeapMemoryAlloc, /* Pointer (*)(this, uint32) palloc */ PortalHeapMemoryFree, /* void (*)(this, Pointer) pfree */ PortalHeapMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */ PortalHeapMemoryGetName, /* char* (*)(this) getName */ PortalHeapMemoryDump /* void (*)(this) dump */};/* ---------------------------------------------------------------- * private internal support routines * ---------------------------------------------------------------- *//* ---------------- * CreateNewBlankPortal * ---------------- */static voidCreateNewBlankPortal(){ Portal portal; AssertState(!PortalIsValid(BlankPortal)); /* * make new portal structure */ portal = (Portal) MemoryContextAlloc((MemoryContext) PortalMemory, sizeof *portal); /* * initialize portal variable context */ NodeSetTag((Node *) &portal->variable, T_PortalVariableMemory); AllocSetInit(&portal->variable.setData, DynamicAllocMode, (Size) 0); portal->variable.method = &PortalVariableContextMethodsData; /* * initialize portal heap context */ NodeSetTag((Node *) &portal->heap, T_PortalHeapMemory); portal->heap.block = NULL; FixedStackInit(&portal->heap.stackData, offsetof(HeapMemoryBlockData, itemData)); portal->heap.method = &PortalHeapContextMethodsData; /* * set bogus portal name */ portal->name = "** Blank Portal **"; /* initialize portal query */ portal->queryDesc = NULL; portal->attinfo = NULL; portal->state = NULL; portal->cleanup = NULL; /* * install blank portal */ BlankPortal = portal;}boolPortalNameIsSpecial(char *pname){ if (strcmp(pname, VACPNAME) == 0) return true; return false;}/* * This routine is used to collect all portals created in this xaction * and then destroy them. There is a little trickiness required as a * result of the dynamic hashing interface to getting every hash entry * sequentially. Its use of static variables requires that we get every * entry *before* we destroy anything (destroying updates the hashtable * and screws up the sequential walk of the table). -mer 17 Aug 1992 */static voidCollectNamedPortals(Portal *portalP, int destroy){ static Portal *portalList = (Portal *) NULL; static int listIndex = 0; static int maxIndex = 9; if (portalList == (Portal *) NULL) portalList = (Portal *) malloc(10 * sizeof(Portal)); if (destroy != 0) { int i; for (i = 0; i < listIndex; i++) PortalDestroy(&portalList[i]); listIndex = 0; } else { Assert(portalP); Assert(*portalP); /* * Don't delete special portals, up to portal creator to do this */ if (PortalNameIsSpecial((*portalP)->name)) return; portalList[listIndex] = *portalP; listIndex++; if (listIndex == maxIndex) { portalList = (Portal *) realloc(portalList, (maxIndex + 11) * sizeof(Portal)); maxIndex += 10; } } return;}voidAtEOXact_portals(){ HashTableWalk(PortalHashTable, CollectNamedPortals, 0); CollectNamedPortals(NULL, 1);}/* ---------------- * PortalDump * ---------------- */#ifdef NOT_USEDstatic voidPortalDump(Portal *thisP){ /* XXX state/argument checking here */ PortalVariableMemoryDump(PortalGetVariableMemory(*thisP)); PortalHeapMemoryDump(PortalGetHeapMemory(*thisP));}#endif/* ---------------- * DumpPortals * ---------------- */#ifdef NOT_USEDstatic voidDumpPortals(){ /* XXX state checking here */ HashTableWalk(PortalHashTable, PortalDump, 0);}#endif/* ---------------------------------------------------------------- * public portal interface functions * ---------------------------------------------------------------- *//* * EnablePortalManager * Enables/disables the portal management module. */voidEnablePortalManager(bool on)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -