@@ -95,6 +95,9 @@ static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
9595static TM_Result heap_lock_updated_tuple (Relation rel , HeapTuple tuple ,
9696 ItemPointer ctid , TransactionId xid ,
9797 LockTupleMode mode );
98+ static int heap_log_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
99+ xl_heap_freeze_plan * plans_out ,
100+ OffsetNumber * offsets_out );
98101static void GetMultiXactIdHintBits (MultiXactId multi , uint16 * new_infomask ,
99102 uint16 * new_infomask2 );
100103static TransactionId MultiXactIdGetUpdateXid (TransactionId xmax ,
@@ -111,9 +114,6 @@ static int bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate);
111114static XLogRecPtr log_heap_new_cid (Relation relation , HeapTuple tup );
112115static HeapTuple ExtractReplicaIdentity (Relation relation , HeapTuple tp , bool key_required ,
113116 bool * copy );
114- static int heap_xlog_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
115- xl_heap_freeze_plan * plans_out ,
116- OffsetNumber * offsets_out );
117117
118118
119119/*
@@ -6868,7 +6868,7 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
68686868 XLogRecPtr recptr ;
68696869
68706870 /* Prepare deduplicated representation for use in WAL record */
6871- nplans = heap_xlog_freeze_plan (tuples , ntuples , plans , offsets );
6871+ nplans = heap_log_freeze_plan (tuples , ntuples , plans , offsets );
68726872
68736873 xlrec .snapshotConflictHorizon = snapshotConflictHorizon ;
68746874 xlrec .nplans = nplans ;
@@ -6895,6 +6895,144 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
68956895 END_CRIT_SECTION ();
68966896}
68976897
6898+ /*
6899+ * Comparator used to deduplicate XLOG_HEAP2_FREEZE_PAGE freeze plans
6900+ */
6901+ static int
6902+ heap_log_freeze_cmp (const void * arg1 , const void * arg2 )
6903+ {
6904+ HeapTupleFreeze * frz1 = (HeapTupleFreeze * ) arg1 ;
6905+ HeapTupleFreeze * frz2 = (HeapTupleFreeze * ) arg2 ;
6906+
6907+ if (frz1 -> xmax < frz2 -> xmax )
6908+ return -1 ;
6909+ else if (frz1 -> xmax > frz2 -> xmax )
6910+ return 1 ;
6911+
6912+ if (frz1 -> t_infomask2 < frz2 -> t_infomask2 )
6913+ return -1 ;
6914+ else if (frz1 -> t_infomask2 > frz2 -> t_infomask2 )
6915+ return 1 ;
6916+
6917+ if (frz1 -> t_infomask < frz2 -> t_infomask )
6918+ return -1 ;
6919+ else if (frz1 -> t_infomask > frz2 -> t_infomask )
6920+ return 1 ;
6921+
6922+ if (frz1 -> frzflags < frz2 -> frzflags )
6923+ return -1 ;
6924+ else if (frz1 -> frzflags > frz2 -> frzflags )
6925+ return 1 ;
6926+
6927+ /*
6928+ * heap_log_freeze_eq would consider these tuple-wise plans to be equal.
6929+ * (So the tuples will share a single canonical freeze plan.)
6930+ *
6931+ * We tiebreak on page offset number to keep each freeze plan's page
6932+ * offset number array individually sorted. (Unnecessary, but be tidy.)
6933+ */
6934+ if (frz1 -> offset < frz2 -> offset )
6935+ return -1 ;
6936+ else if (frz1 -> offset > frz2 -> offset )
6937+ return 1 ;
6938+
6939+ Assert (false);
6940+ return 0 ;
6941+ }
6942+
6943+ /*
6944+ * Compare fields that describe actions required to freeze tuple with caller's
6945+ * open plan. If everything matches then the frz tuple plan is equivalent to
6946+ * caller's plan.
6947+ */
6948+ static inline bool
6949+ heap_log_freeze_eq (xl_heap_freeze_plan * plan , HeapTupleFreeze * frz )
6950+ {
6951+ if (plan -> xmax == frz -> xmax &&
6952+ plan -> t_infomask2 == frz -> t_infomask2 &&
6953+ plan -> t_infomask == frz -> t_infomask &&
6954+ plan -> frzflags == frz -> frzflags )
6955+ return true;
6956+
6957+ /* Caller must call heap_log_freeze_new_plan again for frz */
6958+ return false;
6959+ }
6960+
6961+ /*
6962+ * Start new plan initialized using tuple-level actions. At least one tuple
6963+ * will have steps required to freeze described by caller's plan during REDO.
6964+ */
6965+ static inline void
6966+ heap_log_freeze_new_plan (xl_heap_freeze_plan * plan , HeapTupleFreeze * frz )
6967+ {
6968+ plan -> xmax = frz -> xmax ;
6969+ plan -> t_infomask2 = frz -> t_infomask2 ;
6970+ plan -> t_infomask = frz -> t_infomask ;
6971+ plan -> frzflags = frz -> frzflags ;
6972+ plan -> ntuples = 1 ; /* for now */
6973+ }
6974+
6975+ /*
6976+ * Deduplicate tuple-based freeze plans so that each distinct set of
6977+ * processing steps is only stored once in XLOG_HEAP2_FREEZE_PAGE records.
6978+ * Called during original execution of freezing (for logged relations).
6979+ *
6980+ * Return value is number of plans set in *plans_out for caller. Also writes
6981+ * an array of offset numbers into *offsets_out output argument for caller
6982+ * (actually there is one array per freeze plan, but that's not of immediate
6983+ * concern to our caller).
6984+ */
6985+ static int
6986+ heap_log_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
6987+ xl_heap_freeze_plan * plans_out ,
6988+ OffsetNumber * offsets_out )
6989+ {
6990+ int nplans = 0 ;
6991+
6992+ /* Sort tuple-based freeze plans in the order required to deduplicate */
6993+ qsort (tuples , ntuples , sizeof (HeapTupleFreeze ), heap_log_freeze_cmp );
6994+
6995+ for (int i = 0 ; i < ntuples ; i ++ )
6996+ {
6997+ HeapTupleFreeze * frz = tuples + i ;
6998+
6999+ if (i == 0 )
7000+ {
7001+ /* New canonical freeze plan starting with first tup */
7002+ heap_log_freeze_new_plan (plans_out , frz );
7003+ nplans ++ ;
7004+ }
7005+ else if (heap_log_freeze_eq (plans_out , frz ))
7006+ {
7007+ /* tup matches open canonical plan -- include tup in it */
7008+ Assert (offsets_out [i - 1 ] < frz -> offset );
7009+ plans_out -> ntuples ++ ;
7010+ }
7011+ else
7012+ {
7013+ /* Tup doesn't match current plan -- done with it now */
7014+ plans_out ++ ;
7015+
7016+ /* New canonical freeze plan starting with this tup */
7017+ heap_log_freeze_new_plan (plans_out , frz );
7018+ nplans ++ ;
7019+ }
7020+
7021+ /*
7022+ * Save page offset number in dedicated buffer in passing.
7023+ *
7024+ * REDO routine relies on the record's offset numbers array grouping
7025+ * offset numbers by freeze plan. The sort order within each grouping
7026+ * is ascending offset number order, just to keep things tidy.
7027+ */
7028+ offsets_out [i ] = frz -> offset ;
7029+ }
7030+
7031+ Assert (nplans > 0 && nplans <= ntuples );
7032+
7033+ return nplans ;
7034+ }
7035+
68987036/*
68997037 * heap_freeze_tuple
69007038 * Freeze tuple in place, without WAL logging.
@@ -9015,144 +9153,6 @@ heap_xlog_visible(XLogReaderState *record)
90159153 UnlockReleaseBuffer (vmbuffer );
90169154}
90179155
9018- /*
9019- * Comparator used to deduplicate XLOG_HEAP2_FREEZE_PAGE freeze plans
9020- */
9021- static int
9022- heap_xlog_freeze_cmp (const void * arg1 , const void * arg2 )
9023- {
9024- HeapTupleFreeze * frz1 = (HeapTupleFreeze * ) arg1 ;
9025- HeapTupleFreeze * frz2 = (HeapTupleFreeze * ) arg2 ;
9026-
9027- if (frz1 -> xmax < frz2 -> xmax )
9028- return -1 ;
9029- else if (frz1 -> xmax > frz2 -> xmax )
9030- return 1 ;
9031-
9032- if (frz1 -> t_infomask2 < frz2 -> t_infomask2 )
9033- return -1 ;
9034- else if (frz1 -> t_infomask2 > frz2 -> t_infomask2 )
9035- return 1 ;
9036-
9037- if (frz1 -> t_infomask < frz2 -> t_infomask )
9038- return -1 ;
9039- else if (frz1 -> t_infomask > frz2 -> t_infomask )
9040- return 1 ;
9041-
9042- if (frz1 -> frzflags < frz2 -> frzflags )
9043- return -1 ;
9044- else if (frz1 -> frzflags > frz2 -> frzflags )
9045- return 1 ;
9046-
9047- /*
9048- * heap_xlog_freeze_eq would consider these tuple-wise plans to be equal.
9049- * (So the tuples will share a single canonical freeze plan.)
9050- *
9051- * We tiebreak on page offset number to keep each freeze plan's page
9052- * offset number array individually sorted. (Unnecessary, but be tidy.)
9053- */
9054- if (frz1 -> offset < frz2 -> offset )
9055- return -1 ;
9056- else if (frz1 -> offset > frz2 -> offset )
9057- return 1 ;
9058-
9059- Assert (false);
9060- return 0 ;
9061- }
9062-
9063- /*
9064- * Compare fields that describe actions required to freeze tuple with caller's
9065- * open plan. If everything matches then the frz tuple plan is equivalent to
9066- * caller's plan.
9067- */
9068- static inline bool
9069- heap_xlog_freeze_eq (xl_heap_freeze_plan * plan , HeapTupleFreeze * frz )
9070- {
9071- if (plan -> xmax == frz -> xmax &&
9072- plan -> t_infomask2 == frz -> t_infomask2 &&
9073- plan -> t_infomask == frz -> t_infomask &&
9074- plan -> frzflags == frz -> frzflags )
9075- return true;
9076-
9077- /* Caller must call heap_xlog_new_freeze_plan again for frz */
9078- return false;
9079- }
9080-
9081- /*
9082- * Start new plan initialized using tuple-level actions. At least one tuple
9083- * will have steps required to freeze described by caller's plan during REDO.
9084- */
9085- static inline void
9086- heap_xlog_new_freeze_plan (xl_heap_freeze_plan * plan , HeapTupleFreeze * frz )
9087- {
9088- plan -> xmax = frz -> xmax ;
9089- plan -> t_infomask2 = frz -> t_infomask2 ;
9090- plan -> t_infomask = frz -> t_infomask ;
9091- plan -> frzflags = frz -> frzflags ;
9092- plan -> ntuples = 1 ; /* for now */
9093- }
9094-
9095- /*
9096- * Deduplicate tuple-based freeze plans so that each distinct set of
9097- * processing steps is only stored once in XLOG_HEAP2_FREEZE_PAGE records.
9098- * Called during original execution of freezing (for logged relations).
9099- *
9100- * Return value is number of plans set in *plans_out for caller. Also writes
9101- * an array of offset numbers into *offsets_out output argument for caller
9102- * (actually there is one array per freeze plan, but that's not of immediate
9103- * concern to our caller).
9104- */
9105- static int
9106- heap_xlog_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
9107- xl_heap_freeze_plan * plans_out ,
9108- OffsetNumber * offsets_out )
9109- {
9110- int nplans = 0 ;
9111-
9112- /* Sort tuple-based freeze plans in the order required to deduplicate */
9113- qsort (tuples , ntuples , sizeof (HeapTupleFreeze ), heap_xlog_freeze_cmp );
9114-
9115- for (int i = 0 ; i < ntuples ; i ++ )
9116- {
9117- HeapTupleFreeze * frz = tuples + i ;
9118-
9119- if (i == 0 )
9120- {
9121- /* New canonical freeze plan starting with first tup */
9122- heap_xlog_new_freeze_plan (plans_out , frz );
9123- nplans ++ ;
9124- }
9125- else if (heap_xlog_freeze_eq (plans_out , frz ))
9126- {
9127- /* tup matches open canonical plan -- include tup in it */
9128- Assert (offsets_out [i - 1 ] < frz -> offset );
9129- plans_out -> ntuples ++ ;
9130- }
9131- else
9132- {
9133- /* Tup doesn't match current plan -- done with it now */
9134- plans_out ++ ;
9135-
9136- /* New canonical freeze plan starting with this tup */
9137- heap_xlog_new_freeze_plan (plans_out , frz );
9138- nplans ++ ;
9139- }
9140-
9141- /*
9142- * Save page offset number in dedicated buffer in passing.
9143- *
9144- * REDO routine relies on the record's offset numbers array grouping
9145- * offset numbers by freeze plan. The sort order within each grouping
9146- * is ascending offset number order, just to keep things tidy.
9147- */
9148- offsets_out [i ] = frz -> offset ;
9149- }
9150-
9151- Assert (nplans > 0 && nplans <= ntuples );
9152-
9153- return nplans ;
9154- }
9155-
91569156/*
91579157 * Replay XLOG_HEAP2_FREEZE_PAGE records
91589158 */
@@ -9189,21 +9189,19 @@ heap_xlog_freeze_page(XLogReaderState *record)
91899189 sizeof (xl_heap_freeze_plan )));
91909190 for (int p = 0 ; p < xlrec -> nplans ; p ++ )
91919191 {
9192- xl_heap_freeze_plan plan ;
91939192 HeapTupleFreeze frz ;
91949193
91959194 /*
91969195 * Convert freeze plan representation from WAL record into
91979196 * per-tuple format used by heap_execute_freeze_tuple
91989197 */
9199- memcpy (& plan , & plans [p ], sizeof (xl_heap_freeze_plan ));
9200- frz .xmax = plan .xmax ;
9201- frz .t_infomask2 = plan .t_infomask2 ;
9202- frz .t_infomask = plan .t_infomask ;
9203- frz .frzflags = plan .frzflags ;
9198+ frz .xmax = plans [p ].xmax ;
9199+ frz .t_infomask2 = plans [p ].t_infomask2 ;
9200+ frz .t_infomask = plans [p ].t_infomask ;
9201+ frz .frzflags = plans [p ].frzflags ;
92049202 frz .offset = InvalidOffsetNumber ; /* unused, but be tidy */
92059203
9206- for (int i = 0 ; i < plan .ntuples ; i ++ )
9204+ for (int i = 0 ; i < plans [ p ] .ntuples ; i ++ )
92079205 {
92089206 OffsetNumber offset = offsets [curoff ++ ];
92099207 ItemId lp ;
0 commit comments