@@ -95,6 +95,9 @@ static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
95
95
static TM_Result heap_lock_updated_tuple (Relation rel , HeapTuple tuple ,
96
96
ItemPointer ctid , TransactionId xid ,
97
97
LockTupleMode mode );
98
+ static int heap_log_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
99
+ xl_heap_freeze_plan * plans_out ,
100
+ OffsetNumber * offsets_out );
98
101
static void GetMultiXactIdHintBits (MultiXactId multi , uint16 * new_infomask ,
99
102
uint16 * new_infomask2 );
100
103
static TransactionId MultiXactIdGetUpdateXid (TransactionId xmax ,
@@ -111,9 +114,6 @@ static int bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate);
111
114
static XLogRecPtr log_heap_new_cid (Relation relation , HeapTuple tup );
112
115
static HeapTuple ExtractReplicaIdentity (Relation relation , HeapTuple tp , bool key_required ,
113
116
bool * copy );
114
- static int heap_xlog_freeze_plan (HeapTupleFreeze * tuples , int ntuples ,
115
- xl_heap_freeze_plan * plans_out ,
116
- OffsetNumber * offsets_out );
117
117
118
118
119
119
/*
@@ -6868,7 +6868,7 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
6868
6868
XLogRecPtr recptr ;
6869
6869
6870
6870
/* 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 );
6872
6872
6873
6873
xlrec .snapshotConflictHorizon = snapshotConflictHorizon ;
6874
6874
xlrec .nplans = nplans ;
@@ -6895,6 +6895,144 @@ heap_freeze_execute_prepared(Relation rel, Buffer buffer,
6895
6895
END_CRIT_SECTION ();
6896
6896
}
6897
6897
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
+
6898
7036
/*
6899
7037
* heap_freeze_tuple
6900
7038
* Freeze tuple in place, without WAL logging.
@@ -9015,144 +9153,6 @@ heap_xlog_visible(XLogReaderState *record)
9015
9153
UnlockReleaseBuffer (vmbuffer );
9016
9154
}
9017
9155
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
-
9156
9156
/*
9157
9157
* Replay XLOG_HEAP2_FREEZE_PAGE records
9158
9158
*/
@@ -9189,21 +9189,19 @@ heap_xlog_freeze_page(XLogReaderState *record)
9189
9189
sizeof (xl_heap_freeze_plan )));
9190
9190
for (int p = 0 ; p < xlrec -> nplans ; p ++ )
9191
9191
{
9192
- xl_heap_freeze_plan plan ;
9193
9192
HeapTupleFreeze frz ;
9194
9193
9195
9194
/*
9196
9195
* Convert freeze plan representation from WAL record into
9197
9196
* per-tuple format used by heap_execute_freeze_tuple
9198
9197
*/
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 ;
9204
9202
frz .offset = InvalidOffsetNumber ; /* unused, but be tidy */
9205
9203
9206
- for (int i = 0 ; i < plan .ntuples ; i ++ )
9204
+ for (int i = 0 ; i < plans [ p ] .ntuples ; i ++ )
9207
9205
{
9208
9206
OffsetNumber offset = offsets [curoff ++ ];
9209
9207
ItemId lp ;
0 commit comments