mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
15
src/backend/utils/mmgr/Makefile.inc
Normal file
15
src/backend/utils/mmgr/Makefile.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile.inc--
|
||||
# Makefile for utils/mmgr
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
SUBSRCS+= aset.c mcxt.c palloc.c portalmem.c oset.c
|
||||
|
||||
381
src/backend/utils/mmgr/aset.c
Normal file
381
src/backend/utils/mmgr/aset.c
Normal file
@@ -0,0 +1,381 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* aset.c--
|
||||
* Allocation set definitions.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
|
||||
*
|
||||
* NOTE
|
||||
* XXX This is a preliminary implementation which lacks fail-fast
|
||||
* XXX validity checking of arguments.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "c.h"
|
||||
#include "utils/excid.h" /* for ExhaustedMemory */
|
||||
#include "utils/memutils.h" /* where funnction declarations go */
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
|
||||
#undef AllocSetReset
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
/*
|
||||
* Internal type definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* AllocElem --
|
||||
* Allocation element.
|
||||
*/
|
||||
typedef struct AllocElemData {
|
||||
OrderedElemData elemData; /* elem in AllocSet */
|
||||
Size size;
|
||||
} AllocElemData;
|
||||
|
||||
typedef AllocElemData *AllocElem;
|
||||
|
||||
|
||||
/*
|
||||
* Private method definitions
|
||||
*/
|
||||
|
||||
/*
|
||||
* AllocPointerGetAllocElem --
|
||||
* Returns allocation (internal) elem given (external) pointer.
|
||||
*/
|
||||
#define AllocPointerGetAllocElem(pointer) (&((AllocElem)(pointer))[-1])
|
||||
|
||||
/*
|
||||
* AllocElemGetAllocPointer --
|
||||
* Returns allocation (external) pointer given (internal) elem.
|
||||
*/
|
||||
#define AllocElemGetAllocPointer(alloc) ((AllocPointer)&(alloc)[1])
|
||||
|
||||
/*
|
||||
* AllocElemIsValid --
|
||||
* True iff alloc is valid.
|
||||
*/
|
||||
#define AllocElemIsValid(alloc) PointerIsValid(alloc)
|
||||
|
||||
/* non-export function prototypes */
|
||||
static AllocPointer AllocSetGetFirst(AllocSet set);
|
||||
static AllocPointer AllocPointerGetNext(AllocPointer pointer);
|
||||
|
||||
/*
|
||||
* Public routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* AllocPointerIsValid(pointer)
|
||||
* AllocSetIsValid(set)
|
||||
*
|
||||
* .. are now macros in aset.h -cim 4/27/91
|
||||
*/
|
||||
|
||||
/*
|
||||
* AllocSetInit --
|
||||
* Initializes given allocation set.
|
||||
*
|
||||
* Note:
|
||||
* The semantics of the mode are explained above. Limit is ignored
|
||||
* for dynamic and static modes.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid pointer.
|
||||
* BadArg if mode is invalid.
|
||||
*/
|
||||
void
|
||||
AllocSetInit(AllocSet set, AllocMode mode, Size limit)
|
||||
{
|
||||
AssertArg(PointerIsValid(set));
|
||||
AssertArg((int)DynamicAllocMode <= (int)mode);
|
||||
AssertArg((int)mode <= (int)BoundedAllocMode);
|
||||
|
||||
/*
|
||||
* XXX mode is currently ignored and treated as DynamicAllocMode.
|
||||
* XXX limit is also ignored. This affects this whole file.
|
||||
*/
|
||||
|
||||
OrderedSetInit(&set->setData, offsetof(AllocElemData, elemData));
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetReset --
|
||||
* Frees memory which is allocated in the given set.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
*/
|
||||
void
|
||||
AllocSetReset(AllocSet set)
|
||||
{
|
||||
AllocPointer pointer;
|
||||
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
|
||||
while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) {
|
||||
AllocSetFree(set, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AllocSetReset_debug(char *file, int line, AllocSet set)
|
||||
{
|
||||
AllocPointer pointer;
|
||||
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
|
||||
while (AllocPointerIsValid(pointer = AllocSetGetFirst(set))) {
|
||||
AllocSetFree(set, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetContains --
|
||||
* True iff allocation set contains given allocation element.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
*/
|
||||
bool
|
||||
AllocSetContains(AllocSet set, AllocPointer pointer)
|
||||
{
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
AssertArg(AllocPointerIsValid(pointer));
|
||||
|
||||
return (OrderedSetContains(&set->setData,
|
||||
&AllocPointerGetAllocElem(pointer)->elemData));
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetAlloc --
|
||||
* Returns pointer to allocated memory of given size; memory is added
|
||||
* to the set.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
* MemoryExhausted if allocation fails.
|
||||
*/
|
||||
AllocPointer
|
||||
AllocSetAlloc(AllocSet set, Size size)
|
||||
{
|
||||
AllocElem alloc;
|
||||
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
|
||||
/* allocate */
|
||||
alloc = (AllocElem)malloc(sizeof (*alloc) + size);
|
||||
|
||||
if (!PointerIsValid(alloc)) {
|
||||
elog (FATAL, "palloc failure: memory exhausted");
|
||||
}
|
||||
|
||||
/* add to allocation list */
|
||||
OrderedElemPushInto(&alloc->elemData, &set->setData);
|
||||
|
||||
/* set size */
|
||||
alloc->size = size;
|
||||
|
||||
return (AllocElemGetAllocPointer(alloc));
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetFree --
|
||||
* Frees allocated memory; memory is removed from the set.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
* BadArg if pointer is not member of set.
|
||||
*/
|
||||
void
|
||||
AllocSetFree(AllocSet set, AllocPointer pointer)
|
||||
{
|
||||
AllocElem alloc;
|
||||
|
||||
/* AssertArg(AllocSetIsValid(set)); */
|
||||
/* AssertArg(AllocPointerIsValid(pointer)); */
|
||||
AssertArg(AllocSetContains(set, pointer));
|
||||
|
||||
alloc = AllocPointerGetAllocElem(pointer);
|
||||
|
||||
/* remove from allocation set */
|
||||
OrderedElemPop(&alloc->elemData);
|
||||
|
||||
/* free storage */
|
||||
free(alloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetRealloc --
|
||||
* Returns new pointer to allocated memory of given size; this memory
|
||||
* is added to the set. Memory associated with given pointer is copied
|
||||
* into the new memory, and the old memory is freed.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
* BadArg if pointer is invalid.
|
||||
* BadArg if pointer is not member of set.
|
||||
* MemoryExhausted if allocation fails.
|
||||
*/
|
||||
AllocPointer
|
||||
AllocSetRealloc(AllocSet set, AllocPointer pointer, Size size)
|
||||
{
|
||||
AllocPointer newPointer;
|
||||
AllocElem alloc;
|
||||
|
||||
/* AssertArg(AllocSetIsValid(set)); */
|
||||
/* AssertArg(AllocPointerIsValid(pointer)); */
|
||||
AssertArg(AllocSetContains(set, pointer));
|
||||
|
||||
/*
|
||||
* Calling realloc(3) directly is not be possible (unless we use
|
||||
* our own hacked version of malloc) since we must keep the
|
||||
* allocations in the allocation set.
|
||||
*/
|
||||
|
||||
alloc = AllocPointerGetAllocElem(pointer);
|
||||
|
||||
/* allocate new pointer */
|
||||
newPointer = AllocSetAlloc(set, size);
|
||||
|
||||
/* fill new memory */
|
||||
memmove(newPointer, pointer, (alloc->size < size) ? alloc->size : size);
|
||||
|
||||
/* free old pointer */
|
||||
AllocSetFree(set, pointer);
|
||||
|
||||
return (newPointer);
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetIterate --
|
||||
* Returns size of set. Iterates through set elements calling function
|
||||
* (if valid) on each.
|
||||
*
|
||||
* Note:
|
||||
* This was written as an aid to debugging. It is intended for
|
||||
* debugging use only.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if set is invalid.
|
||||
*/
|
||||
int
|
||||
AllocSetIterate(AllocSet set,
|
||||
void (*function)(AllocPointer pointer))
|
||||
{
|
||||
int count = 0;
|
||||
AllocPointer pointer;
|
||||
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
|
||||
for (pointer = AllocSetGetFirst(set);
|
||||
AllocPointerIsValid(pointer);
|
||||
pointer = AllocPointerGetNext(pointer)) {
|
||||
|
||||
if (PointerIsValid(function)) {
|
||||
(*function)(pointer);
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
int
|
||||
AllocSetCount(AllocSet set)
|
||||
{
|
||||
int count = 0;
|
||||
AllocPointer pointer;
|
||||
|
||||
AssertArg(AllocSetIsValid(set));
|
||||
|
||||
for (pointer = AllocSetGetFirst(set);
|
||||
AllocPointerIsValid(pointer);
|
||||
pointer = AllocPointerGetNext(pointer)) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* AllocSetGetFirst --
|
||||
* Returns "first" allocation pointer in a set.
|
||||
*
|
||||
* Note:
|
||||
* Assumes set is valid.
|
||||
*/
|
||||
static AllocPointer
|
||||
AllocSetGetFirst(AllocSet set)
|
||||
{
|
||||
AllocElem alloc;
|
||||
|
||||
alloc = (AllocElem)OrderedSetGetHead(&set->setData);
|
||||
|
||||
if (!AllocElemIsValid(alloc)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (AllocElemGetAllocPointer(alloc));
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocPointerGetNext --
|
||||
* Returns "successor" allocation pointer.
|
||||
*
|
||||
* Note:
|
||||
* Assumes pointer is valid.
|
||||
*/
|
||||
static AllocPointer
|
||||
AllocPointerGetNext(AllocPointer pointer)
|
||||
{
|
||||
AllocElem alloc;
|
||||
|
||||
alloc = (AllocElem)
|
||||
OrderedElemGetSuccessor(&AllocPointerGetAllocElem(pointer)->elemData);
|
||||
|
||||
if (!AllocElemIsValid(alloc)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (AllocElemGetAllocPointer(alloc));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Debugging routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX AllocPointerDump --
|
||||
* Displays allocated pointer.
|
||||
*/
|
||||
void
|
||||
AllocPointerDump(AllocPointer pointer)
|
||||
{
|
||||
printf("\t%-10d@ %0#x\n", ((long*)pointer)[-1], pointer); /* XXX */
|
||||
}
|
||||
|
||||
/*
|
||||
* AllocSetDump --
|
||||
* Displays allocated set.
|
||||
*/
|
||||
void
|
||||
AllocSetDump(AllocSet set)
|
||||
{
|
||||
int count;
|
||||
count = AllocSetIterate(set, AllocPointerDump);
|
||||
printf("\ttotal %d allocations\n", count);
|
||||
}
|
||||
510
src/backend/utils/mmgr/mcxt.c
Normal file
510
src/backend/utils/mmgr/mcxt.c
Normal file
@@ -0,0 +1,510 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* mcxt.c--
|
||||
* POSTGRES memory context code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h> /* XXX for printf debugging */
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/module.h"
|
||||
#include "utils/excid.h"
|
||||
|
||||
#include "nodes/memnodes.h"
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
#include "utils/mcxt.h"
|
||||
#include "utils/elog.h"
|
||||
|
||||
#include "utils/palloc.h"
|
||||
|
||||
#undef MemoryContextAlloc
|
||||
#undef MemoryContextFree
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
/*
|
||||
* Global State
|
||||
*/
|
||||
static int MemoryContextEnableCount = 0;
|
||||
#define MemoryContextEnabled (MemoryContextEnableCount > 0)
|
||||
|
||||
static OrderedSetData ActiveGlobalMemorySetData; /* uninitialized */
|
||||
#define ActiveGlobalMemorySet (&ActiveGlobalMemorySetData)
|
||||
|
||||
/*
|
||||
* description of allocated memory representation goes here
|
||||
*/
|
||||
|
||||
#define PSIZE(PTR) (*((int32 *)(PTR) - 1))
|
||||
#define PSIZEALL(PTR) (*((int32 *)(PTR) - 1) + sizeof (int32))
|
||||
#define PSIZESKIP(PTR) ((char *)((int32 *)(PTR) + 1))
|
||||
#define PSIZEFIND(PTR) ((char *)((int32 *)(PTR) - 1))
|
||||
#define PSIZESPACE(LEN) ((LEN) + sizeof (int32))
|
||||
|
||||
/*
|
||||
* AllocSizeIsValid --
|
||||
* True iff 0 < size and size <= MaxAllocSize.
|
||||
*/
|
||||
#define AllocSizeIsValid(size) (0 < (size) && (size) <= MaxAllocSize)
|
||||
|
||||
/*****************************************************************************
|
||||
* GLOBAL MEMORY *
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* CurrentMemoryContext --
|
||||
* Memory context for general global allocations.
|
||||
*/
|
||||
MemoryContext CurrentMemoryContext = NULL;
|
||||
|
||||
/*****************************************************************************
|
||||
* PRIVATE DEFINITIONS *
|
||||
*****************************************************************************/
|
||||
|
||||
static Pointer GlobalMemoryAlloc(GlobalMemory this, Size size);
|
||||
static void GlobalMemoryFree(GlobalMemory this, Pointer pointer);
|
||||
static Pointer GlobalMemoryRealloc(GlobalMemory this, Pointer pointer,
|
||||
Size size);
|
||||
static char *GlobalMemoryGetName(GlobalMemory this);
|
||||
static void GlobalMemoryDump(GlobalMemory this);
|
||||
static void DumpGlobalMemories(void);
|
||||
|
||||
|
||||
/*
|
||||
* Global Memory Methods
|
||||
*/
|
||||
|
||||
static struct MemoryContextMethodsData GlobalContextMethodsData = {
|
||||
GlobalMemoryAlloc, /* Pointer (*)(this, uint32) palloc */
|
||||
GlobalMemoryFree, /* void (*)(this, Pointer) pfree */
|
||||
GlobalMemoryRealloc, /* Pointer (*)(this, Pointer) repalloc */
|
||||
GlobalMemoryGetName, /* char* (*)(this) getName */
|
||||
GlobalMemoryDump /* void (*)(this) dump */
|
||||
};
|
||||
|
||||
/*
|
||||
* Note:
|
||||
* TopGlobalMemory is handled specially because of bootstrapping.
|
||||
*/
|
||||
/* extern bool EqualGlobalMemory(); */
|
||||
|
||||
static struct GlobalMemory TopGlobalMemoryData = {
|
||||
T_GlobalMemory, /* NodeTag tag */
|
||||
&GlobalContextMethodsData, /* ContextMethods method */
|
||||
{ { 0 } }, /* uninitialized
|
||||
* OrderedSetData allocSetD
|
||||
*/
|
||||
"TopGlobal", /* char* name */
|
||||
{ 0 } /* uninitialized OrderedElemData elemD */
|
||||
};
|
||||
|
||||
/*
|
||||
* TopMemoryContext --
|
||||
* Memory context for general global allocations.
|
||||
*
|
||||
* Note:
|
||||
* Don't use this memory context for random allocations. If you
|
||||
* allocate something here, you are expected to clean it up when
|
||||
* appropriate.
|
||||
*/
|
||||
MemoryContext TopMemoryContext = (MemoryContext)&TopGlobalMemoryData;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Module State
|
||||
*/
|
||||
|
||||
/*
|
||||
* EnableMemoryContext --
|
||||
* Enables/disables memory management and global contexts.
|
||||
*
|
||||
* Note:
|
||||
* This must be called before creating contexts or allocating memory.
|
||||
* This must be called before other contexts are created.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArg if on is invalid.
|
||||
* BadState if on is false when disabled.
|
||||
*/
|
||||
void
|
||||
EnableMemoryContext(bool on)
|
||||
{
|
||||
static bool processing = false;
|
||||
|
||||
AssertState(!processing);
|
||||
AssertArg(BoolIsValid(on));
|
||||
|
||||
if (BypassEnable(&MemoryContextEnableCount, on)) {
|
||||
return;
|
||||
}
|
||||
|
||||
processing = true;
|
||||
|
||||
if (on) { /* initialize */
|
||||
/* initialize TopGlobalMemoryData.setData */
|
||||
AllocSetInit(&TopGlobalMemoryData.setData, DynamicAllocMode,
|
||||
(Size)0);
|
||||
|
||||
/* make TopGlobalMemoryData member of ActiveGlobalMemorySet */
|
||||
OrderedSetInit(ActiveGlobalMemorySet,
|
||||
offsetof(struct GlobalMemory, elemData));
|
||||
OrderedElemPushInto(&TopGlobalMemoryData.elemData,
|
||||
ActiveGlobalMemorySet);
|
||||
|
||||
/* initialize CurrentMemoryContext */
|
||||
CurrentMemoryContext = TopMemoryContext;
|
||||
|
||||
} else { /* cleanup */
|
||||
GlobalMemory context;
|
||||
|
||||
/* walk the list of allocations */
|
||||
while (PointerIsValid(context = (GlobalMemory)
|
||||
OrderedSetGetHead(ActiveGlobalMemorySet))) {
|
||||
|
||||
if (context == &TopGlobalMemoryData) {
|
||||
/* don't free it and clean it last */
|
||||
OrderedElemPop(&TopGlobalMemoryData.elemData);
|
||||
} else {
|
||||
GlobalMemoryDestroy(context);
|
||||
}
|
||||
/* what is needed for the top? */
|
||||
}
|
||||
|
||||
/*
|
||||
* Freeing memory here should be safe as this is called
|
||||
* only after all modules which allocate in TopMemoryContext
|
||||
* have been disabled.
|
||||
*/
|
||||
|
||||
/* step through remaining allocations and log */
|
||||
/* AllocSetStep(...); */
|
||||
|
||||
/* deallocate whatever is left */
|
||||
AllocSetReset(&TopGlobalMemoryData.setData);
|
||||
}
|
||||
|
||||
processing = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* MemoryContextAlloc --
|
||||
* Returns pointer to aligned allocated memory in the given context.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called before InitMemoryManager.
|
||||
* BadArg if context is invalid or if size is 0.
|
||||
* BadAllocSize if size is larger than MaxAllocSize.
|
||||
*/
|
||||
Pointer
|
||||
MemoryContextAlloc(MemoryContext context, Size size)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(MemoryContextIsValid(context));
|
||||
|
||||
LogTrap(!AllocSizeIsValid(size), BadAllocSize,
|
||||
("size=%d [0x%x]", size, size));
|
||||
|
||||
return (context->method->alloc(context, size));
|
||||
}
|
||||
|
||||
/*
|
||||
* MemoryContextFree --
|
||||
* Frees allocated memory referenced by pointer in the given context.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
* BadArgumentsErr if firstTime is true for subsequent calls.
|
||||
*/
|
||||
void
|
||||
MemoryContextFree(MemoryContext context, Pointer pointer)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(MemoryContextIsValid(context));
|
||||
AssertArg(PointerIsValid(pointer));
|
||||
|
||||
context->method->free_p(context, pointer);
|
||||
}
|
||||
|
||||
/*
|
||||
* MemoryContextRelloc --
|
||||
* Returns pointer to aligned allocated memory in the given context.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
* BadArgumentsErr if firstTime is true for subsequent calls.
|
||||
*/
|
||||
Pointer
|
||||
MemoryContextRealloc(MemoryContext context,
|
||||
Pointer pointer,
|
||||
Size size)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(MemoryContextIsValid(context));
|
||||
AssertArg(PointerIsValid(pointer));
|
||||
|
||||
LogTrap(!AllocSizeIsValid(size), BadAllocSize,
|
||||
("size=%d [0x%x]", size, size));
|
||||
|
||||
return (context->method->realloc(context, pointer, size));
|
||||
}
|
||||
|
||||
/*
|
||||
* MemoryContextGetName --
|
||||
* Returns pointer to aligned allocated memory in the given context.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
* BadArgumentsErr if firstTime is true for subsequent calls.
|
||||
*/
|
||||
char*
|
||||
MemoryContextGetName(MemoryContext context)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(MemoryContextIsValid(context));
|
||||
|
||||
return (context->method->getName(context));
|
||||
}
|
||||
|
||||
/*
|
||||
* PointerGetAllocSize --
|
||||
* Returns size of aligned allocated memory given pointer to it.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
* BadArgumentsErr if firstTime is true for subsequent calls.
|
||||
*/
|
||||
Size
|
||||
PointerGetAllocSize(Pointer pointer)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(PointerIsValid(pointer));
|
||||
|
||||
return (PSIZE(pointer));
|
||||
}
|
||||
|
||||
/*
|
||||
* MemoryContextSwitchTo --
|
||||
* Returns the current context; installs the given context.
|
||||
*
|
||||
* Note:
|
||||
* none
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if context is invalid.
|
||||
*/
|
||||
MemoryContext
|
||||
MemoryContextSwitchTo(MemoryContext context)
|
||||
{
|
||||
MemoryContext old;
|
||||
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(MemoryContextIsValid(context));
|
||||
|
||||
old = CurrentMemoryContext;
|
||||
CurrentMemoryContext = context;
|
||||
return (old);
|
||||
}
|
||||
|
||||
/*
|
||||
* External Functions
|
||||
*/
|
||||
/*
|
||||
* CreateGlobalMemory --
|
||||
* Returns new global memory context.
|
||||
*
|
||||
* Note:
|
||||
* Assumes name is static.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called outside TopMemoryContext (TopGlobalMemory).
|
||||
* BadArg if name is invalid.
|
||||
*/
|
||||
GlobalMemory
|
||||
CreateGlobalMemory(char *name) /* XXX MemoryContextName */
|
||||
{
|
||||
GlobalMemory context;
|
||||
MemoryContext savecxt;
|
||||
|
||||
AssertState(MemoryContextEnabled);
|
||||
|
||||
savecxt = MemoryContextSwitchTo(TopMemoryContext);
|
||||
|
||||
context = (GlobalMemory)newNode(sizeof(struct GlobalMemory), T_GlobalMemory);
|
||||
context->method = &GlobalContextMethodsData;
|
||||
context->name = name; /* assumes name is static */
|
||||
AllocSetInit(&context->setData, DynamicAllocMode, (Size)0);
|
||||
|
||||
/* link the context */
|
||||
OrderedElemPushInto(&context->elemData, ActiveGlobalMemorySet);
|
||||
|
||||
MemoryContextSwitchTo(savecxt);
|
||||
return (context);
|
||||
}
|
||||
|
||||
/*
|
||||
* GlobalMemoryDestroy --
|
||||
* Destroys given global memory context.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called outside TopMemoryContext (TopGlobalMemory).
|
||||
* BadArg if context is invalid GlobalMemory.
|
||||
* BadArg if context is TopMemoryContext (TopGlobalMemory).
|
||||
*/
|
||||
void
|
||||
GlobalMemoryDestroy(GlobalMemory context)
|
||||
{
|
||||
AssertState(MemoryContextEnabled);
|
||||
AssertArg(IsA(context,GlobalMemory));
|
||||
AssertArg(context != &TopGlobalMemoryData);
|
||||
|
||||
AllocSetReset(&context->setData);
|
||||
|
||||
/* unlink and delete the context */
|
||||
OrderedElemPop(&context->elemData);
|
||||
MemoryContextFree(TopMemoryContext, (Pointer)context);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* PRIVATE *
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* GlobalMemoryAlloc --
|
||||
* Returns pointer to aligned space in the global context.
|
||||
*
|
||||
* Exceptions:
|
||||
* ExhaustedMemory if allocation fails.
|
||||
*/
|
||||
static Pointer
|
||||
GlobalMemoryAlloc(GlobalMemory this, Size size)
|
||||
{
|
||||
return (AllocSetAlloc(&this->setData, size));
|
||||
}
|
||||
|
||||
/*
|
||||
* GlobalMemoryFree --
|
||||
* Frees allocated memory in the global context.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadContextErr if current context is not the global context.
|
||||
* BadArgumentsErr if pointer is invalid.
|
||||
*/
|
||||
static void
|
||||
GlobalMemoryFree(GlobalMemory this,
|
||||
Pointer pointer)
|
||||
{
|
||||
AllocSetFree(&this->setData, pointer);
|
||||
}
|
||||
|
||||
/*
|
||||
* GlobalMemoryRealloc --
|
||||
* Returns pointer to aligned space in the global context.
|
||||
*
|
||||
* Note:
|
||||
* Memory associated with the pointer is freed before return.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadContextErr if current context is not the global context.
|
||||
* BadArgumentsErr if pointer is invalid.
|
||||
* NoMoreMemoryErr if allocation fails.
|
||||
*/
|
||||
static Pointer
|
||||
GlobalMemoryRealloc(GlobalMemory this,
|
||||
Pointer pointer,
|
||||
Size size)
|
||||
{
|
||||
return (AllocSetRealloc(&this->setData, pointer, size));
|
||||
}
|
||||
|
||||
/*
|
||||
* GlobalMemoryGetName --
|
||||
* Returns name string for context.
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
*/
|
||||
static char*
|
||||
GlobalMemoryGetName(GlobalMemory this)
|
||||
{
|
||||
return (this->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* GlobalMemoryDump --
|
||||
* Dumps global memory context for debugging.
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
*/
|
||||
static void
|
||||
GlobalMemoryDump(GlobalMemory this)
|
||||
{
|
||||
GlobalMemory context;
|
||||
|
||||
printf("--\n%s:\n", GlobalMemoryGetName(this));
|
||||
|
||||
context = (GlobalMemory)OrderedElemGetPredecessor(&this->elemData);
|
||||
if (PointerIsValid(context)) {
|
||||
printf("\tpredecessor=%s\n", GlobalMemoryGetName(context));
|
||||
}
|
||||
|
||||
context = (GlobalMemory)OrderedElemGetSuccessor(&this->elemData);
|
||||
if (PointerIsValid(context)) {
|
||||
printf("\tsucessor=%s\n", GlobalMemoryGetName(context));
|
||||
}
|
||||
|
||||
AllocSetDump(&this->setData); /* XXX is this right interface */
|
||||
}
|
||||
|
||||
/*
|
||||
* DumpGlobalMemories --
|
||||
* Dumps all global memory contexts for debugging.
|
||||
*
|
||||
* Exceptions:
|
||||
* ???
|
||||
*/
|
||||
static void
|
||||
DumpGlobalMemories()
|
||||
{
|
||||
GlobalMemory context;
|
||||
|
||||
context = (GlobalMemory)OrderedSetGetHead(&ActiveGlobalMemorySetData);
|
||||
|
||||
while (PointerIsValid(context)) {
|
||||
GlobalMemoryDump(context);
|
||||
|
||||
context = (GlobalMemory)OrderedElemGetSuccessor(
|
||||
&context->elemData);
|
||||
}
|
||||
}
|
||||
|
||||
173
src/backend/utils/mmgr/oset.c
Normal file
173
src/backend/utils/mmgr/oset.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* oset.c--
|
||||
* Fixed format ordered set definitions.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/oset.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
|
||||
*
|
||||
* NOTE
|
||||
* XXX This is a preliminary implementation which lacks fail-fast
|
||||
* XXX validity checking of arguments.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "c.h"
|
||||
|
||||
#include "utils/memutils.h" /* where declarations of this file goes */
|
||||
|
||||
static Pointer OrderedElemGetBase(OrderedElem elem);
|
||||
static void OrderedElemInit(OrderedElem elem, OrderedSet set);
|
||||
static void OrderedElemPush(OrderedElem elem);
|
||||
static void OrderedElemPushHead(OrderedElem elem);
|
||||
|
||||
/*
|
||||
* OrderedElemGetBase --
|
||||
* Returns base of enclosing structure.
|
||||
*/
|
||||
static Pointer
|
||||
OrderedElemGetBase(OrderedElem elem)
|
||||
{
|
||||
if (elem == (OrderedElem) NULL)
|
||||
return (Pointer) NULL;
|
||||
|
||||
return ((Pointer)((char*)(elem) - (elem)->set->offset));
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedSetInit --
|
||||
*/
|
||||
void
|
||||
OrderedSetInit(OrderedSet set, Offset offset)
|
||||
{
|
||||
set->head = (OrderedElem)&set->dummy;
|
||||
set->dummy = NULL;
|
||||
set->tail = (OrderedElem)&set->head;
|
||||
set->offset = offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemInit --
|
||||
*/
|
||||
static void
|
||||
OrderedElemInit(OrderedElem elem, OrderedSet set)
|
||||
{
|
||||
elem->set = set;
|
||||
/* mark as unattached */
|
||||
elem->next = NULL;
|
||||
elem->prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedSetContains --
|
||||
* True iff ordered set contains given element.
|
||||
*/
|
||||
bool
|
||||
OrderedSetContains(OrderedSet set, OrderedElem elem)
|
||||
{
|
||||
return ((bool)(elem->set == set && (elem->next || elem->prev)));
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedSetGetHead --
|
||||
*/
|
||||
Pointer
|
||||
OrderedSetGetHead(OrderedSet set)
|
||||
{
|
||||
register OrderedElem elem;
|
||||
|
||||
elem = set->head;
|
||||
if (elem->next) {
|
||||
return (OrderedElemGetBase(elem));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedSetGetTail --
|
||||
*/
|
||||
Pointer
|
||||
OrderedSetGetTail(OrderedSet set)
|
||||
{
|
||||
register OrderedElem elem;
|
||||
|
||||
elem = set->tail;
|
||||
if (elem->prev) {
|
||||
return (OrderedElemGetBase(elem));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemGetPredecessor --
|
||||
*/
|
||||
Pointer
|
||||
OrderedElemGetPredecessor(OrderedElem elem)
|
||||
{
|
||||
elem = elem->prev;
|
||||
if (elem->prev) {
|
||||
return (OrderedElemGetBase(elem));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemGetSuccessor --
|
||||
*/
|
||||
Pointer
|
||||
OrderedElemGetSuccessor(OrderedElem elem)
|
||||
{
|
||||
elem = elem->next;
|
||||
if (elem->next) {
|
||||
return (OrderedElemGetBase(elem));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemPop --
|
||||
*/
|
||||
void
|
||||
OrderedElemPop(OrderedElem elem)
|
||||
{
|
||||
elem->next->prev = elem->prev;
|
||||
elem->prev->next = elem->next;
|
||||
/* assignments used only for error detection */
|
||||
elem->next = NULL;
|
||||
elem->prev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemPushInto --
|
||||
*/
|
||||
void
|
||||
OrderedElemPushInto(OrderedElem elem, OrderedSet set)
|
||||
{
|
||||
OrderedElemInit(elem, set);
|
||||
OrderedElemPush(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemPush --
|
||||
*/
|
||||
static void
|
||||
OrderedElemPush(OrderedElem elem)
|
||||
{
|
||||
OrderedElemPushHead(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* OrderedElemPushHead --
|
||||
*/
|
||||
static void
|
||||
OrderedElemPushHead(OrderedElem elem)
|
||||
{
|
||||
elem->next = elem->set->head;
|
||||
elem->prev = (OrderedElem)&elem->set->head;
|
||||
elem->next->prev = elem;
|
||||
elem->prev->next = elem;
|
||||
}
|
||||
|
||||
117
src/backend/utils/mmgr/palloc.c
Normal file
117
src/backend/utils/mmgr/palloc.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* palloc.c--
|
||||
* POSTGRES memory allocator code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/Attic/palloc.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "c.h"
|
||||
|
||||
#include "utils/mcxt.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
|
||||
#include "nodes/memnodes.h"
|
||||
|
||||
#include "utils/palloc.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* User library functions
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#undef palloc
|
||||
#undef pfree
|
||||
#undef MemoryContextAlloc
|
||||
#undef MemoryContextFree
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
/* define PALLOC_IS_MALLOC if you want palloc to go straight to the
|
||||
raw malloc, without concern for the extra bookkeeping needed to
|
||||
ensure garbage is collected at the end of transactions - jolly 1/12/94 */
|
||||
|
||||
|
||||
/*
|
||||
* palloc --
|
||||
* Returns pointer to aligned memory of specified size.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArgument if size < 1 or size >= MaxAllocSize.
|
||||
* ExhaustedMemory if allocation fails.
|
||||
* NonallocatedPointer if pointer was not returned by palloc or repalloc
|
||||
* or may have been freed already.
|
||||
*
|
||||
* pfree --
|
||||
* Frees memory associated with pointer returned from palloc or repalloc.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArgument if pointer is invalid.
|
||||
* FreeInWrongContext if pointer was allocated in a different "context."
|
||||
* NonallocatedPointer if pointer was not returned by palloc or repalloc
|
||||
* or may have been subsequently freed.
|
||||
*/
|
||||
void*
|
||||
palloc(Size size)
|
||||
{
|
||||
#ifdef PALLOC_IS_MALLOC
|
||||
return malloc(size);
|
||||
#else
|
||||
return (MemoryContextAlloc(CurrentMemoryContext, size));
|
||||
#endif /* PALLOC_IS_MALLOC */
|
||||
}
|
||||
|
||||
void
|
||||
pfree(void *pointer)
|
||||
{
|
||||
#ifdef PALLOC_IS_MALLOC
|
||||
free(pointer);
|
||||
#else
|
||||
MemoryContextFree(CurrentMemoryContext, pointer);
|
||||
#endif /* PALLOC_IS_MALLOC */
|
||||
}
|
||||
|
||||
/*
|
||||
* repalloc --
|
||||
* Returns pointer to aligned memory of specified size.
|
||||
*
|
||||
* Side effects:
|
||||
* The returned memory is first filled with the contents of *pointer
|
||||
* up to the minimum of size and psize(pointer). Pointer is freed.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadArgument if pointer is invalid or size < 1 or size >= MaxAllocSize.
|
||||
* ExhaustedMemory if allocation fails.
|
||||
* NonallocatedPointer if pointer was not returned by palloc or repalloc
|
||||
* or may have been freed already.
|
||||
*/
|
||||
void *
|
||||
repalloc(void *pointer, Size size)
|
||||
{
|
||||
#ifdef PALLOC_IS_MALLOC
|
||||
return realloc(pointer, size);
|
||||
#else
|
||||
return (MemoryContextRealloc(CurrentMemoryContext, pointer, size));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* pstrdup
|
||||
allocates space for and copies a string
|
||||
just like strdup except it uses palloc instead of malloc */
|
||||
char*
|
||||
pstrdup(char* string)
|
||||
{
|
||||
char *nstr;
|
||||
|
||||
nstr = strcpy((char *)palloc(strlen(string)+1), string);
|
||||
return nstr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
980
src/backend/utils/mmgr/portalmem.c
Normal file
980
src/backend/utils/mmgr/portalmem.c
Normal file
@@ -0,0 +1,980 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* portalmem.c--
|
||||
* backend portal memory context management stuff
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.1.1.1 1996/07/09 06:22:09 scrappy 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 <stdio.h> /* for sprintf() */
|
||||
#include <string.h> /* for strlen, strncpy */
|
||||
|
||||
#include "c.h"
|
||||
|
||||
#include "lib/hasht.h"
|
||||
#include "utils/module.h"
|
||||
#include "utils/excid.h" /* for Unimplemented */
|
||||
#include "utils/elog.h"
|
||||
#include "utils/mcxt.h"
|
||||
#include "utils/hsearch.h"
|
||||
|
||||
#include "nodes/memnodes.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/execnodes.h" /* for EState */
|
||||
|
||||
#include "utils/portal.h"
|
||||
|
||||
/* ----------------
|
||||
* 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) \
|
||||
{ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \
|
||||
memset(key, 0, MAX_PORTALNAME_LEN); \
|
||||
sprintf(key, "%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; \
|
||||
}
|
||||
#define PortalHashTableInsert(PORTAL) \
|
||||
{ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \
|
||||
memset(key, 0, MAX_PORTALNAME_LEN); \
|
||||
sprintf(key, "%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; \
|
||||
}
|
||||
#define PortalHashTableDelete(PORTAL) \
|
||||
{ PortalHashEnt *hentry; bool found; char key[MAX_PORTALNAME_LEN]; \
|
||||
memset(key, 0, MAX_PORTALNAME_LEN); \
|
||||
sprintf(key, "%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."); \
|
||||
}
|
||||
|
||||
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 Pointer
|
||||
PortalVariableMemoryAlloc(PortalVariableMemory this,
|
||||
Size size)
|
||||
{
|
||||
return (AllocSetAlloc(&this->setData, size));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalVariableMemoryFree
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
PortalVariableMemoryFree(PortalVariableMemory this,
|
||||
Pointer pointer)
|
||||
{
|
||||
AllocSetFree(&this->setData, pointer);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalVariableMemoryRealloc
|
||||
* ----------------
|
||||
*/
|
||||
static Pointer
|
||||
PortalVariableMemoryRealloc(PortalVariableMemory this,
|
||||
Pointer pointer,
|
||||
Size size)
|
||||
{
|
||||
return (AllocSetRealloc(&this->setData, pointer, size));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalVariableMemoryGetName
|
||||
* ----------------
|
||||
*/
|
||||
static char*
|
||||
PortalVariableMemoryGetName(PortalVariableMemory this)
|
||||
{
|
||||
return (form("%s-var", PortalVariableMemoryGetPortal(this)->name));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalVariableMemoryDump
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
PortalVariableMemoryDump(PortalVariableMemory this)
|
||||
{
|
||||
printf("--\n%s:\n", PortalVariableMemoryGetName(this));
|
||||
|
||||
AllocSetDump(&this->setData); /* XXX is this the right interface */
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalHeapMemoryAlloc
|
||||
* ----------------
|
||||
*/
|
||||
static Pointer
|
||||
PortalHeapMemoryAlloc(PortalHeapMemory this,
|
||||
Size size)
|
||||
{
|
||||
HeapMemoryBlock block = HEAPMEMBLOCK(this);
|
||||
|
||||
AssertState(PointerIsValid(block));
|
||||
|
||||
return (AllocSetAlloc(&block->setData, size));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalHeapMemoryFree
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
PortalHeapMemoryFree(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 Pointer
|
||||
PortalHeapMemoryRealloc(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 (form("%s-heap", PortalHeapMemoryGetPortal(this)->name));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalHeapMemoryDump
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
PortalHeapMemoryDump(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 void
|
||||
CreateNewBlankPortal()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
PortalNameIsSpecial(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
|
||||
*/
|
||||
void
|
||||
CollectNamedPortals(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;
|
||||
}
|
||||
|
||||
void
|
||||
AtEOXact_portals()
|
||||
{
|
||||
HashTableWalk(PortalHashTable, CollectNamedPortals, 0);
|
||||
CollectNamedPortals(NULL, 1);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalDump
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
PortalDump(Portal *thisP)
|
||||
{
|
||||
/* XXX state/argument checking here */
|
||||
|
||||
PortalVariableMemoryDump(PortalGetVariableMemory(*thisP));
|
||||
PortalHeapMemoryDump(PortalGetHeapMemory(*thisP));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* DumpPortals
|
||||
* ----------------
|
||||
*/
|
||||
static void
|
||||
DumpPortals()
|
||||
{
|
||||
/* XXX state checking here */
|
||||
|
||||
HashTableWalk(PortalHashTable, PortalDump, 0);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* public portal interface functions
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* EnablePortalManager --
|
||||
* Enables/disables the portal management module.
|
||||
*/
|
||||
void
|
||||
EnablePortalManager(bool on)
|
||||
{
|
||||
static bool processing = false;
|
||||
HASHCTL ctl;
|
||||
|
||||
AssertState(!processing);
|
||||
AssertArg(BoolIsValid(on));
|
||||
|
||||
if (BypassEnable(&PortalManagerEnableCount, on))
|
||||
return;
|
||||
|
||||
processing = true;
|
||||
|
||||
if (on) { /* initialize */
|
||||
EnableMemoryContext(true);
|
||||
|
||||
PortalMemory = CreateGlobalMemory(PortalMemoryName);
|
||||
|
||||
ctl.keysize = MAX_PORTALNAME_LEN;
|
||||
ctl.datasize = sizeof(Portal);
|
||||
|
||||
/* use PORTALS_PER_USER, defined in utils/portal.h
|
||||
* as a guess of how many hash table entries to create, initially
|
||||
*/
|
||||
PortalHashTable = hash_create(PORTALS_PER_USER * 3, &ctl, HASH_ELEM);
|
||||
|
||||
CreateNewBlankPortal();
|
||||
|
||||
} else { /* cleanup */
|
||||
if (PortalIsValid(BlankPortal)) {
|
||||
PortalDestroy(&BlankPortal);
|
||||
MemoryContextFree((MemoryContext)PortalMemory,
|
||||
(Pointer)BlankPortal);
|
||||
BlankPortal = NULL;
|
||||
}
|
||||
/*
|
||||
* Each portal must free its non-memory resources specially.
|
||||
*/
|
||||
HashTableWalk(PortalHashTable, PortalDestroy, 0);
|
||||
hash_destroy(PortalHashTable);
|
||||
PortalHashTable = NULL;
|
||||
|
||||
GlobalMemoryDestroy(PortalMemory);
|
||||
PortalMemory = NULL;
|
||||
|
||||
EnableMemoryContext(true);
|
||||
}
|
||||
|
||||
processing = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* GetPortalByName --
|
||||
* Returns a portal given a portal name; returns blank portal given
|
||||
* NULL; returns invalid portal if portal not found.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
*/
|
||||
Portal
|
||||
GetPortalByName(char *name)
|
||||
{
|
||||
Portal portal;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
|
||||
if (PointerIsValid(name)) {
|
||||
PortalHashTableLookup(name, portal);
|
||||
}
|
||||
else {
|
||||
if (!PortalIsValid(BlankPortal))
|
||||
CreateNewBlankPortal();
|
||||
portal = BlankPortal;
|
||||
}
|
||||
|
||||
return (portal);
|
||||
}
|
||||
|
||||
/*
|
||||
* BlankPortalAssignName --
|
||||
* Returns former blank portal as portal with given name.
|
||||
*
|
||||
* Side effect:
|
||||
* All references to the former blank portal become incorrect.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called without an intervening call to GetPortalByName(NULL).
|
||||
* BadArg if portal name is invalid.
|
||||
* "WARN" if portal name is in use.
|
||||
*/
|
||||
Portal
|
||||
BlankPortalAssignName(char *name) /* XXX PortalName */
|
||||
{
|
||||
Portal portal;
|
||||
uint16 length;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertState(PortalIsValid(BlankPortal));
|
||||
AssertArg(PointerIsValid(name)); /* XXX PortalName */
|
||||
|
||||
portal = GetPortalByName(name);
|
||||
if (PortalIsValid(portal)) {
|
||||
elog(NOTICE, "BlankPortalAssignName: portal %s already exists", name);
|
||||
return (portal);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove blank portal
|
||||
*/
|
||||
portal = BlankPortal;
|
||||
BlankPortal = NULL;
|
||||
|
||||
/*
|
||||
* initialize portal name
|
||||
*/
|
||||
length = 1 + strlen(name);
|
||||
portal->name = (char*)
|
||||
MemoryContextAlloc((MemoryContext)&portal->variable, length);
|
||||
|
||||
strncpy(portal->name, name, length);
|
||||
|
||||
/*
|
||||
* put portal in table
|
||||
*/
|
||||
PortalHashTableInsert(portal);
|
||||
|
||||
return (portal);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalSetQuery --
|
||||
* Attaches a "query" to portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
* BadArg if queryDesc is "invalid."
|
||||
* BadArg if state is "invalid."
|
||||
*/
|
||||
void
|
||||
PortalSetQuery(Portal portal,
|
||||
QueryDesc *queryDesc,
|
||||
TupleDesc attinfo,
|
||||
EState *state,
|
||||
void (*cleanup)(Portal portal))
|
||||
{
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertArg(PortalIsValid(portal));
|
||||
AssertArg(IsA((Node*)state,EState));
|
||||
|
||||
portal->queryDesc = queryDesc;
|
||||
portal->state = state;
|
||||
portal->attinfo = attinfo;
|
||||
portal->cleanup = cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalGetQueryDesc --
|
||||
* Returns query attached to portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
*/
|
||||
QueryDesc *
|
||||
PortalGetQueryDesc(Portal portal)
|
||||
{
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertArg(PortalIsValid(portal));
|
||||
|
||||
return (portal->queryDesc);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalGetState --
|
||||
* Returns state attached to portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
*/
|
||||
EState *
|
||||
PortalGetState(Portal portal)
|
||||
{
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertArg(PortalIsValid(portal));
|
||||
|
||||
return (portal->state);
|
||||
}
|
||||
|
||||
/*
|
||||
* CreatePortal --
|
||||
* Returns a new portal given a name.
|
||||
*
|
||||
* Note:
|
||||
* This is expected to be of very limited usability. See instead,
|
||||
* BlankPortalAssignName.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal name is invalid.
|
||||
* "WARN" if portal name is in use.
|
||||
*/
|
||||
Portal
|
||||
CreatePortal(char *name) /* XXX PortalName */
|
||||
{
|
||||
Portal portal;
|
||||
uint16 length;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertArg(PointerIsValid(name)); /* XXX PortalName */
|
||||
|
||||
portal = GetPortalByName(name);
|
||||
if (PortalIsValid(portal)) {
|
||||
elog(NOTICE, "CreatePortal: portal %s already exists", name);
|
||||
return (portal);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* initialize portal name */
|
||||
length = 1 + strlen(name);
|
||||
portal->name = (char*)
|
||||
MemoryContextAlloc((MemoryContext)&portal->variable, length);
|
||||
strncpy(portal->name, name, length);
|
||||
|
||||
/* initialize portal query */
|
||||
portal->queryDesc = NULL;
|
||||
portal->attinfo = NULL;
|
||||
portal->state = NULL;
|
||||
portal->cleanup = NULL;
|
||||
|
||||
/* put portal in table */
|
||||
PortalHashTableInsert(portal);
|
||||
|
||||
/* Trap(PointerIsValid(name), Unimplemented); */
|
||||
return (portal);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalDestroy --
|
||||
* Destroys portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
*/
|
||||
void
|
||||
PortalDestroy(Portal *portalP)
|
||||
{
|
||||
Portal portal = *portalP;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertArg(PortalIsValid(portal));
|
||||
|
||||
/* remove portal from table if not blank portal */
|
||||
if (portal != BlankPortal)
|
||||
PortalHashTableDelete(portal);
|
||||
|
||||
/* reset portal */
|
||||
if (PointerIsValid(portal->cleanup))
|
||||
(*portal->cleanup)(portal);
|
||||
|
||||
PortalResetHeapMemory(portal);
|
||||
MemoryContextFree((MemoryContext)&portal->variable,
|
||||
(Pointer)portal->name);
|
||||
AllocSetReset(&portal->variable.setData); /* XXX log */
|
||||
|
||||
if (portal != BlankPortal)
|
||||
MemoryContextFree((MemoryContext)PortalMemory, (Pointer)portal);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* PortalResetHeapMemory --
|
||||
* Resets portal's heap memory context.
|
||||
*
|
||||
* Someday, Reset, Start, and End can be optimized by keeping a global
|
||||
* portal module stack of free HeapMemoryBlock's. This will make Start
|
||||
* and End be fast.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called when not in PortalHeapMemory context.
|
||||
* BadArg if mode is invalid.
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
PortalResetHeapMemory(Portal portal)
|
||||
{
|
||||
PortalHeapMemory context;
|
||||
MemoryContext currentContext;
|
||||
|
||||
context = PortalGetHeapMemory(portal);
|
||||
|
||||
if (PointerIsValid(context->block)) {
|
||||
/* save present context */
|
||||
currentContext = MemoryContextSwitchTo((MemoryContext)context);
|
||||
|
||||
do {
|
||||
EndPortalAllocMode();
|
||||
} while (PointerIsValid(context->block));
|
||||
|
||||
/* restore context */
|
||||
(void) MemoryContextSwitchTo(currentContext);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* StartPortalAllocMode --
|
||||
* Starts a new block of portal heap allocation using mode and limit;
|
||||
* the current block is disabled until EndPortalAllocMode is called.
|
||||
*
|
||||
* Note:
|
||||
* Note blocks may be stacked and restored arbitarily.
|
||||
* The semantics of mode and limit are described in aset.h.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called when not in PortalHeapMemory context.
|
||||
* BadArg if mode is invalid.
|
||||
*/
|
||||
void
|
||||
StartPortalAllocMode(AllocMode mode, Size limit)
|
||||
{
|
||||
PortalHeapMemory context;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertState(IsA(CurrentMemoryContext,PortalHeapMemory));
|
||||
/* AssertArg(AllocModeIsValid); */
|
||||
|
||||
context = (PortalHeapMemory)CurrentMemoryContext;
|
||||
|
||||
/* stack current mode */
|
||||
if (PointerIsValid(context->block))
|
||||
FixedStackPush(&context->stackData, context->block);
|
||||
|
||||
/* allocate and initialize new block */
|
||||
context->block =
|
||||
MemoryContextAlloc(
|
||||
(MemoryContext)PortalHeapMemoryGetVariableMemory(context),
|
||||
sizeof (HeapMemoryBlockData) );
|
||||
|
||||
/* XXX careful, context->block has never been stacked => bad state */
|
||||
|
||||
AllocSetInit(&HEAPMEMBLOCK(context)->setData, mode, limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* EndPortalAllocMode --
|
||||
* Ends current block of portal heap allocation; previous block is
|
||||
* reenabled.
|
||||
*
|
||||
* Note:
|
||||
* Note blocks may be stacked and restored arbitarily.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadState if called when not in PortalHeapMemory context.
|
||||
*/
|
||||
void
|
||||
EndPortalAllocMode()
|
||||
{
|
||||
PortalHeapMemory context;
|
||||
|
||||
AssertState(PortalManagerEnabled);
|
||||
AssertState(IsA(CurrentMemoryContext,PortalHeapMemory));
|
||||
|
||||
context = (PortalHeapMemory)CurrentMemoryContext;
|
||||
AssertState(PointerIsValid(context->block)); /* XXX Trap(...) */
|
||||
|
||||
/* free current mode */
|
||||
AllocSetReset(&HEAPMEMBLOCK(context)->setData);
|
||||
MemoryContextFree((MemoryContext)PortalHeapMemoryGetVariableMemory(context),
|
||||
context->block);
|
||||
|
||||
/* restore previous mode */
|
||||
context->block = FixedStackPop(&context->stackData);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalGetVariableMemory --
|
||||
* Returns variable memory context for a given portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
*/
|
||||
PortalVariableMemory
|
||||
PortalGetVariableMemory(Portal portal)
|
||||
{
|
||||
return (&portal->variable);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalGetHeapMemory --
|
||||
* Returns heap memory context for a given portal.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if portal is invalid.
|
||||
*/
|
||||
PortalHeapMemory
|
||||
PortalGetHeapMemory(Portal portal)
|
||||
{
|
||||
return (&portal->heap);
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalVariableMemoryGetPortal --
|
||||
* Returns portal containing given variable memory context.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if context is invalid.
|
||||
*/
|
||||
Portal
|
||||
PortalVariableMemoryGetPortal(PortalVariableMemory context)
|
||||
{
|
||||
return ((Portal)((char *)context - offsetof (PortalD, variable)));
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalHeapMemoryGetPortal --
|
||||
* Returns portal containing given heap memory context.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if context is invalid.
|
||||
*/
|
||||
Portal
|
||||
PortalHeapMemoryGetPortal(PortalHeapMemory context)
|
||||
{
|
||||
return ((Portal)((char *)context - offsetof (PortalD, heap)));
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalVariableMemoryGetHeapMemory --
|
||||
* Returns heap memory context associated with given variable memory.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if context is invalid.
|
||||
*/
|
||||
PortalHeapMemory
|
||||
PortalVariableMemoryGetHeapMemory(PortalVariableMemory context)
|
||||
{
|
||||
return ((PortalHeapMemory)((char *)context
|
||||
- offsetof (PortalD, variable)
|
||||
+ offsetof (PortalD, heap)));
|
||||
}
|
||||
|
||||
/*
|
||||
* PortalHeapMemoryGetVariableMemory --
|
||||
* Returns variable memory context associated with given heap memory.
|
||||
*
|
||||
* Exceptions:
|
||||
* BadState if called when disabled.
|
||||
* BadArg if context is invalid.
|
||||
*/
|
||||
PortalVariableMemory
|
||||
PortalHeapMemoryGetVariableMemory(PortalHeapMemory context)
|
||||
{
|
||||
return ((PortalVariableMemory)((char *)context
|
||||
- offsetof (PortalD, heap)
|
||||
+ offsetof (PortalD, variable)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user