*** ./src/backend/tsearch/regis.c.orig	2010-07-14 11:47:33.068437888 +0200
--- ./src/backend/tsearch/regis.c	2010-07-14 14:32:47.157437908 +0200
***************
*** 16,27 ****
--- 16,34 ----
  
  #include "tsearch/dicts/regis.h"
  #include "tsearch/ts_locale.h"
+ #include "tsearch/dicts/spell.h"
  
  #define RS_IN_ONEOF 1
  #define RS_IN_ONEOF_IN	2
  #define RS_IN_NONEOF	3
  #define RS_IN_WAIT	4
  
+ extern AllocOnlyBlocksData aob;
+ 
+ #define aoalloc(sz)	ao_alloc(&aob, (sz), false)
+ #define aoalloc0(sz)	 ao_alloc(&aob, (sz), true)
+ #define aostrdup(str)	ao_strdup(&aob, (str))
+ 
  /*
   * Test whether a regex is of the subset supported here.
   * Keep this in sync with RS_compile!
***************
*** 74,80 ****
  {
  	RegisNode  *ptr;
  
! 	ptr = (RegisNode *) palloc0(RNHDRSZ + len + 1);
  	if (prev)
  		prev->next = ptr;
  	return ptr;
--- 81,87 ----
  {
  	RegisNode  *ptr;
  
! 	ptr = (RegisNode *) aoalloc0(RNHDRSZ + len + 1);
  	if (prev)
  		prev->next = ptr;
  	return ptr;
*** ./src/backend/tsearch/spell.c.orig	2010-01-02 17:57:53.000000000 +0100
--- ./src/backend/tsearch/spell.c	2010-07-14 14:46:06.513562368 +0200
***************
*** 28,36 ****
--- 28,97 ----
   */
  static MemoryContext tmpCtx = NULL;
  
+ #define ALLOC_ONLY_MAXSIZE	512
+ 
+ AllocOnlyBlocksData	aob;
+ AllocOnlyBlocksData	tmpaob;
+ 
  #define tmpalloc(sz)  MemoryContextAlloc(tmpCtx, (sz))
  #define tmpalloc0(sz)  MemoryContextAllocZero(tmpCtx, (sz))
  
+ #define aoalloc(sz)	ao_alloc(&aob, (sz), false)
+ #define aoalloc0(sz)	 ao_alloc(&aob, (sz), true)
+ #define aostrdup(str)	ao_strdup(&aob, (str))
+ 
+ #define aotmpalloc(sz)	ao_alloc(&tmpaob, (sz), false)
+ #define aotpmalloc0(sz)	 ao_alloc(&tmpaob, (sz), true)
+ #define aotmpstrdup(str)	ao_strdup(&tmpaob, (str))
+ 
+ /* 
+  * Ispell dictionary uses a thousands small blocks and because
+  * doesn't release these blocks, we can save lot of memory via
+  * sharing mcxt blocks.
+  */
+ char *
+ ao_alloc(AllocOnlyBlocksData *aob, Size size, bool fillzero)
+ {
+ 	char *ptr;
+ 
+ 	size = MAXALIGN(size);
+ 	
+ 	/* 
+ 	 * for "larger" blocks use a mcxt allocator. It is simple
+ 	 * mechanism to ensure a well fragmentation of alloc only
+ 	 * blocks.
+ 	 */
+ 	if (size > ALLOC_ONLY_MAXSIZE)
+ 		return fillzero ? MemoryContextAllocZero(aob->ctx, size) : MemoryContextAlloc(aob->ctx, size);
+ 	
+ 	if (size > aob->freesize)
+ 	{
+ 		aob->freeptr = MemoryContextAlloc(aob->ctx, ALLOCSET_DEFAULT_INITSIZE);
+ 		aob->freesize = ALLOCSET_DEFAULT_INITSIZE;
+ 	}
+ 	
+ 	ptr = aob->freeptr;
+ 	aob->freeptr += size;
+ 	aob->freesize -= size;
+ 	
+ 	if (fillzero)
+ 		memset(ptr, 0, size);
+ 	
+ 	return ptr;
+ }
+ 
+ char *
+ ao_strdup(AllocOnlyBlocksData *aob, const char *string)
+ {
+ 	char *nstr;
+ 	Size 	len = strlen(string) + 1;
+ 	
+ 	nstr = (char *) ao_alloc(aob, len, false);
+ 	memcpy(nstr, string, len);;
+ 	
+ 	return nstr;
+ }
+ 
  static void
  checkTmpCtx(void)
  {
***************
*** 48,53 ****
--- 109,120 ----
  	}
  	else
  		tmpCtx = CurrentMemoryContext->firstchild;
+ 	
+ 	tmpaob.ctx = tmpCtx;
+ 	tmpaob.freesize = 0;
+ 	
+ 	aob.ctx = CurrentMemoryContext;
+ 	aob.freesize = 0;
  }
  
  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++;
--- 246,253 ----
  			Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *));
  		}
  	}
! 	
! 	Conf->Spell[Conf->nspell] = (SPELL *) aotmpalloc(SPELLHDRSZ + strlen(word) + 1);
  	strcpy(Conf->Spell[Conf->nspell]->word, word);
  	strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN);
  	Conf->nspell++;
***************
*** 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);
--- 412,425 ----
  
  		Affix->issimple = 0;
  		Affix->isregis = 0;
! 		tmask = (char *) aotmpalloc(strlen(mask) + 3);
  		if (type == FF_SUFFIX)
  			sprintf(tmask, "%s$", mask);
  		else
  			sprintf(tmask, "^%s", mask);
  
  		masklen = strlen(tmask);
! 		wmask = (pg_wchar *) aotmpalloc((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);
***************
*** 375,383 ****
  	Affix->flag = flag;
  	Affix->type = type;
  
! 	Affix->find = (find && *find) ? pstrdup(find) : VoidString;
  	if ((Affix->replen = strlen(repl)) > 0)
! 		Affix->repl = pstrdup(repl);
  	else
  		Affix->repl = VoidString;
  	Conf->naffixes++;
--- 443,451 ----
  	Affix->flag = flag;
  	Affix->type = type;
  
! 	Affix->find = (find && *find) ? aostrdup(find) : VoidString;
  	if ((Affix->replen = strlen(repl)) > 0)
! 		Affix->repl = aostrdup(repl);
  	else
  		Affix->repl = VoidString;
  	Conf->naffixes++;
***************
*** 833,839 ****
  	}
  
  	ptr = Conf->AffixData + Conf->nAffixData;
! 	*ptr = palloc(strlen(Conf->AffixData[a1]) + strlen(Conf->AffixData[a2]) +
  				  1 /* space */ + 1 /* \0 */ );
  	sprintf(*ptr, "%s %s", Conf->AffixData[a1], Conf->AffixData[a2]);
  	ptr++;
--- 901,907 ----
  	}
  
  	ptr = Conf->AffixData + Conf->nAffixData;
! 	*ptr = aoalloc(strlen(Conf->AffixData[a1]) + strlen(Conf->AffixData[a2]) +
  				  1 /* space */ + 1 /* \0 */ );
  	sprintf(*ptr, "%s %s", Conf->AffixData[a1], Conf->AffixData[a2]);
  	ptr++;
***************
*** 878,884 ****
  	if (!nchar)
  		return NULL;
  
! 	rs = (SPNode *) palloc0(SPNHDRSZ + nchar * sizeof(SPNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
--- 946,952 ----
  	if (!nchar)
  		return NULL;
  
! 	rs = (SPNode *) aoalloc0(SPNHDRSZ + nchar * sizeof(SPNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
***************
*** 965,971 ****
  	 * 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++)
--- 1033,1039 ----
  	 * dictionary. Replace textual flag-field of Conf->Spell entries with
  	 * indexes into Conf->AffixData array.
  	 */
! 	Conf->AffixData = (char **) aoalloc0(naffix * sizeof(char *));
  
  	curaffix = -1;
  	for (i = 0; i < Conf->nspell; i++)
***************
*** 974,980 ****
  		{
  			curaffix++;
  			Assert(curaffix < naffix);
! 			Conf->AffixData[curaffix] = pstrdup(Conf->Spell[i]->p.flag);
  		}
  
  		Conf->Spell[i]->p.d.affix = curaffix;
--- 1042,1048 ----
  		{
  			curaffix++;
  			Assert(curaffix < naffix);
! 			Conf->AffixData[curaffix] = aostrdup(Conf->Spell[i]->p.flag);
  		}
  
  		Conf->Spell[i]->p.d.affix = curaffix;
***************
*** 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;
  
--- 1082,1088 ----
  	aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1));
  	naff = 0;
  
! 	rs = (AffixNode *) aoalloc0(ANHRDSZ + nchar * sizeof(AffixNodeData));
  	rs->length = nchar;
  	data = rs->data;
  
***************
*** 1030,1036 ****
  					if (naff)
  					{
  						data->naff = naff;
! 						data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff);
  						memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  						naff = 0;
  					}
--- 1098,1104 ----
  					if (naff)
  					{
  						data->naff = naff;
! 						data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * naff);
  						memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  						naff = 0;
  					}
***************
*** 1050,1056 ****
  	if (naff)
  	{
  		data->naff = naff;
! 		data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff);
  		memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  		naff = 0;
  	}
--- 1118,1124 ----
  	if (naff)
  	{
  		data->naff = naff;
! 		data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * naff);
  		memcpy(data->aff, aff, sizeof(AFFIX *) * naff);
  		naff = 0;
  	}
***************
*** 1067,1073 ****
  				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;
--- 1135,1141 ----
  				cnt = 0;
  	int			start = (issuffix) ? startsuffix : 0;
  	int			end = (issuffix) ? Conf->naffixes : startsuffix;
! 	AffixNode  *Affix = (AffixNode *) aoalloc0(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;
--- 1159,1165 ----
  	if (cnt == 0)
  		return;
  
! 	Affix->data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * cnt);
  	Affix->data->naff = (uint32) cnt;
  
  	cnt = 0;
***************
*** 1658,1664 ****
  addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
  {
  	if (*lres == NULL)
! 		*lcur = *lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme));
  
  	if (*lcur - *lres < MAX_NORM - 1)
  	{
--- 1726,1732 ----
  addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant)
  {
  	if (*lres == NULL)
! 		*lcur = *lres = (TSLexeme *) aoalloc(MAX_NORM * sizeof(TSLexeme));
  
  	if (*lcur - *lres < MAX_NORM - 1)
  	{
*** ./src/include/tsearch/dicts/spell.h.orig	2010-04-02 17:21:20.000000000 +0200
--- ./src/include/tsearch/dicts/spell.h	2010-07-14 14:23:42.210440053 +0200
***************
*** 160,169 ****
--- 160,180 ----
  	bool		usecompound;
  } IspellDict;
  
+ typedef struct
+ {
+ 	MemoryContext	ctx;
+ 	Size	freesize;
+ 	char	*freeptr;
+ } AllocOnlyBlocksData;
+ 
  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);
  
+ extern char *ao_alloc(AllocOnlyBlocksData *aob, Size size, bool fillzero);
+ extern char *ao_strdup(AllocOnlyBlocksData *aob, const char *string);
+ 
+ 
  #endif
