Header And Logo

PostgreSQL
| The world's most advanced open source database.

mcxt.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * mcxt.c
00004  *    POSTGRES memory context management code.
00005  *
00006  * This module handles context management operations that are independent
00007  * of the particular kind of context being operated on.  It calls
00008  * context-type-specific operations via the function pointers in a
00009  * context's MemoryContextMethods struct.
00010  *
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  * Portions Copyright (c) 1994, Regents of the University of California
00014  *
00015  *
00016  * IDENTIFICATION
00017  *    src/backend/utils/mmgr/mcxt.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 
00022 /* see palloc.h.  Must be before postgres.h */
00023 #define MCXT_INCLUDE_DEFINITIONS
00024 
00025 #include "postgres.h"
00026 
00027 #include "utils/memutils.h"
00028 
00029 
00030 /*****************************************************************************
00031  *    GLOBAL MEMORY                                                          *
00032  *****************************************************************************/
00033 
00034 /*
00035  * CurrentMemoryContext
00036  *      Default memory context for allocations.
00037  */
00038 MemoryContext CurrentMemoryContext = NULL;
00039 
00040 /*
00041  * Standard top-level contexts. For a description of the purpose of each
00042  * of these contexts, refer to src/backend/utils/mmgr/README
00043  */
00044 MemoryContext TopMemoryContext = NULL;
00045 MemoryContext ErrorContext = NULL;
00046 MemoryContext PostmasterContext = NULL;
00047 MemoryContext CacheMemoryContext = NULL;
00048 MemoryContext MessageContext = NULL;
00049 MemoryContext TopTransactionContext = NULL;
00050 MemoryContext CurTransactionContext = NULL;
00051 
00052 /* This is a transient link to the active portal's memory context: */
00053 MemoryContext PortalContext = NULL;
00054 
00055 static void MemoryContextStatsInternal(MemoryContext context, int level);
00056 
00057 
00058 /*****************************************************************************
00059  *    EXPORTED ROUTINES                                                      *
00060  *****************************************************************************/
00061 
00062 
00063 /*
00064  * MemoryContextInit
00065  *      Start up the memory-context subsystem.
00066  *
00067  * This must be called before creating contexts or allocating memory in
00068  * contexts.  TopMemoryContext and ErrorContext are initialized here;
00069  * other contexts must be created afterwards.
00070  *
00071  * In normal multi-backend operation, this is called once during
00072  * postmaster startup, and not at all by individual backend startup
00073  * (since the backends inherit an already-initialized context subsystem
00074  * by virtue of being forked off the postmaster).
00075  *
00076  * In a standalone backend this must be called during backend startup.
00077  */
00078 void
00079 MemoryContextInit(void)
00080 {
00081     AssertState(TopMemoryContext == NULL);
00082 
00083     /*
00084      * Initialize TopMemoryContext as an AllocSetContext with slow growth rate
00085      * --- we don't really expect much to be allocated in it.
00086      *
00087      * (There is special-case code in MemoryContextCreate() for this call.)
00088      */
00089     TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
00090                                              "TopMemoryContext",
00091                                              0,
00092                                              8 * 1024,
00093                                              8 * 1024);
00094 
00095     /*
00096      * Not having any other place to point CurrentMemoryContext, make it point
00097      * to TopMemoryContext.  Caller should change this soon!
00098      */
00099     CurrentMemoryContext = TopMemoryContext;
00100 
00101     /*
00102      * Initialize ErrorContext as an AllocSetContext with slow growth rate ---
00103      * we don't really expect much to be allocated in it. More to the point,
00104      * require it to contain at least 8K at all times. This is the only case
00105      * where retained memory in a context is *essential* --- we want to be
00106      * sure ErrorContext still has some memory even if we've run out
00107      * elsewhere!
00108      */
00109     ErrorContext = AllocSetContextCreate(TopMemoryContext,
00110                                          "ErrorContext",
00111                                          8 * 1024,
00112                                          8 * 1024,
00113                                          8 * 1024);
00114 }
00115 
00116 /*
00117  * MemoryContextReset
00118  *      Release all space allocated within a context and its descendants,
00119  *      but don't delete the contexts themselves.
00120  *
00121  * The type-specific reset routine handles the context itself, but we
00122  * have to do the recursion for the children.
00123  */
00124 void
00125 MemoryContextReset(MemoryContext context)
00126 {
00127     AssertArg(MemoryContextIsValid(context));
00128 
00129     /* save a function call in common case where there are no children */
00130     if (context->firstchild != NULL)
00131         MemoryContextResetChildren(context);
00132 
00133     /* Nothing to do if no pallocs since startup or last reset */
00134     if (!context->isReset)
00135     {
00136         (*context->methods->reset) (context);
00137         context->isReset = true;
00138     }
00139 }
00140 
00141 /*
00142  * MemoryContextResetChildren
00143  *      Release all space allocated within a context's descendants,
00144  *      but don't delete the contexts themselves.  The named context
00145  *      itself is not touched.
00146  */
00147 void
00148 MemoryContextResetChildren(MemoryContext context)
00149 {
00150     MemoryContext child;
00151 
00152     AssertArg(MemoryContextIsValid(context));
00153 
00154     for (child = context->firstchild; child != NULL; child = child->nextchild)
00155         MemoryContextReset(child);
00156 }
00157 
00158 /*
00159  * MemoryContextDelete
00160  *      Delete a context and its descendants, and release all space
00161  *      allocated therein.
00162  *
00163  * The type-specific delete routine removes all subsidiary storage
00164  * for the context, but we have to delete the context node itself,
00165  * as well as recurse to get the children.  We must also delink the
00166  * node from its parent, if it has one.
00167  */
00168 void
00169 MemoryContextDelete(MemoryContext context)
00170 {
00171     AssertArg(MemoryContextIsValid(context));
00172     /* We had better not be deleting TopMemoryContext ... */
00173     Assert(context != TopMemoryContext);
00174     /* And not CurrentMemoryContext, either */
00175     Assert(context != CurrentMemoryContext);
00176 
00177     MemoryContextDeleteChildren(context);
00178 
00179     /*
00180      * We delink the context from its parent before deleting it, so that if
00181      * there's an error we won't have deleted/busted contexts still attached
00182      * to the context tree.  Better a leak than a crash.
00183      */
00184     MemoryContextSetParent(context, NULL);
00185 
00186     (*context->methods->delete_context) (context);
00187     pfree(context);
00188 }
00189 
00190 /*
00191  * MemoryContextDeleteChildren
00192  *      Delete all the descendants of the named context and release all
00193  *      space allocated therein.  The named context itself is not touched.
00194  */
00195 void
00196 MemoryContextDeleteChildren(MemoryContext context)
00197 {
00198     AssertArg(MemoryContextIsValid(context));
00199 
00200     /*
00201      * MemoryContextDelete will delink the child from me, so just iterate as
00202      * long as there is a child.
00203      */
00204     while (context->firstchild != NULL)
00205         MemoryContextDelete(context->firstchild);
00206 }
00207 
00208 /*
00209  * MemoryContextResetAndDeleteChildren
00210  *      Release all space allocated within a context and delete all
00211  *      its descendants.
00212  *
00213  * This is a common combination case where we want to preserve the
00214  * specific context but get rid of absolutely everything under it.
00215  */
00216 void
00217 MemoryContextResetAndDeleteChildren(MemoryContext context)
00218 {
00219     AssertArg(MemoryContextIsValid(context));
00220 
00221     MemoryContextDeleteChildren(context);
00222     MemoryContextReset(context);
00223 }
00224 
00225 /*
00226  * MemoryContextSetParent
00227  *      Change a context to belong to a new parent (or no parent).
00228  *
00229  * We provide this as an API function because it is sometimes useful to
00230  * change a context's lifespan after creation.  For example, a context
00231  * might be created underneath a transient context, filled with data,
00232  * and then reparented underneath CacheMemoryContext to make it long-lived.
00233  * In this way no special effort is needed to get rid of the context in case
00234  * a failure occurs before its contents are completely set up.
00235  *
00236  * Callers often assume that this function cannot fail, so don't put any
00237  * elog(ERROR) calls in it.
00238  *
00239  * A possible caller error is to reparent a context under itself, creating
00240  * a loop in the context graph.  We assert here that context != new_parent,
00241  * but checking for multi-level loops seems more trouble than it's worth.
00242  */
00243 void
00244 MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
00245 {
00246     AssertArg(MemoryContextIsValid(context));
00247     AssertArg(context != new_parent);
00248 
00249     /* Delink from existing parent, if any */
00250     if (context->parent)
00251     {
00252         MemoryContext parent = context->parent;
00253 
00254         if (context == parent->firstchild)
00255             parent->firstchild = context->nextchild;
00256         else
00257         {
00258             MemoryContext child;
00259 
00260             for (child = parent->firstchild; child; child = child->nextchild)
00261             {
00262                 if (context == child->nextchild)
00263                 {
00264                     child->nextchild = context->nextchild;
00265                     break;
00266                 }
00267             }
00268         }
00269     }
00270 
00271     /* And relink */
00272     if (new_parent)
00273     {
00274         AssertArg(MemoryContextIsValid(new_parent));
00275         context->parent = new_parent;
00276         context->nextchild = new_parent->firstchild;
00277         new_parent->firstchild = context;
00278     }
00279     else
00280     {
00281         context->parent = NULL;
00282         context->nextchild = NULL;
00283     }
00284 }
00285 
00286 /*
00287  * GetMemoryChunkSpace
00288  *      Given a currently-allocated chunk, determine the total space
00289  *      it occupies (including all memory-allocation overhead).
00290  *
00291  * This is useful for measuring the total space occupied by a set of
00292  * allocated chunks.
00293  */
00294 Size
00295 GetMemoryChunkSpace(void *pointer)
00296 {
00297     StandardChunkHeader *header;
00298 
00299     /*
00300      * Try to detect bogus pointers handed to us, poorly though we can.
00301      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
00302      * allocated chunk.
00303      */
00304     Assert(pointer != NULL);
00305     Assert(pointer == (void *) MAXALIGN(pointer));
00306 
00307     /*
00308      * OK, it's probably safe to look at the chunk header.
00309      */
00310     header = (StandardChunkHeader *)
00311         ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00312 
00313     AssertArg(MemoryContextIsValid(header->context));
00314 
00315     return (*header->context->methods->get_chunk_space) (header->context,
00316                                                          pointer);
00317 }
00318 
00319 /*
00320  * GetMemoryChunkContext
00321  *      Given a currently-allocated chunk, determine the context
00322  *      it belongs to.
00323  */
00324 MemoryContext
00325 GetMemoryChunkContext(void *pointer)
00326 {
00327     StandardChunkHeader *header;
00328 
00329     /*
00330      * Try to detect bogus pointers handed to us, poorly though we can.
00331      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
00332      * allocated chunk.
00333      */
00334     Assert(pointer != NULL);
00335     Assert(pointer == (void *) MAXALIGN(pointer));
00336 
00337     /*
00338      * OK, it's probably safe to look at the chunk header.
00339      */
00340     header = (StandardChunkHeader *)
00341         ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00342 
00343     AssertArg(MemoryContextIsValid(header->context));
00344 
00345     return header->context;
00346 }
00347 
00348 /*
00349  * MemoryContextGetParent
00350  *      Get the parent context (if any) of the specified context
00351  */
00352 MemoryContext
00353 MemoryContextGetParent(MemoryContext context)
00354 {
00355     AssertArg(MemoryContextIsValid(context));
00356 
00357     return context->parent;
00358 }
00359 
00360 /*
00361  * MemoryContextIsEmpty
00362  *      Is a memory context empty of any allocated space?
00363  */
00364 bool
00365 MemoryContextIsEmpty(MemoryContext context)
00366 {
00367     AssertArg(MemoryContextIsValid(context));
00368 
00369     /*
00370      * For now, we consider a memory context nonempty if it has any children;
00371      * perhaps this should be changed later.
00372      */
00373     if (context->firstchild != NULL)
00374         return false;
00375     /* Otherwise use the type-specific inquiry */
00376     return (*context->methods->is_empty) (context);
00377 }
00378 
00379 /*
00380  * MemoryContextStats
00381  *      Print statistics about the named context and all its descendants.
00382  *
00383  * This is just a debugging utility, so it's not fancy.  The statistics
00384  * are merely sent to stderr.
00385  */
00386 void
00387 MemoryContextStats(MemoryContext context)
00388 {
00389     MemoryContextStatsInternal(context, 0);
00390 }
00391 
00392 static void
00393 MemoryContextStatsInternal(MemoryContext context, int level)
00394 {
00395     MemoryContext child;
00396 
00397     AssertArg(MemoryContextIsValid(context));
00398 
00399     (*context->methods->stats) (context, level);
00400     for (child = context->firstchild; child != NULL; child = child->nextchild)
00401         MemoryContextStatsInternal(child, level + 1);
00402 }
00403 
00404 /*
00405  * MemoryContextCheck
00406  *      Check all chunks in the named context.
00407  *
00408  * This is just a debugging utility, so it's not fancy.
00409  */
00410 #ifdef MEMORY_CONTEXT_CHECKING
00411 void
00412 MemoryContextCheck(MemoryContext context)
00413 {
00414     MemoryContext child;
00415 
00416     AssertArg(MemoryContextIsValid(context));
00417 
00418     (*context->methods->check) (context);
00419     for (child = context->firstchild; child != NULL; child = child->nextchild)
00420         MemoryContextCheck(child);
00421 }
00422 #endif
00423 
00424 /*
00425  * MemoryContextContains
00426  *      Detect whether an allocated chunk of memory belongs to a given
00427  *      context or not.
00428  *
00429  * Caution: this test is reliable as long as 'pointer' does point to
00430  * a chunk of memory allocated from *some* context.  If 'pointer' points
00431  * at memory obtained in some other way, there is a small chance of a
00432  * false-positive result, since the bits right before it might look like
00433  * a valid chunk header by chance.
00434  */
00435 bool
00436 MemoryContextContains(MemoryContext context, void *pointer)
00437 {
00438     StandardChunkHeader *header;
00439 
00440     /*
00441      * Try to detect bogus pointers handed to us, poorly though we can.
00442      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
00443      * allocated chunk.
00444      */
00445     if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
00446         return false;
00447 
00448     /*
00449      * OK, it's probably safe to look at the chunk header.
00450      */
00451     header = (StandardChunkHeader *)
00452         ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00453 
00454     /*
00455      * If the context link doesn't match then we certainly have a non-member
00456      * chunk.  Also check for a reasonable-looking size as extra guard against
00457      * being fooled by bogus pointers.
00458      */
00459     if (header->context == context && AllocSizeIsValid(header->size))
00460         return true;
00461     return false;
00462 }
00463 
00464 /*--------------------
00465  * MemoryContextCreate
00466  *      Context-type-independent part of context creation.
00467  *
00468  * This is only intended to be called by context-type-specific
00469  * context creation routines, not by the unwashed masses.
00470  *
00471  * The context creation procedure is a little bit tricky because
00472  * we want to be sure that we don't leave the context tree invalid
00473  * in case of failure (such as insufficient memory to allocate the
00474  * context node itself).  The procedure goes like this:
00475  *  1.  Context-type-specific routine first calls MemoryContextCreate(),
00476  *      passing the appropriate tag/size/methods values (the methods
00477  *      pointer will ordinarily point to statically allocated data).
00478  *      The parent and name parameters usually come from the caller.
00479  *  2.  MemoryContextCreate() attempts to allocate the context node,
00480  *      plus space for the name.  If this fails we can ereport() with no
00481  *      damage done.
00482  *  3.  We fill in all of the type-independent MemoryContext fields.
00483  *  4.  We call the type-specific init routine (using the methods pointer).
00484  *      The init routine is required to make the node minimally valid
00485  *      with zero chance of failure --- it can't allocate more memory,
00486  *      for example.
00487  *  5.  Now we have a minimally valid node that can behave correctly
00488  *      when told to reset or delete itself.  We link the node to its
00489  *      parent (if any), making the node part of the context tree.
00490  *  6.  We return to the context-type-specific routine, which finishes
00491  *      up type-specific initialization.  This routine can now do things
00492  *      that might fail (like allocate more memory), so long as it's
00493  *      sure the node is left in a state that delete will handle.
00494  *
00495  * This protocol doesn't prevent us from leaking memory if step 6 fails
00496  * during creation of a top-level context, since there's no parent link
00497  * in that case.  However, if you run out of memory while you're building
00498  * a top-level context, you might as well go home anyway...
00499  *
00500  * Normally, the context node and the name are allocated from
00501  * TopMemoryContext (NOT from the parent context, since the node must
00502  * survive resets of its parent context!).  However, this routine is itself
00503  * used to create TopMemoryContext!  If we see that TopMemoryContext is NULL,
00504  * we assume we are creating TopMemoryContext and use malloc() to allocate
00505  * the node.
00506  *
00507  * Note that the name field of a MemoryContext does not point to
00508  * separately-allocated storage, so it should not be freed at context
00509  * deletion.
00510  *--------------------
00511  */
00512 MemoryContext
00513 MemoryContextCreate(NodeTag tag, Size size,
00514                     MemoryContextMethods *methods,
00515                     MemoryContext parent,
00516                     const char *name)
00517 {
00518     MemoryContext node;
00519     Size        needed = size + strlen(name) + 1;
00520 
00521     /* Get space for node and name */
00522     if (TopMemoryContext != NULL)
00523     {
00524         /* Normal case: allocate the node in TopMemoryContext */
00525         node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
00526                                                   needed);
00527     }
00528     else
00529     {
00530         /* Special case for startup: use good ol' malloc */
00531         node = (MemoryContext) malloc(needed);
00532         Assert(node != NULL);
00533     }
00534 
00535     /* Initialize the node as best we can */
00536     MemSet(node, 0, size);
00537     node->type = tag;
00538     node->methods = methods;
00539     node->parent = NULL;        /* for the moment */
00540     node->firstchild = NULL;
00541     node->nextchild = NULL;
00542     node->isReset = true;
00543     node->name = ((char *) node) + size;
00544     strcpy(node->name, name);
00545 
00546     /* Type-specific routine finishes any other essential initialization */
00547     (*node->methods->init) (node);
00548 
00549     /* OK to link node to parent (if any) */
00550     /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
00551     if (parent)
00552     {
00553         node->parent = parent;
00554         node->nextchild = parent->firstchild;
00555         parent->firstchild = node;
00556     }
00557 
00558     /* Return to type-specific creation routine to finish up */
00559     return node;
00560 }
00561 
00562 /*
00563  * MemoryContextAlloc
00564  *      Allocate space within the specified context.
00565  *
00566  * This could be turned into a macro, but we'd have to import
00567  * nodes/memnodes.h into postgres.h which seems a bad idea.
00568  */
00569 void *
00570 MemoryContextAlloc(MemoryContext context, Size size)
00571 {
00572     AssertArg(MemoryContextIsValid(context));
00573 
00574     if (!AllocSizeIsValid(size))
00575         elog(ERROR, "invalid memory alloc request size %lu",
00576              (unsigned long) size);
00577 
00578     context->isReset = false;
00579 
00580     return (*context->methods->alloc) (context, size);
00581 }
00582 
00583 /*
00584  * MemoryContextAllocZero
00585  *      Like MemoryContextAlloc, but clears allocated memory
00586  *
00587  *  We could just call MemoryContextAlloc then clear the memory, but this
00588  *  is a very common combination, so we provide the combined operation.
00589  */
00590 void *
00591 MemoryContextAllocZero(MemoryContext context, Size size)
00592 {
00593     void       *ret;
00594 
00595     AssertArg(MemoryContextIsValid(context));
00596 
00597     if (!AllocSizeIsValid(size))
00598         elog(ERROR, "invalid memory alloc request size %lu",
00599              (unsigned long) size);
00600 
00601     context->isReset = false;
00602 
00603     ret = (*context->methods->alloc) (context, size);
00604 
00605     MemSetAligned(ret, 0, size);
00606 
00607     return ret;
00608 }
00609 
00610 /*
00611  * MemoryContextAllocZeroAligned
00612  *      MemoryContextAllocZero where length is suitable for MemSetLoop
00613  *
00614  *  This might seem overly specialized, but it's not because newNode()
00615  *  is so often called with compile-time-constant sizes.
00616  */
00617 void *
00618 MemoryContextAllocZeroAligned(MemoryContext context, Size size)
00619 {
00620     void       *ret;
00621 
00622     AssertArg(MemoryContextIsValid(context));
00623 
00624     if (!AllocSizeIsValid(size))
00625         elog(ERROR, "invalid memory alloc request size %lu",
00626              (unsigned long) size);
00627 
00628     context->isReset = false;
00629 
00630     ret = (*context->methods->alloc) (context, size);
00631 
00632     MemSetLoop(ret, 0, size);
00633 
00634     return ret;
00635 }
00636 
00637 void *
00638 palloc(Size size)
00639 {
00640     /* duplicates MemoryContextAlloc to avoid increased overhead */
00641     AssertArg(MemoryContextIsValid(CurrentMemoryContext));
00642 
00643     if (!AllocSizeIsValid(size))
00644         elog(ERROR, "invalid memory alloc request size %lu",
00645              (unsigned long) size);
00646 
00647     CurrentMemoryContext->isReset = false;
00648 
00649     return (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
00650 }
00651 
00652 void *
00653 palloc0(Size size)
00654 {
00655     /* duplicates MemoryContextAllocZero to avoid increased overhead */
00656     void       *ret;
00657 
00658     AssertArg(MemoryContextIsValid(CurrentMemoryContext));
00659 
00660     if (!AllocSizeIsValid(size))
00661         elog(ERROR, "invalid memory alloc request size %lu",
00662              (unsigned long) size);
00663 
00664     CurrentMemoryContext->isReset = false;
00665 
00666     ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
00667 
00668     MemSetAligned(ret, 0, size);
00669 
00670     return ret;
00671 }
00672 
00673 /*
00674  * pfree
00675  *      Release an allocated chunk.
00676  */
00677 void
00678 pfree(void *pointer)
00679 {
00680     StandardChunkHeader *header;
00681 
00682     /*
00683      * Try to detect bogus pointers handed to us, poorly though we can.
00684      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
00685      * allocated chunk.
00686      */
00687     Assert(pointer != NULL);
00688     Assert(pointer == (void *) MAXALIGN(pointer));
00689 
00690     /*
00691      * OK, it's probably safe to look at the chunk header.
00692      */
00693     header = (StandardChunkHeader *)
00694         ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00695 
00696     AssertArg(MemoryContextIsValid(header->context));
00697 
00698     (*header->context->methods->free_p) (header->context, pointer);
00699 }
00700 
00701 /*
00702  * repalloc
00703  *      Adjust the size of a previously allocated chunk.
00704  */
00705 void *
00706 repalloc(void *pointer, Size size)
00707 {
00708     StandardChunkHeader *header;
00709 
00710     /*
00711      * Try to detect bogus pointers handed to us, poorly though we can.
00712      * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
00713      * allocated chunk.
00714      */
00715     Assert(pointer != NULL);
00716     Assert(pointer == (void *) MAXALIGN(pointer));
00717 
00718     /*
00719      * OK, it's probably safe to look at the chunk header.
00720      */
00721     header = (StandardChunkHeader *)
00722         ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00723 
00724     AssertArg(MemoryContextIsValid(header->context));
00725 
00726     if (!AllocSizeIsValid(size))
00727         elog(ERROR, "invalid memory alloc request size %lu",
00728              (unsigned long) size);
00729 
00730     /* isReset must be false already */
00731     Assert(!header->context->isReset);
00732 
00733     return (*header->context->methods->realloc) (header->context,
00734                                                  pointer, size);
00735 }
00736 
00737 /*
00738  * MemoryContextStrdup
00739  *      Like strdup(), but allocate from the specified context
00740  */
00741 char *
00742 MemoryContextStrdup(MemoryContext context, const char *string)
00743 {
00744     char       *nstr;
00745     Size        len = strlen(string) + 1;
00746 
00747     nstr = (char *) MemoryContextAlloc(context, len);
00748 
00749     memcpy(nstr, string, len);
00750 
00751     return nstr;
00752 }
00753 
00754 char *
00755 pstrdup(const char *in)
00756 {
00757     return MemoryContextStrdup(CurrentMemoryContext, in);
00758 }
00759 
00760 /*
00761  * pnstrdup
00762  *      Like pstrdup(), but append null byte to a
00763  *      not-necessarily-null-terminated input string.
00764  */
00765 char *
00766 pnstrdup(const char *in, Size len)
00767 {
00768     char       *out = palloc(len + 1);
00769 
00770     memcpy(out, in, len);
00771     out[len] = '\0';
00772     return out;
00773 }