*** ./contrib/dict_preload/dict_preload.c.orig 2010-03-18 17:00:33.281409707 +0100 --- ./contrib/dict_preload/dict_preload.c 2010-03-18 17:00:00.417407791 +0100 *************** *** 0 **** --- 1,102 ---- + /*------------------------------------------------------------------------- + * + * dict_preload.c + * preloaded dictionary - Czech + * + * Copyright (c) 2007-2010, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/contrib/dict_int/dict_int.c,v 1.6 2010/01/02 16:57:32 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + #include "postgres.h" + + #include "commands/defrem.h" + #include "fmgr.h" + #include "nodes/makefuncs.h" + #include "nodes/value.h" + #include "tsearch/ts_public.h" + #include "tsearch/ts_utils.h" + #include "tsearch/dicts/spell.h" + #include "utils/memutils.h" + + PG_MODULE_MAGIC; + + typedef struct + { + StopList stoplist; + IspellDict obj; + } DictISpell; + + MemoryContext preload_ctx; + + DictISpell *prepd = NULL; + + PG_FUNCTION_INFO_V1(dpreloaddict_init); + Datum dpreloaddict_init(PG_FUNCTION_ARGS); + + PG_FUNCTION_INFO_V1(dpreloaddict_lexize); + Datum dpreloaddict_lexize(PG_FUNCTION_ARGS); + + void _PG_init(void); + + Datum + dpreloaddict_init(PG_FUNCTION_ARGS) + { + + if (prepd == NULL) + return dispell_init(fcinfo); + else + { + + /* + * Add preload context to current conntext + */ + preload_ctx->parent = CurrentMemoryContext; + preload_ctx->nextchild = CurrentMemoryContext->firstchild; + CurrentMemoryContext->firstchild = preload_ctx; + + return PointerGetDatum(prepd); + } + } + + Datum + dpreloaddict_lexize(PG_FUNCTION_ARGS) + { + return dispell_lexize(fcinfo); + } + + + void + _PG_init() + { + static bool inited = false; + + MemoryContext oldctx; + List *dictoptions = NIL; + FunctionCallInfoData fcinfo; + + if (inited) + return; + + preload_ctx = AllocSetContextCreate(NULL, "Ispell dictionary preload context", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + oldctx = MemoryContextSwitchTo(preload_ctx); + + dictoptions = list_make1(makeDefElem("DictFile", (Node *) makeString("czech"))); + dictoptions = lappend(dictoptions, makeDefElem("AffFile", (Node *) makeString("czech"))); + dictoptions = lappend(dictoptions, makeDefElem("StopWords", (Node *) makeString("czech"))); + + InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL); + fcinfo.arg[0] = PointerGetDatum(dictoptions); + fcinfo.argnull[0] = false; + + prepd = (DictISpell *) DatumGetPointer(dispell_init(&fcinfo)); + + MemoryContextSwitchTo(oldctx); + + inited = true; + } *** ./contrib/dict_preload/dict_preload.sql.in.orig 2010-03-18 17:00:52.317502927 +0100 --- ./contrib/dict_preload/dict_preload.sql.in 2010-03-18 13:51:50.816472166 +0100 *************** *** 0 **** --- 1,19 ---- + /* $PostgreSQL: pgsql/contrib/dict_int/dict_int.sql.in,v 1.3 2007/11/13 04:24:27 momjian Exp $ */ + + -- Adjust this setting to control where the objects get created. + SET search_path = public; + + CREATE OR REPLACE FUNCTION dpreloaddict_init(internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT; + + CREATE OR REPLACE FUNCTION dpreloaddict_lexize(internal, internal, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT; + + CREATE TEXT SEARCH TEMPLATE preloaddict_template ( + LEXIZE = dpreloaddict_lexize, + INIT = dpreloaddict_init + ); *** ./contrib/dict_preload/uninstall_dict_preload.sql.orig 2010-03-18 17:00:58.039409567 +0100 --- ./contrib/dict_preload/uninstall_dict_preload.sql 2010-03-18 13:52:49.064472194 +0100 *************** *** 0 **** --- 1,10 ---- + /* $PostgreSQL: pgsql/contrib/dict_int/uninstall_dict_int.sql,v 1.3 2007/11/13 04:24:27 momjian Exp $ */ + + -- Adjust this setting to control where the objects get dropped. + SET search_path = public; + + DROP TEXT SEARCH TEMPLATE preloaddict_template CASCADE; + + DROP FUNCTION dpreloaddict_init(internal); + + DROP FUNCTION dpreloaddict_lexize(internal,internal,internal,internal); *** ./src/backend/tsearch/regis.c.orig 2010-01-02 17:57:53.000000000 +0100 --- ./src/backend/tsearch/regis.c 2010-03-18 16:41:03.027708600 +0100 *************** *** 71,88 **** } static RegisNode * ! newRegisNode(RegisNode *prev, int len) { RegisNode *ptr; ! ptr = (RegisNode *) palloc0(RNHDRSZ + len + 1); if (prev) prev->next = ptr; return ptr; } void ! RS_compile(Regis *r, bool issuffix, const char *str) { int len = strlen(str); int state = RS_IN_WAIT; --- 71,89 ---- } static RegisNode * ! newRegisNode(RegisNode *prev, int len, MemoryContext simple_ctx) { RegisNode *ptr; ! ptr = (RegisNode *) MemoryContextAllocZero(simple_ctx, ! RNHDRSZ + len + 1); if (prev) prev->next = ptr; return ptr; } void ! RS_compile(Regis *r, bool issuffix, const char *str, MemoryContext simple_ctx) { int len = strlen(str); int state = RS_IN_WAIT; *************** *** 99,107 **** if (t_isalpha(c)) { if (ptr) ! ptr = newRegisNode(ptr, len); else ! ptr = r->node = newRegisNode(NULL, len); COPYCHAR(ptr->data, c); ptr->type = RSF_ONEOF; ptr->len = pg_mblen(c); --- 100,108 ---- if (t_isalpha(c)) { if (ptr) ! ptr = newRegisNode(ptr, len, simple_ctx); else ! ptr = r->node = newRegisNode(NULL, len, simple_ctx); COPYCHAR(ptr->data, c); ptr->type = RSF_ONEOF; ptr->len = pg_mblen(c); *************** *** 109,117 **** else if (t_iseq(c, '[')) { if (ptr) ! ptr = newRegisNode(ptr, len); else ! ptr = r->node = newRegisNode(NULL, len); ptr->type = RSF_ONEOF; state = RS_IN_ONEOF; } --- 110,118 ---- else if (t_iseq(c, '[')) { if (ptr) ! ptr = newRegisNode(ptr, len, simple_ctx); else ! ptr = r->node = newRegisNode(NULL, len, simple_ctx); ptr->type = RSF_ONEOF; state = RS_IN_ONEOF; } *** ./src/backend/utils/mmgr/Makefile.orig 2010-03-18 15:15:23.063794982 +0100 --- ./src/backend/utils/mmgr/Makefile 2010-03-18 15:15:29.040796648 +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-18 15:14:59.593793406 +0100 --- ./src/backend/utils/mmgr/simple_alloc.c 2010-03-18 11:10:26.000000000 +0100 *************** *** 0 **** --- 1,348 ---- + #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 standard blocks */ + AllocBlock bigblocks; /* head of list of blocks larger than initBlockSize */ + 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) + + #define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData)) + + 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 = MAXALIGN(initBlockSize); + context->external_alloc = external_alloc; + context->external_free = external_free; + + context->blocks = NULL; + context->bigblocks = NULL; + context->isReset = true; + + return (MemoryContext) context; + } + + /* + * Context type methods + */ + static void + SimpleAllocInit(MemoryContext context) + { + /* + * do nothing + */ + } + + static void + SimpleAllocReset(MemoryContext context) + { + AllocBlock block; + AllocBlock next; + SimpleAlloc simple_ctx = (SimpleAlloc) context; + + Assert(SimpleAllocCtxIsValid(simple_ctx)); + + /* + * because simple alloc context doesn't support operation free + * we don't need to implement keeper block. + */ + block = simple_ctx->blocks; + while (block != NULL) + { + next = block->next; + #ifdef CLOBBER_FREED_MEMORY + memset(block->data, 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; + } + + block = simple_ctx->bigblocks; + while (block != NULL) + { + next = block->next; + + #ifdef CLOBBER_FREED_MEMORY + memset(block->data, 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->isReset = true; + simple_ctx->blocks = NULL; + simple_ctx->bigblocks = NULL; + } + + static void + SimpleAllocDelete(MemoryContext context) + { + SimpleAllocReset(context); + } + + static void * + SimpleAllocAlloc(MemoryContext context, Size size) + { + SimpleAlloc simple_ctx = (SimpleAlloc) context; + AllocBlock block; + void *newPointer; + Size allocSize; + bool isBigBlock; + + Assert(SimpleAllocCtxIsValid(simple_ctx)); + + /* + * Allocate separate block for allocation larger than 1/2 of initBlockSize + */ + size = MAXALIGN(size); + if (size > (simple_ctx->initBlockSize/3*2)) + { + /* + * we will allocate a big block - block only for current + * allocation - these blocks are is separete list. + */ + allocSize = size; + isBigBlock = true; + } + else + { + allocSize = simple_ctx->initBlockSize; + isBigBlock = false; + } + + /* + * Allocate a new block if there are no allocated or is big + * or isn't enought space. + */ + if (simple_ctx->blocks == NULL || isBigBlock || + (!isBigBlock && simple_ctx->blocks && simple_ctx->blocks->freesize < size)) + { + /* alloc a new block */ + + block = simple_ctx->external_alloc(MAXALIGN(allocSize + 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) allocSize + sizeof(AllocBlockData) - 1))); + } + + block->freesize = allocSize; + block->freeptr = block->data; + if (!isBigBlock) + { + block->next = simple_ctx->blocks; + simple_ctx->blocks = block; + } + else + { + block->next = simple_ctx->bigblocks; + simple_ctx->bigblocks = block; + } + } + else + block = simple_ctx->blocks; + + Assert(size <= block->freesize); + newPointer = block->freeptr; + + if (!isBigBlock) + { + 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 += MAXALIGN(simple_ctx->initBlockSize + sizeof(AllocBlockData) - 1); + freespace += block->freesize; + } + + for (block = simple_ctx->bigblocks; block != NULL; block = block->next) + { + nblocks++; + totalspace += block->freesize + sizeof(AllocBlockData) - 1; + } + + 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-18 15:18:55.349792968 +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-03-18 15:21:26.328793052 +0100 --- ./src/include/nodes/nodes.h 2010-03-18 15:21:37.257794503 +0100 *************** *** 234,239 **** --- 234,240 ---- */ T_MemoryContext = 600, T_AllocSetContext, + T_SimpleAllocContext, /* * TAGS FOR VALUE NODES (value.h) *** ./src/include/tsearch/dicts/regis.h.orig 2010-03-18 16:40:41.584584472 +0100 --- ./src/include/tsearch/dicts/regis.h 2010-03-18 16:40:13.428708569 +0100 *************** *** 40,46 **** bool RS_isRegis(const char *str); ! void RS_compile(Regis *r, bool issuffix, const char *str); void RS_free(Regis *r); /*returns true if matches */ --- 40,46 ---- bool RS_isRegis(const char *str); ! void RS_compile(Regis *r, bool issuffix, const char *str, MemoryContext simple_ctx); void RS_free(Regis *r); /*returns true if matches */ *** ./src/include/utils/memutils.h.orig 2010-01-02 17:58:10.000000000 +0100 --- ./src/include/utils/memutils.h 2010-03-18 15:20:48.889794704 +0100 *************** *** 136,139 **** --- 136,148 ---- #define ALLOCSET_SMALL_INITSIZE (1 * 1024) #define ALLOCSET_SMALL_MAXSIZE (8 * 1024) + /* simple_alloc.c */ + 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 */