Skip to content

Commit

Permalink
Avoid compaction to trigger extra flushes DbLedgerStorage (#3959)
Browse files Browse the repository at this point in the history
* Avoid compaction to trigger extra flushes DbLedgerStorage

* Expanded comment

* Fixed test

* Fixed direct io test

(cherry picked from commit c924cfe)
  • Loading branch information
merlimat authored and zymap committed Dec 6, 2023
1 parent 25463d8 commit d94d1cc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -863,9 +863,30 @@ public Iterable<Long> getActiveLedgersInRange(long firstLedgerId, long lastLedge

@Override
public void updateEntriesLocations(Iterable<EntryLocation> locations) throws IOException {
// Trigger a flush to have all the entries being compacted in the db storage
flush();
// Before updating the DB with the new location for the compacted entries, we need to
// make sure that there is no ongoing flush() operation.
// If there were a flush, we could have the following situation, which is highly
// unlikely though possible:
// 1. Flush operation has written the write-cache content into entry-log files
// 2. The DB location index is not yet updated
// 3. Compaction is triggered and starts compacting some of the recent files
// 4. Compaction will write the "new location" into the DB
// 5. The pending flush() will overwrite the DB with the "old location", pointing
// to a file that no longer exists
//
// To avoid this race condition, we need that all the entries that are potentially
// included in the compaction round to have all the indexes already flushed into
// the DB.
// The easiest lightweight way to achieve this is to wait for any pending
// flush operation to be completed before updating the index with the compacted
// entries, by blocking on the flushMutex.
flushMutex.lock();
flushMutex.unlock();

// We don't need to keep the flush mutex locked here while updating the DB.
// It's fine to have a concurrent flush operation at this point, because we
// know that none of the entries being flushed was included in the compaction
// round that we are dealing with.
entryLocationIndex.updateLocations(locations);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ public void testBookieCompaction() throws Exception {
entry3.writeBytes("entry-3".getBytes());
storage.addEntry(entry3);


// Simulate bookie compaction
SingleDirectoryDbLedgerStorage singleDirStorage = ((DbLedgerStorage) storage).getLedgerStorageList().get(0);
EntryLogger entryLogger = singleDirStorage.getEntryLogger();
Expand All @@ -234,6 +235,7 @@ public void testBookieCompaction() throws Exception {
newEntry3.writeBytes("new-entry-3".getBytes());
long location = entryLogger.addEntry(4L, newEntry3, false);

storage.flush();
List<EntryLocation> locations = Lists.newArrayList(new EntryLocation(4, 3, location));
singleDirStorage.updateEntriesLocations(locations);

Expand Down

0 comments on commit d94d1cc

Please sign in to comment.