? GNUmakefile ? config.log ? config.status ? core.7509 ? cscope.files ? cscope.out ? install ? contrib/pgbench/pgbench ? src/Makefile.global ? src/backend/postgres ? src/backend/catalog/postgres.bki ? src/backend/catalog/postgres.description ? src/backend/catalog/postgres.shdescription ? src/backend/utils/mb/conversion_procs/conversion_create.sql ? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0 ? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0 ? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0 ? src/bin/initdb/initdb ? src/bin/ipcclean/ipcclean ? src/bin/pg_config/pg_config ? src/bin/pg_controldata/pg_controldata ? src/bin/pg_ctl/pg_ctl ? src/bin/pg_dump/pg_dump ? src/bin/pg_dump/pg_dumpall ? src/bin/pg_dump/pg_restore ? src/bin/pg_resetxlog/pg_resetxlog ? src/bin/psql/psql ? src/bin/scripts/clusterdb ? src/bin/scripts/createdb ? src/bin/scripts/createlang ? src/bin/scripts/createuser ? src/bin/scripts/dropdb ? src/bin/scripts/droplang ? src/bin/scripts/dropuser ? src/bin/scripts/reindexdb ? src/bin/scripts/vacuumdb ? src/include/pg_config.h ? src/include/stamp-h ? src/interfaces/ecpg/compatlib/libecpg_compat.so.2.3 ? src/interfaces/ecpg/ecpglib/libecpg.so.5.3 ? src/interfaces/ecpg/include/ecpg_config.h ? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.2.3 ? src/interfaces/ecpg/preproc/ecpg ? src/interfaces/libpq/exports.list ? src/interfaces/libpq/libpq.so.5.1 ? src/pl/plpgsql/src/libplpgsql.so.1.0 ? src/port/pg_config_paths.h ? src/test/regress/libregress.so.0.0 ? src/test/regress/pg_regress ? src/test/regress/results ? src/test/regress/testtablespace ? src/test/regress/expected/constraints.out ? src/test/regress/expected/copy.out ? src/test/regress/expected/create_function_1.out ? src/test/regress/expected/create_function_2.out ? src/test/regress/expected/largeobject.out ? src/test/regress/expected/largeobject_1.out ? src/test/regress/expected/misc.out ? src/test/regress/expected/tablespace.out ? src/test/regress/sql/constraints.sql ? src/test/regress/sql/copy.sql ? src/test/regress/sql/create_function_1.sql ? src/test/regress/sql/create_function_2.sql ? src/test/regress/sql/largeobject.sql ? src/test/regress/sql/misc.sql ? src/test/regress/sql/tablespace.sql ? src/timezone/zic Index: src/backend/commands/analyze.c =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/analyze.c,v retrieving revision 1.104 diff -c -r1.104 analyze.c *** src/backend/commands/analyze.c 6 Apr 2007 04:21:42 -0000 1.104 --- src/backend/commands/analyze.c 11 Apr 2007 06:10:12 -0000 *************** *** 139,144 **** --- 139,148 ---- if (!onerel) return; + /* set the snapshot if not already done so */ + if (ActiveSnapshot == NULL) + ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + /* * Check permissions --- this should match vacuum's check! */ Index: src/backend/commands/cluster.c =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/cluster.c,v retrieving revision 1.159 diff -c -r1.159 cluster.c *** src/backend/commands/cluster.c 8 Apr 2007 01:26:28 -0000 1.159 --- src/backend/commands/cluster.c 11 Apr 2007 06:10:12 -0000 *************** *** 205,212 **** /* Start a new transaction for each relation. */ StartTransactionCommand(); ! /* functions in indexes may want a snapshot set */ ! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); cluster_rel(rvtc, true); CommitTransactionCommand(); } --- 205,215 ---- /* Start a new transaction for each relation. */ StartTransactionCommand(); ! /* ! * functions in indexes may want a snapshot set, but we don't ! * set it until the relation is locked succesfully. This helps ! * us avoid certain deadlocks with CREATE INDEX CONCURRENTLY ! */ cluster_rel(rvtc, true); CommitTransactionCommand(); } *************** *** 253,258 **** --- 256,264 ---- if (!OldHeap) return; + if (ActiveSnapshot == NULL) + ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + /* * Since we may open a new transaction for each relation, we have to check * that the relation still is what we think it is. Index: src/backend/commands/indexcmds.c =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/indexcmds.c,v retrieving revision 1.157 diff -c -r1.157 indexcmds.c *** src/backend/commands/indexcmds.c 13 Mar 2007 00:33:39 -0000 1.157 --- src/backend/commands/indexcmds.c 11 Apr 2007 06:10:12 -0000 *************** *** 512,518 **** * need not check for that. */ for (ixcnt = 0; ixcnt < snapshot->xcnt; ixcnt++) ! XactLockTableWait(snapshot->xip[ixcnt]); /* Index can now be marked valid -- update its pg_index entry */ pg_index = heap_open(IndexRelationId, RowExclusiveLock); --- 512,533 ---- * need not check for that. */ for (ixcnt = 0; ixcnt < snapshot->xcnt; ixcnt++) ! { ! /* ! * Another backend doing VACUUM/ANALYZE/CLUSTER may deadlock with us ! * because we might wait for the other backend to finish while it waits ! * for the lock on the relation. We handle this by waiting for a ! * transaction only if it has already set its serializable ! * snapshot. A backend doing VACUUM/ANALYZE/CLUSTER always grabs lock ! * on the relation first and then set its serializable snapshot. ! * ! * A transaction which hasn't yet set its serializable ! * snapshot can not see any of the tuples that we did not index, so ! * its OK if we don't wait for it. ! */ ! if (TransactionHasSnapshot(snapshot->xip[ixcnt])) ! XactLockTableWait(snapshot->xip[ixcnt]); ! } /* Index can now be marked valid -- update its pg_index entry */ pg_index = heap_open(IndexRelationId, RowExclusiveLock); Index: src/backend/commands/vacuum.c =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/vacuum.c,v retrieving revision 1.349 diff -c -r1.349 vacuum.c *** src/backend/commands/vacuum.c 14 Mar 2007 18:48:55 -0000 1.349 --- src/backend/commands/vacuum.c 11 Apr 2007 06:10:12 -0000 *************** *** 338,344 **** * * For ANALYZE (no VACUUM): if inside a transaction block, we cannot * start/commit our own transactions. Also, there's no need to do so if ! * only processing one relation. For multiple relations when not within a * transaction block, use own transactions so we can release locks sooner. */ if (vacstmt->vacuum) --- 338,347 ---- * * For ANALYZE (no VACUUM): if inside a transaction block, we cannot * start/commit our own transactions. Also, there's no need to do so if ! * only processing one relation. But we still do that because that helps ! * us to set serializable snapshot only after acquiring appropriate lock ! * on the relation. This avoids certain deadlock conditions with CREATE ! * INDEX CONCURRENTLY. For multiple relations when not within a * transaction block, use own transactions so we can release locks sooner. */ if (vacstmt->vacuum) *************** *** 348,357 **** Assert(vacstmt->analyze); if (in_outer_xact) use_own_xacts = false; ! else if (list_length(relations) > 1) use_own_xacts = true; - else - use_own_xacts = false; } /* --- 351,358 ---- Assert(vacstmt->analyze); if (in_outer_xact) use_own_xacts = false; ! else use_own_xacts = true; } /* *************** *** 411,418 **** if (use_own_xacts) { StartTransactionCommand(); ! /* functions in indexes may want a snapshot set */ ! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); } else old_context = MemoryContextSwitchTo(anl_context); --- 412,422 ---- if (use_own_xacts) { StartTransactionCommand(); ! /* ! * functions in indexes may want a snapshot set, but ! * we shall set the snapshot only after acquiring lock on ! * the relation ! */ } else old_context = MemoryContextSwitchTo(anl_context); *************** *** 961,972 **** /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); ! if (vacstmt->full) ! { ! /* functions in indexes may want a snapshot set */ ! ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); ! } ! else { /* * During a lazy VACUUM we do not run any user-supplied functions, and --- 965,971 ---- /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); ! if (!vacstmt->full) { /* * During a lazy VACUUM we do not run any user-supplied functions, and *************** *** 1017,1022 **** --- 1016,1027 ---- return; } + if (ActiveSnapshot == NULL) + { + /* functions in indexes may want a snapshot set */ + ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + } + /* * Check permissions. * Index: src/backend/storage/ipc/procarray.c =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/storage/ipc/procarray.c,v retrieving revision 1.24 diff -c -r1.24 procarray.c *** src/backend/storage/ipc/procarray.c 3 Apr 2007 16:34:36 -0000 1.24 --- src/backend/storage/ipc/procarray.c 11 Apr 2007 06:10:12 -0000 *************** *** 1079,1084 **** --- 1079,1121 ---- LWLockRelease(ProcArrayLock); } + /* + * Returns true if snapshot is set for the given transaction. + * + * Note: We acquire LW_SHARED on procArray below, which means that + * a transaction might be setting its snapshot while we are + * checking for it. + */ + bool + TransactionHasSnapshot(TransactionId xid) + { + ProcArrayStruct *arrayP = procArray; + int index; + bool has_snapshot = false; + + LWLockAcquire(ProcArrayLock, LW_SHARED); + + for (index = 0; index < arrayP->numProcs; index++) + { + PGPROC *proc = arrayP->procs[index]; + + if (proc->pid == 0) + continue; /* do not count prepared xacts */ + + if (proc->xid != xid) + continue; + + if (TransactionIdIsValid(proc->xmin)) + has_snapshot = true; + + break; + } + + LWLockRelease(ProcArrayLock); + + return has_snapshot; + } + #ifdef XIDCACHE_DEBUG /* Index: src/include/storage/procarray.h =================================================================== RCS file: /home/cvs/postgres/cvs/pgsql/src/include/storage/procarray.h,v retrieving revision 1.13 diff -c -r1.13 procarray.h *** src/include/storage/procarray.h 3 Apr 2007 16:34:36 -0000 1.13 --- src/include/storage/procarray.h 11 Apr 2007 06:10:12 -0000 *************** *** 40,44 **** --- 40,45 ---- extern void XidCacheRemoveRunningXids(TransactionId xid, int nxids, TransactionId *xids); + extern bool TransactionHasSnapshot(TransactionId xid); #endif /* PROCARRAY_H */