*** 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 <time.h>
+ #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_<process id>_<timestamp>.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
