/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.addthis.hydra.data.tree.concurrent; import java.util.Map; import java.util.function.BooleanSupplier; import com.addthis.hydra.store.db.DBKey; import org.apache.commons.lang3.mutable.MutableLong; import org.slf4j.Logger; /** * Delete from the backing storage all nodes that have been moved to be * children of the trash node where they are waiting deletion. Also delete * all subtrees of these nodes. After deleting each subtree then test * the provided {@link ConcurrentTreeDeletionTask#terminationCondition}. * If it returns true then stop deletion. */ class ConcurrentTreeDeletionTask implements Runnable { private final ConcurrentTree dataTreeNodes; private final BooleanSupplier terminationCondition; private final Logger deletionLogger; public ConcurrentTreeDeletionTask(ConcurrentTree dataTreeNodes, BooleanSupplier terminationCondition, Logger deletionLogger) { this.dataTreeNodes = dataTreeNodes; this.terminationCondition = terminationCondition; this.deletionLogger = deletionLogger; } @Override public void run() { try { Map.Entry<DBKey, ConcurrentTreeNode> entry; MutableLong totalCount = new MutableLong(); MutableLong nodeCount = new MutableLong(); do { entry = dataTreeNodes.nextTrashNode(); if (entry != null) { ConcurrentTreeNode node = entry.getValue(); ConcurrentTreeNode prev = dataTreeNodes.source.remove(entry.getKey()); if (prev != null) { dataTreeNodes.deleteSubTree(node, totalCount, nodeCount, terminationCondition, deletionLogger); nodeCount.increment(); dataTreeNodes.treeTrashNode.incrementCounter(); } } } while ((entry != null) && !terminationCondition.getAsBoolean()); } catch (Exception ex) { ConcurrentTree.log.warn("{}", "Uncaught exception in concurrent tree background deletion thread", ex); } } }