Attached is the complete patch against HEAD to prevent hashtable bucket
splits during hash_seq_search. Any comments before I start
back-porting? I suppose we had better patch this all the way back,
even though AtPrepare_Locks() is the only known trouble spot.
regards, tom lane
*** src/backend/access/transam/xact.c.orig Tue Apr 3 12:34:35 2007
--- src/backend/access/transam/xact.c Wed Apr 25 20:32:00 2007
***
*** 1631,1636
--- 1631,1637
/* smgrcommit already done */
AtEOXact_Files();
AtEOXact_ComboCid();
+ AtEOXact_HashTables(true);
pgstat_clear_snapshot();
pgstat_count_xact_commit();
pgstat_report_txn_timestamp(0);
***
*** 1849,1854
--- 1850,1856
/* smgrcommit already done */
AtEOXact_Files();
AtEOXact_ComboCid();
+ AtEOXact_HashTables(true);
pgstat_clear_snapshot();
CurrentResourceOwner = NULL;
***
*** 2003,2008
--- 2005,2011
smgrabort();
AtEOXact_Files();
AtEOXact_ComboCid();
+ AtEOXact_HashTables(false);
pgstat_clear_snapshot();
pgstat_count_xact_rollback();
pgstat_report_txn_timestamp(0);
***
*** 3716,3721
--- 3719,3725
s->parent->subTransactionId);
AtEOSubXact_Files(true, s->subTransactionId,
s->parent->subTransactionId);
+ AtEOSubXact_HashTables(true, s->nestingLevel);
/*
* We need to restore the upper transaction's read-only state, in case
the
***
*** 3827,3832
--- 3831,3837
s->parent->subTransactionId);
AtEOSubXact_Files(false, s->subTransactionId,
s->parent->subTransactionId);
+ AtEOSubXact_HashTables(false, s->nestingLevel);
}
/*
*** src/backend/commands/prepare.c.orig Mon Apr 16 14:21:07 2007
--- src/backend/commands/prepare.c Thu Apr 26 15:00:40 2007
***
*** 21,27
#include "catalog/pg_type.h"
#include "commands/explain.h"
#include "commands/prepare.h"
! #include "funcapi.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
--- 21,27
#include "catalog/pg_type.h"
#include "commands/explain.h"
#include "commands/prepare.h"
! #include "miscadmin.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
***
*** 743,834
Datum
pg_prepared_statement(PG_FUNCTION_ARGS)
{
! FuncCallContext *funcctx;
! HASH_SEQ_STATUS *hash_seq;
! PreparedStatement *prep_stmt;
! /* stuff done only on the first call of the function */
! if (SRF_IS_FIRSTCALL())
! {
! TupleDesc tupdesc;
! MemoryContext oldcontext;
! /* create a function context for cross-call persistence */
! funcctx = SRF_FIRSTCALL_INIT();
! /*
!* switch to memory context appropriate for multiple function
calls
!*/
! oldcontext =
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
! /* allocate memory for user context */
! if (prepared_queries)
{
! hash_seq = (HASH_SEQ_STATUS *)
palloc(sizeof(HASH_SEQ_STATUS));
! hash_seq_init(hash_seq, prepared_queries);
! funcctx->user_fctx = (void *) hash_seq;
! }
! else
! funcctx->user_fctx = NULL;
! /*
!* build tupdesc for result tuples. This must match the
definition of
!* the pg_prepared_statements view in system_views.sql
!*/
! tupdesc = CreateTemplateTupleDesc(5, false);
! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
! TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
! TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 3, "prepare_time",
! TIMESTAMPTZOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 4, "parameter_types",
! REGTYPEARRAYOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "from_sql",
! BOOLOID, -1, 0);
!
! funcctx->tuple_desc = BlessTupleDesc(tupdesc);
! MemoryContextSwitchTo(oldcontext);
! }
!
! /* stuff done on every call of the function */
! funcctx = SR