[][src]Enum pgx::memcxt::PgMemoryContexts

pub enum PgMemoryContexts {
    CurrentMemoryContext,
    TopMemoryContext,
    PortalContext,
    ErrorContext,
    PostmasterContext,
    CacheMemoryContext,
    MessageContext,
    TopTransactionContext,
    CurTransactionContext,
    For(MemoryContext),
    Owned(OwnedMemoryContext),
    Of(void_ptr),
    Transient {
        parent: MemoryContext,
        name: &'static str,
        min_context_size: u32,
        initial_block_size: u32,
        max_block_size: u32,
    },
}

An Enumeration of Postgres top-level MemoryContexts. Each have their own use and "lifetimes" as defined by Postgres' memory management model.

It's possible to deference any one of these (except Transient) via the ::value() method if it's necessary to pass the raw pointer to a Postgres function.

Additionally, the ::switch_to() function, which takes a closure as its argument, executes the closure within that MemoryContext

Variants

CurrentMemoryContext

Because it would be too much notational overhead to always pass an appropriate memory context to called routines, there always exists the notion of the current memory context CurrentMemoryContext. Without it, for example, the copyObject routines would need to be passed a context, as would function execution routines that return a pass-by-reference datatype. Similarly for routines that temporarily allocate space internally, but don't return it to their caller? We certainly don't want to clutter every call in the system with "here is a context to use for any temporary memory allocation you might want to do".

The upshot of that reasoning, though, is that CurrentMemoryContext should generally point at a short-lifespan context if at all possible. During query execution it usually points to a context that gets reset after each tuple. Only in very circumscribed code should it ever point at a context having greater than transaction lifespan, since doing so risks permanent memory leaks.

TopMemoryContext

this is the actual top level of the context tree; every other context is a direct or indirect child of this one. Allocating here is essentially the same as "malloc", because this context will never be reset or deleted. This is for stuff that should live forever, or for stuff that the controlling module will take care of deleting at the appropriate time. An example is fd.c's tables of open files. Avoid allocating stuff here unless really necessary, and especially avoid running with CurrentMemoryContext pointing here.

PortalContext

this is not actually a separate context, but a global variable pointing to the per-portal context of the currently active execution portal. This can be used if it's necessary to allocate storage that will live just as long as the execution of the current portal requires.

ErrorContext

this permanent context is switched into for error recovery processing, and then reset on completion of recovery. We arrange to have a few KB of memory available in it at all times. In this way, we can ensure that some memory is available for error recovery even if the backend has run out of memory otherwise. This allows out-of-memory to be treated as a normal ERROR condition, not a FATAL error.

PostmasterContext

this is the postmaster's normal working context. After a backend is spawned, it can delete PostmasterContext to free its copy of memory the postmaster was using that it doesn't need. Note that in non-EXEC_BACKEND builds, the postmaster's copy of pg_hba.conf and pg_ident.conf data is used directly during authentication in backend processes; so backends can't delete PostmasterContext until that's done. (The postmaster has only TopMemoryContext, PostmasterContext, and ErrorContext --- the remaining top-level contexts are set up in each backend during startup.)

CacheMemoryContext

permanent storage for relcache, catcache, and related modules. This will never be reset or deleted, either, so it's not truly necessary to distinguish it from TopMemoryContext. But it seems worthwhile to maintain the distinction for debugging purposes. (Note: CacheMemoryContext has child contexts with shorter lifespans. For example, a child context is the best place to keep the subsidiary storage associated with a relcache entry; that way we can free rule parsetrees and so forth easily, without having to depend on constructing a reliable version of freeObject().)

MessageContext

this context holds the current command message from the frontend, as well as any derived storage that need only live as long as the current message (for example, in simple-Query mode the parse and plan trees can live here). This context will be reset, and any children deleted, at the top of each cycle of the outer loop of PostgresMain. This is kept separate from per-transaction and per-portal contexts because a query string might need to live either a longer or shorter time than any single transaction or portal.

TopTransactionContext

this holds everything that lives until end of the top-level transaction. This context will be reset, and all its children deleted, at conclusion of each top-level transaction cycle. In most cases you don't want to allocate stuff directly here, but in CurTransactionContext; what does belong here is control information that exists explicitly to manage status across multiple subtransactions. Note: this context is NOT cleared immediately upon error; its contents will survive until the transaction block is exited by COMMIT/ROLLBACK.

CurTransactionContext

this holds data that has to survive until the end of the current transaction, and in particular will be needed at top-level transaction commit. When we are in a top-level transaction this is the same as TopTransactionContext, but in subtransactions it points to a child context. It is important to understand that if a subtransaction aborts, its CurTransactionContext is thrown away after finishing the abort processing; but a committed subtransaction's CurTransactionContext is kept until top-level commit (unless of course one of the intermediate levels of subtransaction aborts). This ensures that we do not keep data from a failed subtransaction longer than necessary. Because of this behavior, you must be careful to clean up properly during subtransaction abort --- the subtransaction's state must be delinked from any pointers or lists kept in upper transactions, or you will have dangling pointers leading to a crash at top-level commit. An example of data kept here is pending NOTIFY messages, which are sent at top-level commit, but only if the generating subtransaction did not abort.

This represents a MemoryContext that was likely created via pg_sys::AllocSetContextCreateExtended.

That could be a MemoryContext you created yourself, or it could be one given to you from Postgres. For example, the TupleTableSlot struct has a field referencing the MemoryContext in which slots are allocated.

A MemoryContext owned by Rust that will be freed when when Dropped

Use the MemoryContext in which the specified pointer was allocated.

It's incredibly important that the specified pointer be one actually allocated by Postgres' memory management system. Otherwise, it's undefined behavior and will absolutely crash Postgres

Transient

Create a temporary MemoryContext for use with [::switch_to()]. It gets deleted as soon as [::switch_to()] exits.

Trying to use this context through [::value{}] will result in a panic!().

Fields of Transient

parent: MemoryContextname: &'static strmin_context_size: u32initial_block_size: u32max_block_size: u32

Implementations

impl PgMemoryContexts[src]

pub fn new(name: &str) -> PgMemoryContexts[src]

Create a new PgMemoryContext::Owned

pub fn value(&self) -> MemoryContext[src]

Retrieve the underlying Postgres *mut MemoryContextData

This works for every type except the ::Transient type.

pub fn set_as_current(&self) -> PgMemoryContexts[src]

Set this MemoryContext as the CurrentMemoryContext, returning whatever CurrentMemoryContext` is

pub fn reset(&mut self)[src]

Release all space allocated within a context and delete all its descendant contexts (but not the context itself).

pub fn switch_to<R, F: Fn(&mut PgMemoryContexts) -> R + UnwindSafe + RefUnwindSafe>(
    &mut self,
    f: F
) -> R
[src]

Run the specified function "within" the MemoryContext represented by this enum.

The important implementation detail is that Postgres' CurrentMemoryContext is changed to be this context, the function is run so that all Postgres memory allocations happen within that context, and then CurrentMemoryContext is restored to what it was before we started.

Examples

use pgx::*;

#[pg_guard]
pub fn do_something() -> pg_sys::ItemPointer {
    PgMemoryContexts::TopTransactionContext.switch_to(|context| {
        // allocate a new ItemPointerData, but inside the TopTransactionContext
        let tid = PgBox::<pg_sys::ItemPointerData>::alloc();
         
        // do something with the tid and then return it.
        // Note that it stays allocated here in the TopTransactionContext
        tid.into_pg()
    })
}

pub fn pstrdup(&self, s: &str) -> *mut c_char[src]

Duplicate a Rust &str into a Postgres-allocated "char *"

Examples

use pgx::PgMemoryContexts;
let copy = PgMemoryContexts::CurrentMemoryContext.pstrdup("make a copy of this");

pub fn copy_ptr_into<T>(&mut self, src: *mut T, len: usize) -> *mut T[src]

Copies len bytes, starting at src into this memory context and returns a raw *mut T pointer to the newly allocated location

pub fn palloc(&mut self, len: usize) -> *mut c_void[src]

Allocate memory in this context, which will be free'd whenever Postgres deletes this MemoryContext

pub fn palloc_struct<T>(&mut self) -> *mut T[src]

pub fn palloc0_struct<T>(&mut self) -> *mut T[src]

pub fn palloc_slice<'a, T>(&mut self, len: usize) -> &'a mut [T][src]

Allocate a slice in this context, which will be free'd whenever Postgres deletes this MemoryContext

pub fn palloc0_slice<'a, T>(&mut self, len: usize) -> &'a mut [T][src]

Allocate a slice in this context, where the memory is zero'd, which will be free'd whenever Postgres deletes this MemoryContext

pub fn palloc0(&mut self, len: usize) -> *mut c_void[src]

Allocate memory in this context, which will be free'd whenever Postgres deletes this MemoryContext

The allocated memory is zero'd

pub fn leak_and_drop_on_delete<T>(&mut self, v: T) -> *mut T[src]

Trait Implementations

impl Debug for PgMemoryContexts[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Same<T> for T

type Output = T

Should always be Self

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.