From add86d3c7c047215f886c51e2b29a4c7f1e86c0c Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Thu, 03 Sep 2026 08:21:14 +0000
Subject: [PATCH] [#877] Bound a statement of the JDBC backend by the class of the work it belongs to (#882)
---
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
index 812300f..7eb800c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
@@ -57,9 +57,16 @@
this.counter = new ShardedCounter(name);
}
- SequentialCursor<EntryID, Void> openCursor(ReadableTransaction txn)
+ /**
+ * Walks the children counts whole, which {@code verify-index} does and no client operation does:
+ * there is no overload of this method that would take the bound of an operation by accident.
+ * Reading the count of a single entry is another matter - see {@link #getCount}.
+ *
+ * @see ReadableTransaction#openBulkCursor(TreeName)
+ */
+ SequentialCursor<EntryID, Void> openBulkCursor(ReadableTransaction txn)
{
- return transformKeysAndValues(counter.openCursor(txn),
+ return transformKeysAndValues(counter.openBulkCursor(txn),
TO_ENTRY_ID, CursorTransformer.<ByteString, Void> keepValuesUnchanged());
}
@@ -141,7 +148,23 @@
*/
long getCount(ReadableTransaction txn, EntryID entryID)
{
- return counter.getCount(txn, toKey(entryID));
+ return getCount(txn, entryID, false);
+ }
+
+ /**
+ * Get the number of children for the given entry, as part of a walk of a whole tree rather than
+ * of a client operation. {@code verify-index} reads one of these per DN while it walks dn2id
+ * whole, and no client is waiting on any of them.
+ *
+ * @param txn storage transaction
+ * @param entryID The entryID identifying to the counter
+ * @param partOfAWholeTreeWalk whether this read belongs to a walk of a whole tree
+ * @return Value of the counter. 0 if no counter is associated yet.
+ * @see ReadableTransaction#openBulkCursor(TreeName)
+ */
+ long getCount(ReadableTransaction txn, EntryID entryID, boolean partOfAWholeTreeWalk)
+ {
+ return counter.getCount(txn, toKey(entryID), partOfAWholeTreeWalk);
}
/**
@@ -151,7 +174,26 @@
*/
long getTotalCount(ReadableTransaction txn)
{
- return getCount(txn, TOTAL_COUNT_ENTRY_ID);
+ return getTotalCount(txn, false);
+ }
+
+ /**
+ * The same total, told which kind of work it is part of. It is a read of this tree like any
+ * other - a cursor positioned on one key, which on a storage engine that walks a table rather
+ * than an index is a scan of it - so what it may take follows who is waiting on it:
+ * {@code verify-index} reads it once to size the progress report of a walk of the whole backend,
+ * with nobody waiting, while {@code cn=monitor} and the searches of {@code GroupManager} and
+ * {@code SubentryManager} read the same total for a client.
+ *
+ * @param txn storage transaction
+ * @param partOfAWholeTreeWalk whether this read belongs to a walk of a whole tree rather than to
+ * a client operation
+ * @return Sum of all the counter contained in this tree
+ * @see ReadableTransaction#openBulkCursor(TreeName)
+ */
+ long getTotalCount(ReadableTransaction txn, boolean partOfAWholeTreeWalk)
+ {
+ return getCount(txn, TOTAL_COUNT_ENTRY_ID, partOfAWholeTreeWalk);
}
/**
--
Gitblit v1.10.0