/*
* At first, try to insert new tuple to the first page in notFullPage
- * array. If success we don't need to modify the meta page.
+ * array. If successful, we don't need to modify the meta page.
*/
metaBuffer = ReadBuffer(index, BLOOM_METAPAGE_BLKNO);
LockBuffer(metaBuffer, BUFFER_LOCK_SHARE);
Page page;
blkno = metaData->notFullPage[metaData->nStart];
-
Assert(blkno != InvalidBlockNumber);
+
+ /* Don't hold metabuffer lock while doing insert */
LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
buffer = ReadBuffer(index, blkno);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+
state = GenericXLogStart(index);
page = GenericXLogRegister(state, buffer, false);
if (BloomPageAddItem(&blstate, page, itup))
{
+ /* Success! Apply the change, clean up, and exit */
GenericXLogFinish(state);
UnlockReleaseBuffer(buffer);
ReleaseBuffer(metaBuffer);
MemoryContextDelete(insertCtx);
return false;
}
- else
- {
- GenericXLogAbort(state);
- UnlockReleaseBuffer(buffer);
- }
+
+ /* Didn't fit, must try other pages */
+ GenericXLogAbort(state);
+ UnlockReleaseBuffer(buffer);
}
else
{
- /* First page in notFullPage isn't suitable */
+ /* No entries in notFullPage */
LockBuffer(metaBuffer, BUFFER_LOCK_UNLOCK);
}
*/
LockBuffer(metaBuffer, BUFFER_LOCK_EXCLUSIVE);
- state = GenericXLogStart(index);
- metaPage = GenericXLogRegister(state, metaBuffer, false);
- metaData = BloomPageGetMeta(metaPage);
-
- /*
- * Iterate over notFullPage array. Skip page we already tried first.
- */
+ /* nStart might have changed while we didn't have lock */
nStart = metaData->nStart;
- if (metaData->nEnd > nStart &&
+
+ /* Skip first page if we already tried it above */
+ if (nStart < metaData->nEnd &&
blkno == metaData->notFullPage[nStart])
nStart++;
- while (metaData->nEnd > nStart)
+ /*
+ * This loop iterates for each page we try from the notFullPage array, and
+ * will also initialize a GenericXLogState for the fallback case of having
+ * to allocate a new page.
+ */
+ for (;;)
{
+ state = GenericXLogStart(index);
+
+ /* get modifiable copy of metapage */
+ metaPage = GenericXLogRegister(state, metaBuffer, false);
+ metaData = BloomPageGetMeta(metaPage);
+
+ if (nStart >= metaData->nEnd)
+ break; /* no more entries in notFullPage array */
+
blkno = metaData->notFullPage[nStart];
Assert(blkno != InvalidBlockNumber);
if (BloomPageAddItem(&blstate, page, itup))
{
+ /* Success! Apply the changes, clean up, and exit */
metaData->nStart = nStart;
GenericXLogFinish(state);
UnlockReleaseBuffer(buffer);
MemoryContextDelete(insertCtx);
return false;
}
- else
- {
- GenericXLogUnregister(state, buffer);
- UnlockReleaseBuffer(buffer);
- }
+
+ /* Didn't fit, must try other pages */
+ GenericXLogAbort(state);
+ UnlockReleaseBuffer(buffer);
nStart++;
}
- GenericXLogAbort(state);
-
/*
* Didn't find place to insert in notFullPage array. Allocate new page.
+ * (XXX is it good to do this while holding ex-lock on the metapage??)
*/
buffer = BloomNewBuffer(index);
- state = GenericXLogStart(index);
- metaPage = GenericXLogRegister(state, metaBuffer, false);
- metaData = BloomPageGetMeta(metaPage);
page = GenericXLogRegister(state, buffer, true);
BloomInitPage(page, 0);
if (!BloomPageAddItem(&blstate, page, itup))
{
- /* We shouldn't be here since we're inserting to the empty page */
+ /* We shouldn't be here since we're inserting to an empty page */
elog(ERROR, "could not add new bloom tuple to empty page");
}
+ /* Reset notFullPage array to contain just this new page */
metaData->nStart = 0;
metaData->nEnd = 1;
metaData->notFullPage[0] = BufferGetBlockNumber(buffer);
+ /* Apply the changes, clean up, and exit */
GenericXLogFinish(state);
UnlockReleaseBuffer(buffer);
UnlockReleaseBuffer(metaBuffer);
+ MemoryContextSwitchTo(oldCtx);
+ MemoryContextDelete(insertCtx);
+
return false;
}