1
0
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:
Marc G. Fournier
1996-07-09 06:22:35 +00:00
commit d31084e9d1
868 changed files with 242656 additions and 0 deletions

View 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

View 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);
}

View 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);
}
}

View 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;
}

View 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;
}

View 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)));
}