@@ -200,7 +200,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
200200
201201 /*
202202 * At first, try to insert new tuple to the first page in notFullPage
203- * array. If success we don't need to modify the meta page.
203+ * array. If successful, we don't need to modify the meta page.
204204 */
205205 metaBuffer = ReadBuffer (index , BLOOM_METAPAGE_BLKNO );
206206 LockBuffer (metaBuffer , BUFFER_LOCK_SHARE );
@@ -212,33 +212,35 @@ blinsert(Relation index, Datum *values, bool *isnull,
212212 Page page ;
213213
214214 blkno = metaData -> notFullPage [metaData -> nStart ];
215-
216215 Assert (blkno != InvalidBlockNumber );
216+
217+ /* Don't hold metabuffer lock while doing insert */
217218 LockBuffer (metaBuffer , BUFFER_LOCK_UNLOCK );
218219
219220 buffer = ReadBuffer (index , blkno );
220221 LockBuffer (buffer , BUFFER_LOCK_EXCLUSIVE );
222+
221223 state = GenericXLogStart (index );
222224 page = GenericXLogRegister (state , buffer , false);
223225
224226 if (BloomPageAddItem (& blstate , page , itup ))
225227 {
228+ /* Success! Apply the change, clean up, and exit */
226229 GenericXLogFinish (state );
227230 UnlockReleaseBuffer (buffer );
228231 ReleaseBuffer (metaBuffer );
229232 MemoryContextSwitchTo (oldCtx );
230233 MemoryContextDelete (insertCtx );
231234 return false;
232235 }
233- else
234- {
235- GenericXLogAbort (state );
236- UnlockReleaseBuffer (buffer );
237- }
236+
237+ /* Didn't fit, must try other pages */
238+ GenericXLogAbort (state );
239+ UnlockReleaseBuffer (buffer );
238240 }
239241 else
240242 {
241- /* First page in notFullPage isn't suitable */
243+ /* No entries in notFullPage */
242244 LockBuffer (metaBuffer , BUFFER_LOCK_UNLOCK );
243245 }
244246
@@ -248,20 +250,30 @@ blinsert(Relation index, Datum *values, bool *isnull,
248250 */
249251 LockBuffer (metaBuffer , BUFFER_LOCK_EXCLUSIVE );
250252
251- state = GenericXLogStart (index );
252- metaPage = GenericXLogRegister (state , metaBuffer , false);
253- metaData = BloomPageGetMeta (metaPage );
254-
255- /*
256- * Iterate over notFullPage array. Skip page we already tried first.
257- */
253+ /* nStart might have changed while we didn't have lock */
258254 nStart = metaData -> nStart ;
259- if (metaData -> nEnd > nStart &&
255+
256+ /* Skip first page if we already tried it above */
257+ if (nStart < metaData -> nEnd &&
260258 blkno == metaData -> notFullPage [nStart ])
261259 nStart ++ ;
262260
263- while (metaData -> nEnd > nStart )
261+ /*
262+ * This loop iterates for each page we try from the notFullPage array, and
263+ * will also initialize a GenericXLogState for the fallback case of having
264+ * to allocate a new page.
265+ */
266+ for (;;)
264267 {
268+ state = GenericXLogStart (index );
269+
270+ /* get modifiable copy of metapage */
271+ metaPage = GenericXLogRegister (state , metaBuffer , false);
272+ metaData = BloomPageGetMeta (metaPage );
273+
274+ if (nStart >= metaData -> nEnd )
275+ break ; /* no more entries in notFullPage array */
276+
265277 blkno = metaData -> notFullPage [nStart ];
266278 Assert (blkno != InvalidBlockNumber );
267279
@@ -271,6 +283,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
271283
272284 if (BloomPageAddItem (& blstate , page , itup ))
273285 {
286+ /* Success! Apply the changes, clean up, and exit */
274287 metaData -> nStart = nStart ;
275288 GenericXLogFinish (state );
276289 UnlockReleaseBuffer (buffer );
@@ -279,41 +292,41 @@ blinsert(Relation index, Datum *values, bool *isnull,
279292 MemoryContextDelete (insertCtx );
280293 return false;
281294 }
282- else
283- {
284- GenericXLogUnregister (state , buffer );
285- UnlockReleaseBuffer (buffer );
286- }
295+
296+ /* Didn't fit, must try other pages */
297+ GenericXLogAbort (state );
298+ UnlockReleaseBuffer (buffer );
287299 nStart ++ ;
288300 }
289301
290- GenericXLogAbort (state );
291-
292302 /*
293303 * Didn't find place to insert in notFullPage array. Allocate new page.
304+ * (XXX is it good to do this while holding ex-lock on the metapage??)
294305 */
295306 buffer = BloomNewBuffer (index );
296307
297- state = GenericXLogStart (index );
298- metaPage = GenericXLogRegister (state , metaBuffer , false);
299- metaData = BloomPageGetMeta (metaPage );
300308 page = GenericXLogRegister (state , buffer , true);
301309 BloomInitPage (page , 0 );
302310
303311 if (!BloomPageAddItem (& blstate , page , itup ))
304312 {
305- /* We shouldn't be here since we're inserting to the empty page */
313+ /* We shouldn't be here since we're inserting to an empty page */
306314 elog (ERROR , "could not add new bloom tuple to empty page" );
307315 }
308316
317+ /* Reset notFullPage array to contain just this new page */
309318 metaData -> nStart = 0 ;
310319 metaData -> nEnd = 1 ;
311320 metaData -> notFullPage [0 ] = BufferGetBlockNumber (buffer );
312321
322+ /* Apply the changes, clean up, and exit */
313323 GenericXLogFinish (state );
314324
315325 UnlockReleaseBuffer (buffer );
316326 UnlockReleaseBuffer (metaBuffer );
317327
328+ MemoryContextSwitchTo (oldCtx );
329+ MemoryContextDelete (insertCtx );
330+
318331 return false;
319332}
0 commit comments