*** a/contrib/Makefile --- b/contrib/Makefile *************** *** 47,53 **** SUBDIRS = \ tsm_system_time \ tsearch2 \ unaccent \ ! vacuumlo ifeq ($(with_openssl),yes) SUBDIRS += sslinfo --- 47,54 ---- tsm_system_time \ tsearch2 \ unaccent \ ! vacuumlo \ ! memdump ifeq ($(with_openssl),yes) SUBDIRS += sslinfo *** /dev/null --- b/contrib/memdump/Makefile *************** *** 0 **** --- 1,21 ---- + # contrib/memdump/Makefile + + MODULES = memdump + + EXTENSION = memdump + DATA = memdump--1.0.sql memdump--unpackaged--1.0.sql + + REGRESS = memdump + + LDFLAGS_SL += $(filter -lm, $(LIBS)) + + ifdef USE_PGXS + PG_CONFIG = pg_config + PGXS := $(shell $(PG_CONFIG) --pgxs) + include $(PGXS) + else + subdir = contrib/memdump + top_builddir = ../.. + include $(top_builddir)/src/Makefile.global + include $(top_srcdir)/contrib/contrib-global.mk + endif *** /dev/null --- b/contrib/memdump/memdump--1.0.sql *************** *** 0 **** --- 1,9 ---- + /* contrib/memdump/memdump--1.0.sql */ + + -- complain if script is sourced in psql, rather than via CREATE EXTENSION + \echo Use "CREATE EXTENSION memdump" to load this file. \quit + + CREATE FUNCTION dump_memctxt_info() + RETURNS void + AS 'MODULE_PATHNAME','dump_memctxt_info' + LANGUAGE C VOLATILE STRICT; *** /dev/null --- b/contrib/memdump/memdump--unpackaged--1.0.sql *************** *** 0 **** --- 1,7 ---- + /* contrib/memdump/memdump--unpackaged--1.0.sql */ + + -- complain if script is sourced in psql, rather than via CREATE EXTENSION + \echo Use "CREATE EXTENSION memdump" to load this file. \quit + + ALTER EXTENSION memdump ADD function dump_memctxt_info(void); + *** /dev/null --- b/contrib/memdump/memdump.c *************** *** 0 **** --- 1,58 ---- + /*------------------------------------------------------------------------- + * + * misc.c + * + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * contrib/memdump/memdump.c + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include "utils/memutils.h" + #include "storage/fd.h" + #include "pgtime.h" + #include + #include "utils/builtins.h" + #include "pgtime.h" + + PG_MODULE_MAGIC; + + extern Datum dump_memctxt_info(PG_FUNCTION_ARGS); + PG_FUNCTION_INFO_V1(dump_memctxt_info); + + Datum + dump_memctxt_info(PG_FUNCTION_ARGS) + { + FILE *file = NULL; + char filename[MAXPGPATH]; + int len; + pg_time_t tnow = (pg_time_t) time(NULL); + struct pg_tm *tz; + + memset(filename, 0, MAXPGPATH); + + /* + * For the file to dump memory context details in the format of + * "context__.dump". + */ + tz = pg_localtime(&tnow, pg_get_timezone()); + + snprintf(filename, MAXPGPATH, "context_%d", (int)getpid()); + len = strlen(filename); + + pg_strftime(filename + len, MAXPGPATH - len, "_%Y-%m-%d_%H%M%S.dump", tz); + + file = AllocateFile(filename,"w"); + + /* Do the actual work*/ + MemoryContextStats(TopMemoryContext, file); + + return 0; + } *** /dev/null --- b/contrib/memdump/memdump.control *************** *** 0 **** --- 1,5 ---- + # memdump extension + comment = 'functions that dump all memory context' + default_version = '1.0' + module_pathname = '$libdir/memdump' + relocatable = true *** a/src/backend/utils/misc/timeout.c --- b/src/backend/utils/misc/timeout.c *************** *** 21,27 **** #include "utils/timeout.h" #include "utils/timestamp.h" - /* Data about any one timeout reason */ typedef struct timeout_params { --- 21,26 ---- *** a/src/backend/utils/mmgr/aset.c --- b/src/backend/utils/mmgr/aset.c *************** *** 254,260 **** static void AllocSetDelete(MemoryContext context); static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer); static bool AllocSetIsEmpty(MemoryContext context); static void AllocSetStats(MemoryContext context, int level, bool print, ! MemoryContextCounters *totals); #ifdef MEMORY_CONTEXT_CHECKING static void AllocSetCheck(MemoryContext context); --- 254,260 ---- static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer); static bool AllocSetIsEmpty(MemoryContext context); static void AllocSetStats(MemoryContext context, int level, bool print, ! MemoryContextCounters *totals, FILE *file); #ifdef MEMORY_CONTEXT_CHECKING static void AllocSetCheck(MemoryContext context); *************** *** 499,505 **** AllocSetContextCreate(MemoryContext parent, block = (AllocBlock) malloc(blksize); if (block == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 499,505 ---- block = (AllocBlock) malloc(blksize); if (block == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 1237,1243 **** AllocSetIsEmpty(MemoryContext context) */ static void AllocSetStats(MemoryContext context, int level, bool print, ! MemoryContextCounters *totals) { AllocSet set = (AllocSet) context; Size nblocks = 0; --- 1237,1243 ---- */ static void AllocSetStats(MemoryContext context, int level, bool print, ! MemoryContextCounters *totals, FILE *file) { AllocSet set = (AllocSet) context; Size nblocks = 0; *************** *** 1270,1277 **** AllocSetStats(MemoryContext context, int level, bool print, int i; for (i = 0; i < level; i++) ! fprintf(stderr, " "); ! fprintf(stderr, "%s: %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n", set->header.name, totalspace, nblocks, freespace, freechunks, totalspace - freespace); --- 1270,1277 ---- int i; for (i = 0; i < level; i++) ! fprintf(file, " "); ! fprintf(file, "%s: %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n", set->header.name, totalspace, nblocks, freespace, freechunks, totalspace - freespace); *** a/src/backend/utils/mmgr/mcxt.c --- b/src/backend/utils/mmgr/mcxt.c *************** *** 54,60 **** MemoryContext PortalContext = NULL; static void MemoryContextCallResetCallbacks(MemoryContext context); static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, ! MemoryContextCounters *totals); /* * You should not do memory allocations within a critical section, because --- 54,61 ---- static void MemoryContextCallResetCallbacks(MemoryContext context); static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, ! MemoryContextCounters *totals, ! FILE *file); /* * You should not do memory allocations within a critical section, because *************** *** 484,493 **** MemoryContextIsEmpty(MemoryContext context) * The statistics are sent to stderr. */ void ! MemoryContextStats(MemoryContext context) { /* A hard-wired limit on the number of children is usually good enough */ ! MemoryContextStatsDetail(context, 100); } /* --- 485,494 ---- * The statistics are sent to stderr. */ void ! MemoryContextStats(MemoryContext context, FILE *file) { /* A hard-wired limit on the number of children is usually good enough */ ! MemoryContextStatsDetail(context, 100, file); } /* *************** *** 496,510 **** MemoryContextStats(MemoryContext context) * Entry point for use if you want to vary the number of child contexts shown. */ void ! MemoryContextStatsDetail(MemoryContext context, int max_children) { MemoryContextCounters grand_totals; memset(&grand_totals, 0, sizeof(grand_totals)); ! MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals); ! fprintf(stderr, "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n", grand_totals.totalspace, grand_totals.nblocks, grand_totals.freespace, grand_totals.freechunks, --- 497,515 ---- * Entry point for use if you want to vary the number of child contexts shown. */ void ! MemoryContextStatsDetail(MemoryContext context, int max_children, FILE *file) { MemoryContextCounters grand_totals; memset(&grand_totals, 0, sizeof(grand_totals)); ! /* Default case will report to standard output*/ ! if (!file) ! file = stderr; ! MemoryContextStatsInternal(context, 0, true, max_children, &grand_totals, file); ! ! fprintf(file, "Grand total: %zu bytes in %zd blocks; %zu free (%zd chunks); %zu used\n", grand_totals.totalspace, grand_totals.nblocks, grand_totals.freespace, grand_totals.freechunks, *************** *** 521,527 **** MemoryContextStatsDetail(MemoryContext context, int max_children) static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, ! MemoryContextCounters *totals) { MemoryContextCounters local_totals; MemoryContext child; --- 526,533 ---- static void MemoryContextStatsInternal(MemoryContext context, int level, bool print, int max_children, ! MemoryContextCounters *totals, ! FILE *file) { MemoryContextCounters local_totals; MemoryContext child; *************** *** 530,536 **** MemoryContextStatsInternal(MemoryContext context, int level, AssertArg(MemoryContextIsValid(context)); /* Examine the context itself */ ! (*context->methods->stats) (context, level, print, totals); /* * Examine children. If there are more than max_children of them, we do --- 536,542 ---- AssertArg(MemoryContextIsValid(context)); /* Examine the context itself */ ! (*context->methods->stats) (context, level, print, totals, file); /* * Examine children. If there are more than max_children of them, we do *************** *** 545,555 **** MemoryContextStatsInternal(MemoryContext context, int level, if (ichild < max_children) MemoryContextStatsInternal(child, level + 1, print, max_children, ! totals); else MemoryContextStatsInternal(child, level + 1, false, max_children, ! &local_totals); } /* Deal with excess children */ --- 551,563 ---- if (ichild < max_children) MemoryContextStatsInternal(child, level + 1, print, max_children, ! totals, ! file); else MemoryContextStatsInternal(child, level + 1, false, max_children, ! &local_totals, ! file); } /* Deal with excess children */ *************** *** 560,567 **** MemoryContextStatsInternal(MemoryContext context, int level, int i; for (i = 0; i <= level; i++) ! fprintf(stderr, " "); ! fprintf(stderr, "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n", ichild - max_children, local_totals.totalspace, --- 568,575 ---- int i; for (i = 0; i <= level; i++) ! fprintf(file, " "); ! fprintf(file, "%d more child contexts containing %zu total in %zd blocks; %zu free (%zd chunks); %zu used\n", ichild - max_children, local_totals.totalspace, *************** *** 762,768 **** MemoryContextAlloc(MemoryContext context, Size size) ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 770,776 ---- ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 797,803 **** MemoryContextAllocZero(MemoryContext context, Size size) ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 805,811 ---- ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 834,840 **** MemoryContextAllocZeroAligned(MemoryContext context, Size size) ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 842,848 ---- ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 871,877 **** MemoryContextAllocExtended(MemoryContext context, Size size, int flags) { if ((flags & MCXT_ALLOC_NO_OOM) == 0) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 879,885 ---- { if ((flags & MCXT_ALLOC_NO_OOM) == 0) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 905,911 **** palloc(Size size) ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 913,919 ---- ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 934,940 **** palloc0(Size size) ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 942,948 ---- ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 968,974 **** palloc_extended(Size size, int flags) { if ((flags & MCXT_ALLOC_NO_OOM) == 0) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 976,982 ---- { if ((flags & MCXT_ALLOC_NO_OOM) == 0) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *************** *** 1081,1087 **** MemoryContextAllocHuge(MemoryContext context, Size size) ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), --- 1089,1095 ---- ret = (*context->methods->alloc) (context, size); if (ret == NULL) { ! MemoryContextStats(TopMemoryContext, NULL); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"), *** a/src/include/nodes/memnodes.h --- b/src/include/nodes/memnodes.h *************** *** 63,69 **** typedef struct MemoryContextMethods Size (*get_chunk_space) (MemoryContext context, void *pointer); bool (*is_empty) (MemoryContext context); void (*stats) (MemoryContext context, int level, bool print, ! MemoryContextCounters *totals); #ifdef MEMORY_CONTEXT_CHECKING void (*check) (MemoryContext context); #endif --- 63,69 ---- Size (*get_chunk_space) (MemoryContext context, void *pointer); bool (*is_empty) (MemoryContext context); void (*stats) (MemoryContext context, int level, bool print, ! MemoryContextCounters *totals, FILE *file); #ifdef MEMORY_CONTEXT_CHECKING void (*check) (MemoryContext context); #endif *** a/src/include/pgtime.h --- b/src/include/pgtime.h *************** *** 44,50 **** typedef struct pg_tzenum pg_tzenum; #define TZ_STRLEN_MAX 255 /* these functions are in localtime.c */ - extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz); extern struct pg_tm *pg_gmtime(const pg_time_t *timep); extern int pg_next_dst_boundary(const pg_time_t *timep, --- 44,49 ---- *************** *** 74,79 **** extern pg_tz *session_timezone; --- 73,80 ---- extern pg_tz *log_timezone; extern void pg_timezone_initialize(void); + extern pg_tz * pg_get_timezone(void); + extern pg_tz *pg_tzset(const char *tzname); extern pg_tz *pg_tzset_offset(long gmtoffset); *** a/src/include/utils/memutils.h --- b/src/include/utils/memutils.h *************** *** 103,110 **** extern Size GetMemoryChunkSpace(void *pointer); extern MemoryContext GetMemoryChunkContext(void *pointer); extern MemoryContext MemoryContextGetParent(MemoryContext context); extern bool MemoryContextIsEmpty(MemoryContext context); ! extern void MemoryContextStats(MemoryContext context); ! extern void MemoryContextStatsDetail(MemoryContext context, int max_children); extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow); --- 103,110 ---- extern MemoryContext GetMemoryChunkContext(void *pointer); extern MemoryContext MemoryContextGetParent(MemoryContext context); extern bool MemoryContextIsEmpty(MemoryContext context); ! extern void MemoryContextStats(MemoryContext context, FILE *file); ! extern void MemoryContextStatsDetail(MemoryContext context, int max_children, FILE *file); extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow); *** a/src/timezone/localtime.c --- b/src/timezone/localtime.c *************** *** 1094,1100 **** pg_localtime(const pg_time_t *timep, const pg_tz *tz) return localsub(timep, 0L, &tm, tz); } - /* * gmtsub is to gmtime as localsub is to localtime. */ --- 1094,1099 ---- *** a/src/timezone/pgtz.c --- b/src/timezone/pgtz.c *************** *** 355,360 **** pg_timezone_initialize(void) --- 355,365 ---- log_timezone = session_timezone; } + pg_tz * + pg_get_timezone(void) + { + return log_timezone; + } /* * Functions to enumerate available timezones