From a9df049d29e7d36a75d941babd467b7b91acb09e Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 09 Mar 2016 09:30:32 +0000
Subject: [PATCH] OPENDJ-2645 numSubordinates attribute not returned when using PDB

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java |   33 ++++++++++++++++++++++-----------
 1 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
index 4b9d7cd..5d7637f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBStorage.java
@@ -11,7 +11,7 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2014-2015 ForgeRock AS.
+ * Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.backends.pdb;
 
@@ -709,6 +709,8 @@
   }
 
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+  private final ThreadLocal<Boolean> isInsideWriteTransaction = new ThreadLocal<Boolean>();
+
   private final ServerContext serverContext;
   private final File backendDirectory;
   private AccessMode accessMode;
@@ -852,13 +854,11 @@
   @Override
   public <T> T read(final ReadOperation<T> operation) throws Exception
   {
-    final Transaction txn = db.getTransaction();
     // This check may be unnecessary for PDB, but it will help us detect bad business logic
     // in the pluggable backend that would cause problems for JE.
-    // A nested read would be a serious problem for the JE storage
-    // as it could result in self-deadlock where an inner read attempts to read-lock a record
-    // that has been write-locked in an outer write.
-    throwIfTransactionIsNested(txn);
+    throwIfNestedInWriteTransaction();
+
+    final Transaction txn = db.getTransaction();
     for (;;)
     {
       txn.begin();
@@ -905,11 +905,13 @@
   @Override
   public void write(final WriteOperation operation) throws Exception
   {
+    throwIfNestedInWriteTransaction();
+
     final Transaction txn = db.getTransaction();
-    throwIfTransactionIsNested(txn);
     for (;;)
     {
       txn.begin();
+      isInsideWriteTransaction.set(Boolean.TRUE);
       try
       {
         try (final StorageImpl storageImpl = newStorageImpl())
@@ -940,16 +942,25 @@
       finally
       {
         txn.end();
+        isInsideWriteTransaction.set(Boolean.FALSE);
       }
     }
   }
 
-  private void throwIfTransactionIsNested(final Transaction txn)
+  /**
+   * A nested transaction within a write transaction may cause a self-deadlock where an inner read
+   * attempts to read-lock a record that has been write-locked in an outer write.
+   * <p>
+   * It would also be good to forbid any nested transactions, but it is impractical due to some
+   * transactions being deeply nested into the call hierarchy.
+   *
+   * @see <a href="https://bugster.forgerock.org/jira/browse/OPENDJ-2645">OPENDJ-2645</a>
+   */
+  private void throwIfNestedInWriteTransaction()
   {
-    final int txnDepth = txn.getNestedTransactionDepth();
-    if (txnDepth > 0)
+    if (Boolean.TRUE.equals(isInsideWriteTransaction.get()))
     {
-      throw new IllegalStateException("OpenDJ does not use nested transactions. "
+      throw new IllegalStateException("OpenDJ does not support transactions nested in a write transaction. "
           + "Code is forbidden from opening one.");
     }
   }

--
Gitblit v1.10.0