*** ./src/backend/tsearch/dict_ispell.c.orig	2010-03-15 15:10:31.997321968 +0100
--- ./src/backend/tsearch/dict_ispell.c	2010-03-15 15:17:33.726323706 +0100
***************
*** 38,43 ****
--- 38,46 ----
  				stoploaded = false;
  	ListCell   *l;
  
+ 	MemoryContext	simple_ctx = NULL;
+ 	MemoryContext	temp_ctx = NULL;
+ 
  	d = (DictISpell *) palloc0(sizeof(DictISpell));
  
  	foreach(l, dictoptions)
***************
*** 52,58 ****
  						 errmsg("multiple DictFile parameters")));
  			NIImportDictionary(&(d->obj),
  							 get_tsearch_config_filename(defGetString(defel),
! 														 "dict"));
  			dictloaded = true;
  		}
  		else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
--- 55,63 ----
  						 errmsg("multiple DictFile parameters")));
  			NIImportDictionary(&(d->obj),
  							 get_tsearch_config_filename(defGetString(defel),
! 														 "dict"),
! 														 &simple_ctx,
! 														 &temp_ctx);
  			dictloaded = true;
  		}
  		else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
***************
*** 63,69 ****
  						 errmsg("multiple AffFile parameters")));
  			NIImportAffixes(&(d->obj),
  							get_tsearch_config_filename(defGetString(defel),
! 														"affix"));
  			affloaded = true;
  		}
  		else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
--- 68,76 ----
  						 errmsg("multiple AffFile parameters")));
  			NIImportAffixes(&(d->obj),
  							get_tsearch_config_filename(defGetString(defel),
! 														"affix"),
! 														&simple_ctx,
! 														&temp_ctx);
  			affloaded = true;
  		}
  		else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
***************
*** 86,93 ****
  
  	if (affloaded && dictloaded)
  	{
! 		NISortDictionary(&(d->obj));
! 		NISortAffixes(&(d->obj));
  	}
  	else if (!affloaded)
  	{
--- 93,100 ----
  
  	if (affloaded && dictloaded)
  	{
! 		NISortDictionary(&(d->obj), &simple_ctx, &temp_ctx);
! 		NISortAffixes(&(d->obj), &simple_ctx, &temp_ctx);
  	}
  	else if (!affloaded)
  	{
***************
*** 102,108 ****
  				 errmsg("missing DictFile parameter")));
  	}
  	
! 	MemoryContextDeleteChildren(CurrentMemoryContext);
  
  	PG_RETURN_POINTER(d);
  }
--- 109,124 ----
  				 errmsg("missing DictFile parameter")));
  	}
  	
! fprintf(stderr,"final\n");
! MemoryContextStats(CurrentMemoryContext);
! 
! 	if (temp_ctx != NULL)
! 		MemoryContextDelete(temp_ctx);
! 
! fprintf(stderr,"super final\n");
! MemoryContextStats(CurrentMemoryContext);
! 
! 
  
  	PG_RETURN_POINTER(d);
  }
*** ./src/backend/tsearch/spell.c.orig	2010-01-02 17:57:53.000000000 +0100
--- ./src/backend/tsearch/spell.c	2010-03-15 17:53:33.092448863 +0100
***************
*** 27,53 ****
   * for the short-lived stuff.
   */
  static MemoryContext tmpCtx = NULL;
  
  #define tmpalloc(sz)  MemoryContextAlloc(tmpCtx, (sz))
  #define tmpalloc0(sz)  MemoryContextAllocZero(tmpCtx, (sz))
  
  static void
! checkTmpCtx(void)
  {
  	/*
  	 * XXX: This assumes that CurrentMemoryContext doesn't have any children
  	 * other than the one we create here.
  	 */
! 	if (CurrentMemoryContext->firstchild == NULL)
  	{
! 		tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
  									   "Ispell dictionary init context",
  									   ALLOCSET_DEFAULT_MINSIZE,
  									   ALLOCSET_DEFAULT_INITSIZE,
  									   ALLOCSET_DEFAULT_MAXSIZE);
  	}
  	else
! 		tmpCtx = CurrentMemoryContext->firstchild;
  }
  
  static char *
--- 27,69 ----
   * for the short-lived stuff.
   */
  static MemoryContext tmpCtx = NULL;
+ static MemoryContext simple_tmpCtx = NULL;
  
  #define tmpalloc(sz)  MemoryContextAlloc(tmpCtx, (sz))
  #define tmpalloc0(sz)  MemoryContextAllocZero(tmpCtx, (sz))
  
+ #define tmp_simple_alloc(sz)  MemoryContextAlloc(simple_tmpCtx, (sz))
+ #define tmp_simple_alloc0(sz)  MemoryContextAllocZero(simple_tmpCtx, (sz))
+ 
+ 
+ 
  static void
! checkTmpCtx(MemoryContext *temp_ctx)
  {
  	/*
  	 * XXX: This assumes that CurrentMemoryContext doesn't have any children
  	 * other than the one we create here.
  	 */
! 	if (*temp_ctx == NULL)
  	{
! 		*temp_ctx = AllocSetContextCreate(CurrentMemoryContext,
  									   "Ispell dictionary init context",
  									   ALLOCSET_DEFAULT_MINSIZE,
  									   ALLOCSET_DEFAULT_INITSIZE,
  									   ALLOCSET_DEFAULT_MAXSIZE);
+ 		tmpCtx = *temp_ctx;
+ 		
+ 		simple_tmpCtx = SimpleAllocContextCreate(tmpCtx,
+ 										"Ispell dictionary simple init context",
+ 										SIMPLEALLOC_LARGE_INITSIZE,
+ 										malloc,
+ 										free);
  	}
  	else
! 	{
! 		tmpCtx = *temp_ctx;
! 		simple_tmpCtx = tmpCtx->firstchild;
! 	}
  }
  
  static char *
***************
*** 179,185 ****
  			Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *));
  		}
  	}
! 	Conf->Spell[Conf->nspell] = (SPELL *) tmpalloc(SPELLHDRSZ + strlen(word) + 1);
  	strcpy(Conf->Spell[Conf->nspell]->word, word);
  	strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN);
  	Conf->nspell++;
--- 195,201 ----
  			Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *));
  		}
  	}
! 	Conf->Spell[Conf->nspell] = (SPELL *) tmp_simple_alloc(SPELLHDRSZ + strlen(word) + 1);
  	strcpy(Conf->Spell[Conf->nspell]->word, word);
  	strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN);
  	Conf->nspell++;
***************
*** 191,202 ****
   * Note caller must already have applied get_tsearch_config_filename
   */
  void
! NIImportDictionary(IspellDict *Conf, const char *filename)
  {
  	tsearch_readline_state trst;
  	char	   *line;
  
! 	checkTmpCtx();
  
  	if (!tsearch_readline_begin(&trst, filename))
  		ereport(ERROR,
--- 207,218 ----
   * Note caller must already have applied get_tsearch_config_filename
   */
  void
! NIImportDictionary(IspellDict *Conf, const char *filename, MemoryContext *simple_ctx, MemoryContext *temp_ctx)
  {
  	tsearch_readline_state trst;
  	char	   *line;
  
! 	checkTmpCtx(temp_ctx);
  
  	if (!tsearch_readline_begin(&trst, filename))
  		ereport(ERROR,
***************
*** 344,357 ****
  
  		Affix->issimple = 0;
  		Affix->isregis = 0;
! 		tmask = (char *) tmpalloc(strlen(mask) + 3);
  		if (type == FF_SUFFIX)
  			sprintf(tmask, "%s$", mask);
  		else
  			sprintf(tmask, "^%s", mask);
  
  		masklen = strlen(tmask);
! 		wmask = (pg_wchar *) tmpalloc((masklen + 1) * sizeof(pg_wchar));
  		wmasklen = pg_mb2wchar_with_len(tmask, wmask, masklen);
  
  		err = pg_regcomp(&(Affix->reg.regex), wmask, wmasklen, REG_ADVANCED | REG_NOSUB);
--- 360,373 ----
  
  		Affix->issimple = 0;
  		Affix->isregis = 0;
! 		tmask = (char *) tmp_simple_alloc(strlen(mask) + 3);
  		if (type == FF_SUFFIX)
  			sprintf(tmask, "%s$", mask);
  		else
  			sprintf(tmask, "^%s", mask);
  
  		masklen = strlen(tmask);
! 		wmask = (pg_wchar *) tmp_simple_alloc((masklen + 1) * sizeof(pg_wchar));
  		wmasklen = pg_mb2wchar_with_len(tmask, wmask, masklen);
  
  		err = pg_regcomp(&(Affix->reg.regex), wmask, wmasklen, REG_ADVANCED | REG_NOSUB);
***************
*** 526,532 ****
  }
  
  static void
! NIImportOOAffixes(IspellDict *Conf, const char *filename)
  {
  	char		type[BUFSIZ],
  			   *ptype = NULL;
--- 542,548 ----
  }
  
  static void
! NIImportOOAffixes(IspellDict *Conf, const char *filename, MemoryContext *simple_ctx, MemoryContext *temp_ctx)
  {
  	char		type[BUFSIZ],
  			   *ptype = NULL;
***************
*** 545,551 ****
  	char		scanbuf[BUFSIZ];
  	char	   *recoded;
  
! 	checkTmpCtx();
  
  	/* read file to find any flag */
  	memset(Conf->flagval, 0, sizeof(Conf->flagval));
--- 561,567 ----
  	char		scanbuf[BUFSIZ];
  	char	   *recoded;
  
! 	checkTmpCtx(temp_ctx);
  
  	/* read file to find any flag */
  	memset(Conf->flagval, 0, sizeof(Conf->flagval));
***************
*** 687,693 ****
   * Note caller must already have applied get_tsearch_config_filename
   */
  void
! NIImportAffixes(IspellDict *Conf, const char *filename)
  {
  	char	   *pstr = NULL;
  	char		mask[BUFSIZ];
--- 703,709 ----
   * Note caller must already have applied get_tsearch_config_filename
   */
  void
! NIImportAffixes(IspellDict *Conf, const char *filename, MemoryContext *simple_ctx, MemoryContext *temp_ctx)
  {
  	char	   *pstr = NULL;
  	char		mask[BUFSIZ];
***************
*** 702,708 ****
  	bool		oldformat = false;
  	char	   *recoded = NULL;
  
! 	checkTmpCtx();
  
  	if (!tsearch_readline_begin(&trst, filename))
  		ereport(ERROR,
--- 718,724 ----
  	bool		oldformat = false;
  	char	   *recoded = NULL;
  
! 	checkTmpCtx(temp_ctx);
  
  	if (!tsearch_readline_begin(&trst, filename))
  		ereport(ERROR,
***************
*** 802,808 ****
  						(errcode(ERRCODE_CONFIG_FILE_ERROR),
  						 errmsg("wrong affix file format for flag")));
  			tsearch_readline_end(&trst);
! 			NIImportOOAffixes(Conf, filename);
  			return;
  		}
  		if ((!suffixes) && (!prefixes))
--- 818,824 ----
  						(errcode(ERRCODE_CONFIG_FILE_ERROR),
  						 errmsg("wrong affix file format for flag")));
  			tsearch_readline_end(&trst);
! 			NIImportOOAffixes(Conf, filename, simple_ctx, temp_ctx);
  			return;
  		}
  		if ((!suffixes) && (!prefixes))
***************
*** 859,865 ****
  }
  
  static SPNode *
! mkSPNode(IspellDict *Conf, int low, int high, int level)
  {
  	int			i;
  	int			nchar = 0;
--- 875,881 ----
  }
  
  static SPNode *
! mkSPNode(IspellDict *Conf, int low, int high, int level, MemoryContext simple_ctx)
  {
  	int			i;
  	int			nchar = 0;
***************
*** 878,884 ****
  	if (!nchar)
  		return NULL;
  
! 	rs = (SPNode *) palloc0(SPNHDRSZ + nchar * sizeof(SPNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
--- 894,901 ----
  	if (!nchar)
  		return NULL;
  
! 	rs = (SPNode *) MemoryContextAllocZero(simple_ctx, 
! 							   SPNHDRSZ + nchar * sizeof(SPNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
***************
*** 890,896 ****
  			{
  				if (lastchar)
  				{
! 					data->node = mkSPNode(Conf, lownew, i, level + 1);
  					lownew = i;
  					data++;
  				}
--- 907,913 ----
  			{
  				if (lastchar)
  				{
! 					data->node = mkSPNode(Conf, lownew, i, level + 1, simple_ctx);
  					lownew = i;
  					data++;
  				}
***************
*** 929,935 ****
  			}
  		}
  
! 	data->node = mkSPNode(Conf, lownew, high, level + 1);
  
  	return rs;
  }
--- 946,952 ----
  			}
  		}
  
! 	data->node = mkSPNode(Conf, lownew, high, level + 1, simple_ctx);
  
  	return rs;
  }
***************
*** 939,951 ****
   * and affixes.
   */
  void
! NISortDictionary(IspellDict *Conf)
  {
  	int			i;
  	int			naffix = 0;
  	int			curaffix;
  
! 	checkTmpCtx();
  
  	/* compress affixes */
  
--- 956,968 ----
   * and affixes.
   */
  void
! NISortDictionary(IspellDict *Conf, MemoryContext *simple_ctx, MemoryContext *temp_ctx)
  {
  	int			i;
  	int			naffix = 0;
  	int			curaffix;
  
! 	checkTmpCtx(temp_ctx);
  
  	/* compress affixes */
  
***************
*** 959,971 ****
  		if (i == 0 || strncmp(Conf->Spell[i]->p.flag, Conf->Spell[i - 1]->p.flag, MAXFLAGLEN))
  			naffix++;
  	}
  
  	/*
  	 * Fill in Conf->AffixData with the affixes that were used in the
  	 * dictionary. Replace textual flag-field of Conf->Spell entries with
  	 * indexes into Conf->AffixData array.
  	 */
! 	Conf->AffixData = (char **) palloc0(naffix * sizeof(char *));
  
  	curaffix = -1;
  	for (i = 0; i < Conf->nspell; i++)
--- 976,1000 ----
  		if (i == 0 || strncmp(Conf->Spell[i]->p.flag, Conf->Spell[i - 1]->p.flag, MAXFLAGLEN))
  			naffix++;
  	}
+ 	
+ 	if (*simple_ctx == NULL)
+ 	{
+ 		/* create simple alloc memory context */
+ 		*simple_ctx = SimpleAllocContextCreate(CurrentMemoryContext,
+ 										"Ispell dictionary simple context",
+ 										SIMPLEALLOC_LARGE_INITSIZE,
+ 										malloc,
+ 										free);
+ 	}
  
  	/*
  	 * Fill in Conf->AffixData with the affixes that were used in the
  	 * dictionary. Replace textual flag-field of Conf->Spell entries with
  	 * indexes into Conf->AffixData array.
  	 */
! 	
! 	Conf->AffixData = (char **) palloc0(naffix * sizeof(char *)); 
! 	/* cannot move to simple context now ^ */
  
  	curaffix = -1;
  	for (i = 0; i < Conf->nspell; i++)
***************
*** 974,979 ****
--- 1003,1009 ----
  		{
  			curaffix++;
  			Assert(curaffix < naffix);
+ 			/* can't be moved to simple alloc context now */
  			Conf->AffixData[curaffix] = pstrdup(Conf->Spell[i]->p.flag);
  		}
  
***************
*** 984,996 ****
  	Conf->lenAffixData = Conf->nAffixData = naffix;
  
  	qsort((void *) Conf->Spell, Conf->nspell, sizeof(SPELL *), cmpspell);
! 	Conf->Dictionary = mkSPNode(Conf, 0, Conf->nspell, 0);
  
  	Conf->Spell = NULL;
  }
  
  static AffixNode *
! mkANode(IspellDict *Conf, int low, int high, int level, int type)
  {
  	int			i;
  	int			nchar = 0;
--- 1014,1026 ----
  	Conf->lenAffixData = Conf->nAffixData = naffix;
  
  	qsort((void *) Conf->Spell, Conf->nspell, sizeof(SPELL *), cmpspell);
! 	Conf->Dictionary = mkSPNode(Conf, 0, Conf->nspell, 0, *simple_ctx);
  
  	Conf->Spell = NULL;
  }
  
  static AffixNode *
! mkANode(IspellDict *Conf, int low, int high, int level, int type, MemoryContext simple_ctx)
  {
  	int			i;
  	int			nchar = 0;
***************
*** 1014,1020 ****
  	aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1));
  	naff = 0;
  
! 	rs = (AffixNode *) palloc0(ANHRDSZ + nchar * sizeof(AffixNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
--- 1044,1052 ----
  	aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1));
  	naff = 0;
  
! 	rs = (AffixNode *) MemoryContextAllocZero(simple_ctx, 
! 							   ANHRDSZ + nchar * sizeof(AffixNodeData));
! 
  	rs->length = nchar;
  	data = rs->data;
  
***************
*** 1026,1036 ****
  			{
  				if (lastchar)
  				{
! 					data->node = mkANode(Conf, lownew, i, level + 1, type);
  					if (naff)
  					{
  						data->naff = naff;
! 						data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff);
  						memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  						naff = 0;
  					}
--- 1058,1068 ----
  			{
  				if (lastchar)
  				{
! 					data->node = mkANode(Conf, lownew, i, level + 1, type, simple_ctx);
  					if (naff)
  					{
  						data->naff = naff;
! 						data->aff = (AFFIX **) MemoryContextAlloc(simple_ctx, sizeof(AFFIX *) * naff);
  						memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  						naff = 0;
  					}
***************
*** 1046,1056 ****
  			}
  		}
  
! 	data->node = mkANode(Conf, lownew, high, level + 1, type);
  	if (naff)
  	{
  		data->naff = naff;
! 		data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff);
  		memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  		naff = 0;
  	}
--- 1078,1088 ----
  			}
  		}
  
! 	data->node = mkANode(Conf, lownew, high, level + 1, type, simple_ctx);
  	if (naff)
  	{
  		data->naff = naff;
! 		data->aff = (AFFIX **) MemoryContextAlloc(simple_ctx, sizeof(AFFIX *) * naff);
  		memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  		naff = 0;
  	}
***************
*** 1061,1073 ****
  }
  
  static void
! mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix)
  {
  	int			i,
  				cnt = 0;
  	int			start = (issuffix) ? startsuffix : 0;
  	int			end = (issuffix) ? Conf->naffixes : startsuffix;
! 	AffixNode  *Affix = (AffixNode *) palloc0(ANHRDSZ + sizeof(AffixNodeData));
  
  	Affix->length = 1;
  	Affix->isvoid = 1;
--- 1093,1107 ----
  }
  
  static void
! mkVoidAffix(IspellDict *Conf, bool issuffix, int startsuffix, MemoryContext simple_ctx)
  {
  	int			i,
  				cnt = 0;
  	int			start = (issuffix) ? startsuffix : 0;
  	int			end = (issuffix) ? Conf->naffixes : startsuffix;
! 	//AffixNode  *Affix = (AffixNode *) palloc0(ANHRDSZ + sizeof(AffixNodeData));
! 
! 	AffixNode  *Affix = (AffixNode *) MemoryContextAllocZero(simple_ctx, ANHRDSZ + sizeof(AffixNodeData));
  
  	Affix->length = 1;
  	Affix->isvoid = 1;
***************
*** 1091,1097 ****
  	if (cnt == 0)
  		return;
  
! 	Affix->data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * cnt);
  	Affix->data->naff = (uint32) cnt;
  
  	cnt = 0;
--- 1125,1131 ----
  	if (cnt == 0)
  		return;
  
! 	Affix->data->aff = (AFFIX **) MemoryContextAllocZero(simple_ctx, sizeof(AFFIX *) * cnt);
  	Affix->data->naff = (uint32) cnt;
  
  	cnt = 0;
***************
*** 1116,1129 ****
  }
  
  void
! NISortAffixes(IspellDict *Conf)
  {
  	AFFIX	   *Affix;
  	size_t		i;
  	CMPDAffix  *ptr;
  	int			firstsuffix = Conf->naffixes;
  
! 	checkTmpCtx();
  
  	if (Conf->naffixes == 0)
  		return;
--- 1150,1173 ----
  }
  
  void
! NISortAffixes(IspellDict *Conf, MemoryContext *simple_ctx, MemoryContext *temp_ctx)
  {
  	AFFIX	   *Affix;
  	size_t		i;
  	CMPDAffix  *ptr;
  	int			firstsuffix = Conf->naffixes;
  
! 	checkTmpCtx(temp_ctx);
! 
! 	if (*simple_ctx == NULL)
! 	{
! 		/* create simple alloc memory context */
! 		*simple_ctx = SimpleAllocContextCreate(CurrentMemoryContext,
! 										"Ispell dictionary simple context",
! 										SIMPLEALLOC_LARGE_INITSIZE,
! 										malloc,
! 										free);
! 	}
  
  	if (Conf->naffixes == 0)
  		return;
***************
*** 1159,1168 ****
  	ptr->affix = NULL;
  	Conf->CompoundAffix = (CMPDAffix *) repalloc(Conf->CompoundAffix, sizeof(CMPDAffix) * (ptr - Conf->CompoundAffix + 1));
  
! 	Conf->Prefix = mkANode(Conf, 0, firstsuffix, 0, FF_PREFIX);
! 	Conf->Suffix = mkANode(Conf, firstsuffix, Conf->naffixes, 0, FF_SUFFIX);
! 	mkVoidAffix(Conf, true, firstsuffix);
! 	mkVoidAffix(Conf, false, firstsuffix);
  }
  
  static AffixNodeData *
--- 1203,1212 ----
  	ptr->affix = NULL;
  	Conf->CompoundAffix = (CMPDAffix *) repalloc(Conf->CompoundAffix, sizeof(CMPDAffix) * (ptr - Conf->CompoundAffix + 1));
  
! 	Conf->Prefix = mkANode(Conf, 0, firstsuffix, 0, FF_PREFIX, *simple_ctx);
! 	Conf->Suffix = mkANode(Conf, firstsuffix, Conf->naffixes, 0, FF_SUFFIX, *simple_ctx);
! 	mkVoidAffix(Conf, true, firstsuffix, *simple_ctx);
! 	mkVoidAffix(Conf, false, firstsuffix, *simple_ctx);
  }
  
  static AffixNodeData *
*** ./src/backend/utils/mmgr/Makefile.orig	2008-02-19 11:30:09.000000000 +0100
--- ./src/backend/utils/mmgr/Makefile	2010-03-15 11:03:16.738323659 +0100
***************
*** 12,17 ****
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = aset.o mcxt.o portalmem.o
  
  include $(top_srcdir)/src/backend/common.mk
--- 12,17 ----
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = aset.o mcxt.o portalmem.o simple_alloc.o
  
  include $(top_srcdir)/src/backend/common.mk
*** ./src/backend/utils/mmgr/simple_alloc.c.orig	2010-03-15 11:02:48.741323741 +0100
--- ./src/backend/utils/mmgr/simple_alloc.c	2010-03-15 14:32:40.009321969 +0100
***************
*** 0 ****
--- 1,308 ----
+ #include "postgres.h"
+ 
+ #include "utils/memutils.h"
+ 
+ typedef struct AllocBlockData *AllocBlock;		/* forward reference */
+ 
+ 
+ typedef struct SimpleAllocContextData
+ {
+ 	MemoryContextData header;	/* Standard memory-context fields */
+ 	AllocBlock	blocks;		/* head of list of blocks */
+ 	bool	isReset;
+ 	/* Allocation parameters for this context */
+ 	Size initBlockSize;
+ 	void *(*external_alloc) (Size size);	/* allocate memory */
+ 	void (*external_free) (void *);		/* deallocate memory */
+ } SimpleAllocContextData;
+ 
+ typedef SimpleAllocContextData *SimpleAlloc;
+ 
+ typedef struct AllocBlockData
+ {
+ 	AllocBlock	next;
+ 	Size 	   freesize;
+ 	char	   *freeptr;
+ 	char	data[1];
+ } AllocBlockData;
+ 
+ #define SimpleAllocCtxIsValid(ctx)	PointerIsValid(ctx);
+ 
+ static void SimpleAllocInit(MemoryContext context);
+ static void SimpleAllocReset(MemoryContext context);
+ static void SimpleAllocDelete(MemoryContext context);
+ static void *SimpleAllocAlloc(MemoryContext context, Size size);
+ static void SimpleAllocStats(MemoryContext context, int level);
+ static void *SimpleAllocRealloc(MemoryContext context, void *pointer, Size size);
+ static void SimpleAllocFree(MemoryContext context, void *pointer);
+ static bool SimpleAllocIsEmpty(MemoryContext context);
+ static Size SimpleAllocGetChunkSpace(MemoryContext context, void *pointer);
+ 
+ #ifdef MEMORY_CONTEXT_CHECKING
+ static void SimpleAllocCheck(MemoryContext context);
+ #endif
+ 
+ /*
+  * This is the virtual function table for SimpleAlloc context
+  */
+ static MemoryContextMethods SimpleAllocMethods = {
+ 	SimpleAllocAlloc,
+ 	SimpleAllocFree,				/* not supported */
+ 	SimpleAllocRealloc,				/* not supported */
+ 	SimpleAllocInit,
+ 	SimpleAllocReset,
+ 	SimpleAllocDelete,
+ 	SimpleAllocGetChunkSpace,			/* not supported */
+ 	SimpleAllocIsEmpty,
+ 	SimpleAllocStats
+ #ifdef MEMORY_CONTEXT_CHECKING
+ 	, SimpleAllocCheck
+ #endif
+ };
+ 
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
+ 
+ /*
+  * Fill a just-allocated piece of memory with "random" data.  It's not really
+  * very random, just a repeating sequence with a length that's prime.  What
+  * we mainly want out of it is to have a good probability that two palloc's
+  * of the same number of bytes start out containing different data.
+  */
+ static void
+ randomize_mem(char *ptr, size_t size)
+ {
+ 	static int	save_ctr = 1;
+ 	int			ctr;
+ 
+ 	ctr = save_ctr;
+ 	while (size-- > 0)
+ 	{
+ 		*ptr++ = ctr;
+ 		if (++ctr > 251)
+ 			ctr = 1;
+ 	}
+ 	save_ctr = ctr;
+ }
+ #endif   /* RANDOMIZE_ALLOCATED_MEMORY */
+ 
+ /*
+  * SimpleAllocContextCreate 
+  *
+  *
+  */
+ MemoryContext
+ SimpleAllocContextCreate(MemoryContext parent,
+ 					      const char *name,
+ 					      Size initBlockSize,
+ 					      void *(*external_alloc) (Size size),
+ 					      void (*external_free) (void *))
+ {
+ 	SimpleAlloc	context;
+ 	
+ 	context = (SimpleAlloc) MemoryContextCreate(T_SimpleAllocContext,
+ 										sizeof(SimpleAllocContextData),
+ 										&SimpleAllocMethods,
+ 										parent,
+ 										name);
+ 	context->initBlockSize = initBlockSize;
+ 	context->external_alloc = external_alloc;
+ 	context->external_free = external_free;
+ 	
+ 	context->blocks = NULL;
+ 	context->isReset = true;
+ 	
+ 	return (MemoryContext) context;
+ }
+ 
+ /* 
+  * Context type methods 
+  */
+ static void
+ SimpleAllocInit(MemoryContext context)
+ {
+ 	/*
+ 	 * do nothing
+ 	 */
+ }
+ 
+ static void
+ SimpleAllocReset(MemoryContext context)
+ {
+ 	AllocBlock	block;
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	
+ 	Assert(SimpleAllocCtxIsValid(simple_ctx));
+ 	
+ 	block = simple_ctx->blocks;
+ 	
+ 	/*
+ 	 * reset all allocated memory
+ 	 */
+ 	while (block != NULL)
+ 	{
+ 		block->freesize = simple_ctx->initBlockSize;
+ 		block->freeptr = block->data;
+ 		
+ #ifdef CLOBBER_FREED_MEMORY
+ 		memset(block->freeptr, 0x7F, simple_ctx->initBlockSize);
+ #endif
+ 		block = block->next;
+ 	}
+ 	simple_ctx->isReset = true;
+ }
+ 
+ static void
+ SimpleAllocDelete(MemoryContext context)
+ {
+ 	AllocBlock	block;
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	
+ 	Assert(SimpleAllocCtxIsValid(simple_ctx));
+ 	
+ 	block = simple_ctx->blocks;
+ 	
+ 	/*
+ 	 * reset all allocated memory
+ 	 */
+ 	while (block != NULL)
+ 	{
+ 		AllocBlock	next = block->next;
+ 		
+ 		block->freesize = simple_ctx->initBlockSize;
+ 		block->freeptr = block->data;
+ 		
+ #ifdef CLOBBER_FREED_MEMORY
+ 		memset(block->freeptr, 0x7F, simple_ctx->initBlockSize);
+ #endif
+ 		if (simple_ctx->external_free != NULL)
+ 			simple_ctx->external_free(block);
+ 		else
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 					 errmsg("cannot release allocated memory")));
+ 		block = next;
+ 	}
+ 	
+ 	simple_ctx->blocks = NULL;
+ 	simple_ctx->isReset = true;
+ }
+ 
+ static void *
+ SimpleAllocAlloc(MemoryContext context, Size size)
+ {
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	AllocBlock   block;
+ 	void	*newPointer;
+ 
+ 	Assert(SimpleAllocCtxIsValid(simple_ctx));
+ 	
+ 	if (size > simple_ctx->initBlockSize)
+ 		ereport(ERROR,
+ 			(errcode(ERRCODE_OUT_OF_MEMORY),
+ 			 errmsg("out of memory"),
+ 				 errdetail("simple allocator cannot allocate larger block than is  initial size")));
+ 	
+ 	if (simple_ctx->blocks == NULL || (simple_ctx->blocks && simple_ctx->blocks->freesize < size))
+ 	{
+ 		/* alloc a new block */
+ 		block = simple_ctx->external_alloc(simple_ctx->initBlockSize + sizeof(AllocBlockData) - 1);
+ 		if (block == NULL)
+ 		{
+ 			MemoryContextStats(TopMemoryContext);
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_OUT_OF_MEMORY),
+ 					 errmsg("out of memory"),
+ 					 errdetail("Failed on request of size %lu.",
+ 							   (unsigned long) simple_ctx->initBlockSize + sizeof(AllocBlockData) - 1)));
+ 		}
+ 		block->freesize = simple_ctx->initBlockSize;
+ 		block->freeptr = block->data;
+ 		block->next = simple_ctx->blocks;
+ 		simple_ctx->blocks = block;
+ 	}
+ 	else
+ 		block = simple_ctx->blocks;
+ 	
+ 	Assert(size > block->freesize)
+ 	newPointer = block->freeptr;
+ 	block->freeptr += size;
+ 	block->freesize -= size;
+ 	
+ #ifdef RANDOMIZE_ALLOCATED_MEMORY
+ 	randomize_mem((char *) newPointer, size);
+ #endif
+ 	simple_ctx->isReset = false;
+ 
+ 	return newPointer;
+ }
+ 
+ /*
+  * SimpleAllocStats
+  */
+ static void
+ SimpleAllocStats(MemoryContext context, int level)
+ {
+ 	SimpleAlloc simple_ctx = (SimpleAlloc) context;
+ 	AllocBlock	block;
+ 	long nblocks = 0;
+ 	long	totalspace = 0;
+ 	long	freespace = 0;
+ 	int		i;
+ 	
+ 	
+ 	for (block = simple_ctx->blocks; block != NULL; block = block->next)
+ 	{
+ 		nblocks++;
+ 		totalspace += simple_ctx->initBlockSize + sizeof(AllocBlockData) - 1;
+ 		freespace += block->freesize;
+ 	}
+ 	
+ 	for (i = 0; i < level; i++)
+ 		fprintf(stderr, "  ");
+ 
+ 	fprintf(stderr,
+ 			"%s: %lu total in %ld blocks; %lu free; %lu used\n",
+ 			simple_ctx->header.name, totalspace, nblocks, freespace, 
+ 										totalspace - freespace);
+ }
+ 
+ static void *
+ SimpleAllocRealloc(MemoryContext context, void *pointer, Size size)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator can't realloc memory")));
+ 	return NULL;		/* be compiler quite */
+ }
+ 
+ static void
+ SimpleAllocFree(MemoryContext context, void *pointer)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator can't release memory")));
+ }
+ 
+ static bool
+ SimpleAllocIsEmpty(MemoryContext context)
+ {
+ 	return ((SimpleAlloc) context)->isReset;
+ }
+ 
+ static Size
+ SimpleAllocGetChunkSpace(MemoryContext context, void *pointer)
+ {
+ 	ereport(ERROR,
+ 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 			 errmsg("simple allocator has not chunks")));
+ 	return 0;		/* be compile quite */
+ }
+ 
+ #ifdef MEMORY_CONTEXT_CHECKING
+ static void
+ SimpleAllocCheck(MemoryContext context)
+ {
+ 	/* do nothing */
+ }
+ 
+ #endif
*** ./src/include/nodes/memnodes.h.orig	2010-01-02 17:58:04.000000000 +0100
--- ./src/include/nodes/memnodes.h	2010-03-15 14:07:38.597323708 +0100
***************
*** 72,77 ****
   */
  #define MemoryContextIsValid(context) \
  	((context) != NULL && \
! 	 (IsA((context), AllocSetContext)))
  
  #endif   /* MEMNODES_H */
--- 72,77 ----
   */
  #define MemoryContextIsValid(context) \
  	((context) != NULL && \
! 	 (IsA((context), AllocSetContext) || IsA((context), SimpleAllocContext)))
  
  #endif   /* MEMNODES_H */
*** ./src/include/nodes/nodes.h.orig	2010-01-05 22:53:59.000000000 +0100
--- ./src/include/nodes/nodes.h	2010-03-15 14:06:20.021447204 +0100
***************
*** 234,239 ****
--- 234,240 ----
  	 */
  	T_MemoryContext = 600,
  	T_AllocSetContext,
+ 	T_SimpleAllocContext,
  
  	/*
  	 * TAGS FOR VALUE NODES (value.h)
*** ./src/include/tsearch/dicts/spell.h.orig	2010-01-02 17:58:09.000000000 +0100
--- ./src/include/tsearch/dicts/spell.h	2010-03-15 15:16:21.662447289 +0100
***************
*** 161,169 ****
  } IspellDict;
  
  extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word);
! extern void NIImportAffixes(IspellDict *Conf, const char *filename);
! extern void NIImportDictionary(IspellDict *Conf, const char *filename);
! extern void NISortDictionary(IspellDict *Conf);
! extern void NISortAffixes(IspellDict *Conf);
  
  #endif
--- 161,169 ----
  } IspellDict;
  
  extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word);
! extern void NIImportAffixes(IspellDict *Conf, const char *filename, MemoryContext *simple_ctx, MemoryContext *temp_ctx);
! extern void NIImportDictionary(IspellDict *Conf, const char *filename, MemoryContext *simple_ctx, MemoryContext *temp_ctx);
! extern void NISortDictionary(IspellDict *Conf, MemoryContext *simple_ctx, MemoryContext *temp_ctx);
! extern void NISortAffixes(IspellDict *Conf, MemoryContext *simple_ctx, MemoryContext *temp_ctx);
  
  #endif
*** ./src/include/utils/memutils.h.orig	2010-03-15 14:33:58.000000000 +0100
--- ./src/include/utils/memutils.h	2010-03-15 16:20:24.280321906 +0100
***************
*** 136,139 ****
--- 136,147 ----
  #define ALLOCSET_SMALL_INITSIZE  (1 * 1024)
  #define ALLOCSET_SMALL_MAXSIZE	 (8 * 1024)
  
+ extern MemoryContext SimpleAllocContextCreate(MemoryContext parent,
+ 					      const char *name,
+ 					      Size initBlockSize,
+ 					      void *(*external_alloc) (Size size),
+ 					      void (*external_free) (void *));
+ 
+ #define SIMPLEALLOC_LARGE_INITSIZE	(1024 * 128)
+ 
  #endif   /* MEMUTILS_H */
