From 5c877a749c0633a0fa6ef146b89d9a559637bc99 Mon Sep 17 00:00:00 2001
From: "Brian S. O'Neill" <bronee@gmail.com>
Date: Wed, 22 Dec 2010 23:24:13 +0000
Subject: Request and persist layout metadata in separate thread.

---
 .../com/amazon/carbonado/layout/LayoutFactory.java | 63 ++++++++++++++++++++--
 1 file changed, 59 insertions(+), 4 deletions(-)

diff --git a/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java b/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java
index 836ee54..4457ee0 100644
--- a/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java
+++ b/src/main/java/com/amazon/carbonado/layout/LayoutFactory.java
@@ -32,6 +32,7 @@ import java.util.Map;
 import com.amazon.carbonado.Cursor;
 import com.amazon.carbonado.FetchDeadlockException;
 import com.amazon.carbonado.FetchException;
+import com.amazon.carbonado.FetchInterruptedException;
 import com.amazon.carbonado.FetchNoneException;
 import com.amazon.carbonado.FetchTimeoutException;
 import com.amazon.carbonado.IsolationLevel;
@@ -113,8 +114,8 @@ public class LayoutFactory implements LayoutCapability {
      * @throws PersistException if type represents a new generation, but
      * persisting this information failed
      */
-    public Layout layoutFor(boolean readOnly,
-                            Class<? extends Storable> type, LayoutOptions options)
+    public Layout layoutFor(final boolean readOnly,
+                            final Class<? extends Storable> type, final LayoutOptions options)
         throws FetchException, PersistException
     {
         if (options != null) {
@@ -131,8 +132,62 @@ public class LayoutFactory implements LayoutCapability {
             }
         }
 
-        StorableInfo<?> info = StorableIntrospector.examine(type);
+        final StorableInfo<?> info = StorableIntrospector.examine(type);
 
+        // Launch layout request in a new separate thread to ensure that
+        // transaction is top-level.
+
+        class LayoutRequest extends Thread {
+            private boolean done;
+            private Layout layout;
+            private FetchException fetchEx;
+            private PersistException persistEx;
+
+            public synchronized void run() {
+                try {
+                    try {
+                        layout = layoutFor(readOnly, info, options);
+                    } catch (FetchException e) {
+                        fetchEx = e;
+                    } catch (PersistException e) {
+                        persistEx = e;
+                    }
+                } finally {
+                    done = true;
+                    notifyAll();
+                }
+            }
+
+            synchronized Layout getLayout()
+                throws FetchException, PersistException, InterruptedException
+            {
+                while (!done) {
+                    wait();
+                }
+                if (fetchEx != null) {
+                    throw fetchEx;
+                }
+                if (persistEx != null) {
+                    throw persistEx;
+                }
+                return layout;
+            }
+        }
+
+        LayoutRequest request = new LayoutRequest();
+        request.setDaemon(true);
+        request.start();
+
+        try {
+            return request.getLayout();
+        } catch (InterruptedException e) {
+            throw new FetchInterruptedException();
+        }
+    }
+
+    private Layout layoutFor(boolean readOnly, StorableInfo<?> info, LayoutOptions options)
+        throws FetchException, PersistException
+    {
         Layout layout;
         ResyncCapability resyncCap = null;
 
@@ -192,7 +247,7 @@ public class LayoutFactory implements LayoutCapability {
                             // extremely rare, unless there is a bug somewhere.
                             throw new FetchException
                                 ("Unable to generate unique layout identifier for " +
-                                 type.getName());
+                                 info.getName());
                         }
                     }
 
-- 
cgit v1.2.3