@@ -3104,28 +3104,33 @@ DropRelFileNodeBuffers(SMgrRelation smgr_reln, ForkNumber *forkNum,
3104
3104
* --------------------------------------------------------------------
3105
3105
*/
3106
3106
void
3107
- DropRelFileNodesAllBuffers (RelFileNodeBackend * rnodes , int nnodes )
3107
+ DropRelFileNodesAllBuffers (SMgrRelation * smgr_reln , int nnodes )
3108
3108
{
3109
- int i ,
3110
- n = 0 ;
3109
+ int i ;
3110
+ int j ;
3111
+ int n = 0 ;
3112
+ SMgrRelation * rels ;
3113
+ BlockNumber (* block )[MAX_FORKNUM + 1 ];
3114
+ BlockNumber nBlocksToInvalidate = 0 ;
3111
3115
RelFileNode * nodes ;
3116
+ bool cached = true;
3112
3117
bool use_bsearch ;
3113
3118
3114
3119
if (nnodes == 0 )
3115
3120
return ;
3116
3121
3117
- nodes = palloc (sizeof (RelFileNode ) * nnodes ); /* non-local relations */
3122
+ rels = palloc (sizeof (SMgrRelation ) * nnodes ); /* non-local relations */
3118
3123
3119
3124
/* If it's a local relation, it's localbuf.c's problem. */
3120
3125
for (i = 0 ; i < nnodes ; i ++ )
3121
3126
{
3122
- if (RelFileNodeBackendIsTemp (rnodes [i ]))
3127
+ if (RelFileNodeBackendIsTemp (smgr_reln [i ]-> smgr_rnode ))
3123
3128
{
3124
- if (rnodes [i ].backend == MyBackendId )
3125
- DropRelFileNodeAllLocalBuffers (rnodes [i ].node );
3129
+ if (smgr_reln [i ]-> smgr_rnode .backend == MyBackendId )
3130
+ DropRelFileNodeAllLocalBuffers (smgr_reln [i ]-> smgr_rnode .node );
3126
3131
}
3127
3132
else
3128
- nodes [n ++ ] = rnodes [i ]. node ;
3133
+ rels [n ++ ] = smgr_reln [i ];
3129
3134
}
3130
3135
3131
3136
/*
@@ -3134,10 +3139,72 @@ DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
3134
3139
*/
3135
3140
if (n == 0 )
3136
3141
{
3137
- pfree (nodes );
3142
+ pfree (rels );
3138
3143
return ;
3139
3144
}
3140
3145
3146
+ /*
3147
+ * This is used to remember the number of blocks for all the relations
3148
+ * forks.
3149
+ */
3150
+ block = (BlockNumber (* )[MAX_FORKNUM + 1 ])
3151
+ palloc (sizeof (BlockNumber ) * n * (MAX_FORKNUM + 1 ));
3152
+
3153
+ /*
3154
+ * We can avoid scanning the entire buffer pool if we know the exact size
3155
+ * of each of the given relation forks. See DropRelFileNodeBuffers.
3156
+ */
3157
+ for (i = 0 ; i < n && cached ; i ++ )
3158
+ {
3159
+ for (j = 0 ; j <= MAX_FORKNUM ; j ++ )
3160
+ {
3161
+ /* Get the number of blocks for a relation's fork. */
3162
+ block [i ][j ] = smgrnblocks_cached (rels [i ], j );
3163
+
3164
+ /* We need to only consider the relation forks that exists. */
3165
+ if (block [i ][j ] == InvalidBlockNumber )
3166
+ {
3167
+ if (!smgrexists (rels [i ], j ))
3168
+ continue ;
3169
+ cached = false;
3170
+ break ;
3171
+ }
3172
+
3173
+ /* calculate the total number of blocks to be invalidated */
3174
+ nBlocksToInvalidate += block [i ][j ];
3175
+ }
3176
+ }
3177
+
3178
+ /*
3179
+ * We apply the optimization iff the total number of blocks to invalidate
3180
+ * is below the BUF_DROP_FULL_SCAN_THRESHOLD.
3181
+ */
3182
+ if (cached && nBlocksToInvalidate < BUF_DROP_FULL_SCAN_THRESHOLD )
3183
+ {
3184
+ for (i = 0 ; i < n ; i ++ )
3185
+ {
3186
+ for (j = 0 ; j <= MAX_FORKNUM ; j ++ )
3187
+ {
3188
+ /* ignore relation forks that doesn't exist */
3189
+ if (!BlockNumberIsValid (block [i ][j ]))
3190
+ continue ;
3191
+
3192
+ /* drop all the buffers for a particular relation fork */
3193
+ FindAndDropRelFileNodeBuffers (rels [i ]-> smgr_rnode .node ,
3194
+ j , block [i ][j ], 0 );
3195
+ }
3196
+ }
3197
+
3198
+ pfree (block );
3199
+ pfree (rels );
3200
+ return ;
3201
+ }
3202
+
3203
+ pfree (block );
3204
+ nodes = palloc (sizeof (RelFileNode ) * n ); /* non-local relations */
3205
+ for (i = 0 ; i < n ; i ++ )
3206
+ nodes [i ] = rels [i ]-> smgr_rnode .node ;
3207
+
3141
3208
/*
3142
3209
* For low number of relations to drop just use a simple walk through, to
3143
3210
* save the bsearch overhead. The threshold to use is rather a guess than
@@ -3193,6 +3260,7 @@ DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
3193
3260
}
3194
3261
3195
3262
pfree (nodes );
3263
+ pfree (rels );
3196
3264
}
3197
3265
3198
3266
/* ---------------------------------------------------------------------
0 commit comments