This is an automated email from the ASF dual-hosted git repository. domgarguilo pushed a commit to branch 2.1 in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/2.1 by this push: new 5bba2f3cf3 Improvements to scan ref removal in DatafileManager (#5674) 5bba2f3cf3 is described below commit 5bba2f3cf36717d0e2fabbf4abb93c3455c0619e Author: Dom G. <domgargu...@apache.org> AuthorDate: Wed Jul 2 11:36:32 2025 -0400 Improvements to scan ref removal in DatafileManager (#5674) * Use a new scheduled task in the tablet server to clean up all scan refs. This removes the attempt to clean them up after each scan so we can batch this operation --------- Co-authored-by: Keith Turner <ktur...@apache.org> --- .../org/apache/accumulo/tserver/TabletServer.java | 2 +- .../accumulo/tserver/tablet/DatafileManager.java | 71 +++++++++++----------- .../org/apache/accumulo/tserver/tablet/Tablet.java | 18 +++++- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java index d5d411db50..0cf5c2ec47 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/TabletServer.java @@ -314,7 +314,7 @@ public class TabletServer extends AbstractServer context.getScheduledExecutor().scheduleWithFixedDelay(Threads.createNamedRunnable( "ScanRefCleanupTask", () -> getOnlineTablets().values().forEach(tablet -> { try { - tablet.removeOrphanedScanRefs(); + tablet.removeBatchedScanRefs(); } catch (Exception e) { log.error("Error cleaning up stale scan references for tablet {}", tablet.getExtent(), e); diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/DatafileManager.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/DatafileManager.java index df88ad6225..ce8c4dcd29 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/DatafileManager.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/DatafileManager.java @@ -119,43 +119,27 @@ class DatafileManager { void returnFilesForScan(Long reservationId) { - final Set<StoredTabletFile> filesToDelete = new HashSet<>(); - - try { - synchronized (tablet) { - Set<StoredTabletFile> absFilePaths = scanFileReservations.remove(reservationId); + synchronized (tablet) { + Set<StoredTabletFile> absFilePaths = scanFileReservations.remove(reservationId); - if (absFilePaths == null) { - throw new IllegalArgumentException("Unknown scan reservation id " + reservationId); - } + if (absFilePaths == null) { + throw new IllegalArgumentException("Unknown scan reservation id " + reservationId); + } - boolean notify = false; - try { - for (StoredTabletFile path : absFilePaths) { - long refCount = fileScanReferenceCounts.decrement(path, 1); - if (refCount == 0) { - if (filesToDeleteAfterScan.remove(path)) { - filesToDelete.add(path); - } - notify = true; - } else if (refCount < 0) { - throw new IllegalStateException("Scan ref count for " + path + " is " + refCount); - } - } - } finally { - if (notify) { - tablet.notifyAll(); + boolean notify = false; + try { + for (StoredTabletFile path : absFilePaths) { + long refCount = fileScanReferenceCounts.decrement(path, 1); + if (refCount == 0) { + notify = true; + } else if (refCount < 0) { + throw new IllegalStateException("Scan ref count for " + path + " is " + refCount); } } - } - } finally { - // Remove scan files even if the loop above did not fully complete because once a - // file is in the set filesToDelete that means it was removed from filesToDeleteAfterScan - // and would never be added back. - if (!filesToDelete.isEmpty()) { - log.debug("Removing scan refs from metadata {} {}", tablet.getExtent(), filesToDelete); - MetadataTableUtil.removeScanFiles(tablet.getExtent(), filesToDelete, tablet.getContext(), - tablet.getTabletServer().getLock()); + } finally { + if (notify) { + tablet.notifyAll(); + } } } } @@ -185,11 +169,10 @@ class DatafileManager { } /** - * Removes any scan-in-use metadata entries that were left behind when a scan cleanup was - * interrupted. Intended to be called periodically to clear these orphaned scan refs once their - * in-memory reference count reaches zero. + * This method will remove any scan references that have been added to filesToDeleteAfterScan. + * This is meant to be called periodically as to batch the removal of scan references. */ - public void removeOrphanedScanRefs() { + public void removeBatchedScanRefs() { Set<StoredTabletFile> snapshot; synchronized (tablet) { snapshot = new HashSet<>(filesToDeleteAfterScan); @@ -198,6 +181,20 @@ class DatafileManager { removeFilesAfterScan(snapshot); } + /** + * @return true if any file is no longer in use by a scan and can be removed, false otherwise. + */ + boolean canScanRefsBeRemoved() { + synchronized (tablet) { + for (var path : filesToDeleteAfterScan) { + if (fileScanReferenceCounts.get(path) == 0) { + return true; + } + } + return false; + } + } + private TreeSet<StoredTabletFile> waitForScansToFinish(Set<StoredTabletFile> pathsToWaitFor) { long maxWait = 10000L; long startTime = System.currentTimeMillis(); diff --git a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/Tablet.java b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/Tablet.java index e4d9f9787c..8e296d400d 100644 --- a/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/Tablet.java +++ b/server/tserver/src/main/java/org/apache/accumulo/tserver/tablet/Tablet.java @@ -2220,8 +2220,22 @@ public class Tablet extends TabletBase { return getDatafileManager().getUpdateCount(); } - public void removeOrphanedScanRefs() { - getDatafileManager().removeOrphanedScanRefs(); + public void removeBatchedScanRefs() { + synchronized (this) { + if (isClosed() || isClosing()) { + return; + } + // return early if there are no scan files to remove + if (!getDatafileManager().canScanRefsBeRemoved()) { + return; + } + incrementWritesInProgress(); + } + try { + getDatafileManager().removeBatchedScanRefs(); + } finally { + decrementWritesInProgress(); + } } TabletMemory getTabletMemory() {