*** ./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 */