You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2012/01/25 03:01:30 UTC

svn commit: r1235594 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-slice/src/main/java/org/apache/openjpa/slice/ openjpa-slice/src/test/java/org/apache/op...

Author: ppoddar
Date: Wed Jan 25 02:01:30 2012
New Revision: 1235594

URL: http://svn.apache.org/viewvc?rev=1235594&view=rev
Log:
OPENJPA-2099: Align Slice threading model and Select reuse threading model

Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
    openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceThread.java
    openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=1235594&r1=1235593&r2=1235594&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Jan 25 02:01:30 2012
@@ -83,13 +83,14 @@ import org.apache.openjpa.util.UserExcep
  * @author Abe White
  * @nojavadoc
  */
+@SuppressWarnings({ "serial", "deprecation" })
 public class JDBCStoreQuery 
     extends ExpressionStoreQuery {
 
     private static final Table INVALID = new Table();
 
     // add all standard filter and aggregate listeners to these maps
-    private static final Map _listeners = new HashMap();
+    private static final Map<String,FilterListener> _listeners = new HashMap<String, FilterListener>();
 
     static {
         // deprecated extensions
@@ -186,8 +187,8 @@ public class JDBCStoreQuery 
         ExpContext ctx = new ExpContext(_store, params, fetch);
 
         // add selects with populate WHERE conditions to list
-        List sels = new ArrayList(mappings.length);
-        List selMappings = new ArrayList(mappings.length);
+        List<Select> sels = new ArrayList<Select>(mappings.length);
+        List<ClassMapping> selMappings = new ArrayList<ClassMapping>(mappings.length);
         BitSet subclassBits = new BitSet();
         BitSet nextBits = new BitSet();
         boolean unionable = createWhereSelects(sels, mappings, selMappings,
@@ -335,8 +336,8 @@ public class JDBCStoreQuery 
      * Generate the selects with WHERE conditions needed to execute the query
      * for the given mappings.
      */
-    private boolean createWhereSelects(List sels, ClassMapping[] mappings,
-        List selMappings, boolean subclasses, BitSet subclassBits,
+    private boolean createWhereSelects(List<Select> sels, ClassMapping[] mappings,
+        List<ClassMapping> selMappings, boolean subclasses, BitSet subclassBits,
         BitSet nextBits, ExpressionFactory[] facts, QueryExpressions[] exps,
         QueryExpressionsState[] states, ExpContext ctx, int subclassMode) {
         Number optHint = (Number) ctx.fetch.getHint
@@ -364,12 +365,12 @@ public class JDBCStoreQuery 
             else if (this.ctx.isUnique())
                 sel.setExpectedResultCount(1, false);
             
-            List selectFrom = getJoinedTableMeta(sel);
+            List<ClassMapping> selectFrom = getJoinedTableMeta(sel);
             int size = 0;
             if (selectFrom != null) {
                 size = selectFrom.size();
                 for (int j = 0; j < size; j++) {
-                    ClassMapping vert = (ClassMapping)selectFrom.get(j); 
+                    ClassMapping vert = selectFrom.get(j); 
                     selMappings.add(vert);
                     if (j == size - 1) {
                         nextBits.set(sels.size());
@@ -388,7 +389,7 @@ public class JDBCStoreQuery 
                         nextBits.set(sels.size());
                         sels.add(sel);
                     } else
-                        sels.add(sel.fullClone(1));
+                        sels.add((Select)sel.fullClone(1));
                 }
             }
             
@@ -400,17 +401,17 @@ public class JDBCStoreQuery 
         return unionable;
     }
     
-    private List getJoinedTableMeta(Select sel) {
-        List selectFrom = sel.getJoinedTableClassMeta();
-        List exSelectFrom = sel.getExcludedJoinedTableClassMeta();
+    private List<ClassMapping> getJoinedTableMeta(Select sel) {
+        List<ClassMapping> selectFrom = sel.getJoinedTableClassMeta();
+        List<ClassMapping> exSelectFrom = sel.getExcludedJoinedTableClassMeta();
         if (exSelectFrom == null)
             return selectFrom;
         if (selectFrom == null)
             return null;
         int size = selectFrom.size();
-        List retList = new ArrayList(size);
+        List<ClassMapping> retList = new ArrayList<ClassMapping>(size);
         for (int i = 0; i < size; i++) {
-            Object obj = selectFrom.get(i);
+        	ClassMapping obj = selectFrom.get(i);
             if (!exSelectFrom.contains(obj))
                 retList.add(obj);
         }
@@ -430,15 +431,15 @@ public class JDBCStoreQuery 
             || !hasVerticalSubclasses(mapping))
             return new ClassMapping[] { mapping };
 
-        List subs = new ArrayList(4);
+        List<ClassMapping> subs = new ArrayList<ClassMapping>(4);
         addSubclasses(mapping, subs);
-        return (ClassMapping[]) subs.toArray(new ClassMapping[subs.size()]);
+        return subs.toArray(new ClassMapping[subs.size()]);
     }
 
     /**
      * Recursive helper to add mappings for subclasses to the given list.
      */
-    private void addSubclasses(ClassMapping mapping, Collection subs) {
+    private void addSubclasses(ClassMapping mapping, Collection<ClassMapping> subs) {
         // possible future optimizations:
         // - if no fields in meta or its subclasses (and not in an
         //   already-selected table) are in the current fetch
@@ -699,8 +700,8 @@ public class JDBCStoreQuery 
         ExpContext ctx = new ExpContext(_store, params, fetch);
 
         // add selects with populate WHERE conditions to list
-        List sels = new ArrayList(mappings.length);
-        List selMappings = new ArrayList(mappings.length);
+        List<Select> sels = new ArrayList<Select>(mappings.length);
+        List<ClassMapping> selMappings = new ArrayList<ClassMapping>(mappings.length);
         BitSet subclassBits = new BitSet();
         BitSet nextBits = new BitSet();
         boolean unionable = createWhereSelects(sels, mappings, selMappings,
@@ -797,11 +798,11 @@ public class JDBCStoreQuery 
             (org.apache.openjpa.jdbc.kernel.exps.Math) value;
         Val value1 = mathVal.getVal1();
         Object val1 = getValue(value1, ob, params, sm);
-        Class c1 = value1.getType();
+        Class<?> c1 = value1.getType();
 
         Val value2 = mathVal.getVal2();
         Object val2 = getValue(value2, ob, params, sm);
-        Class c2 = value2.getType();
+        Class<?> c2 = value2.getType();
 
         String op = mathVal.getOperation();
         if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.ADD)) 
@@ -942,7 +943,7 @@ public class JDBCStoreQuery 
         org.apache.openjpa.jdbc.kernel.exps.Abs absVal = 
             (org.apache.openjpa.jdbc.kernel.exps.Abs) value;
         Object val = getValue(absVal.getValue(), ob, params, sm);
-        Class c = val.getClass();
+        Class<?> c = val.getClass();
         if (c == Integer.class)
             return Integer.valueOf(java.lang.Math.abs(((Integer) val).intValue()));
         else if (c == Float.class)
@@ -959,7 +960,7 @@ public class JDBCStoreQuery 
         org.apache.openjpa.jdbc.kernel.exps.Sqrt sqrtVal = 
             (org.apache.openjpa.jdbc.kernel.exps.Sqrt) value;
         Object val = getValue(sqrtVal.getValue(), ob, params, sm);
-        Class c = val.getClass();
+        Class<?> c = val.getClass();
         if (c == Integer.class)
             return Double.valueOf(java.lang.Math.sqrt(((Integer) val).doubleValue()));
         else if (c == Float.class)

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java?rev=1235594&r1=1235593&r2=1235594&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/BindParameter.java Wed Jan 25 02:01:30 2012
@@ -18,6 +18,9 @@
  */
 package org.apache.openjpa.jdbc.sql;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.openjpa.jdbc.schema.Column;
 
 
@@ -31,7 +34,7 @@ import org.apache.openjpa.jdbc.schema.Co
  * select. 
  * <br><b>NOTE:</b>
  * The primary assumption of usage is that the binding parameter values to a cached select and
- * executing it are carried out in the same thread. 
+ * executing it are carried out in the same (or <em>equivalent</em>) thread. 
  * <br> 
  * The parameter is further qualified by whether it is user specified (e.g. from a query parameter) 
  * or internally generated (e.g. a discriminator value for inheritance join). A database column can 
@@ -51,7 +54,7 @@ public class BindParameter {
 	private final Column  _column;
 	// key of this parameter
 	private final Object  _key;
-	private ThreadLocal<Object> _value = new ThreadLocal<Object>();
+	private Map<Thread, Object> _value = new HashMap<Thread, Object>();
 	
 	/**
 	 * Constructs a parameter with given key, column and user flag.
@@ -67,21 +70,34 @@ public class BindParameter {
 		_key = key;
 		_user = user;
 		_column = column;
-		_value.set(value);
+		_value.put(Thread.currentThread(), value);
 	}
 	
 	/**
-	 * Gets the value bound to this parameter. Can be null.
+	 * Gets the value bound to this parameter for the calling thread. Can be null.
+	 * 
+	 * @exception if the current thread or its equivalent never bound a value
+	 * to this parameter.
 	 */
 	public Object getValue() {
-		return _value.get();
+		Thread current = Thread.currentThread();
+		if (!_value.containsKey(current)) {
+			// calling thread may be a child of the thread that inserted the value.
+			// This is for SliceThread
+			for (Map.Entry<Thread, Object> e : _value.entrySet()) {
+				if (isEquivalent(e.getKey(), current)) 
+					return e.getValue();
+			}
+			throw new IllegalStateException("No value for " + current + ". Known threads " + _value.keySet());
+		}
+		return _value.get(current);
 	}
 	
 	/**
 	 * Binds the given value to this parameter. Can be null.
 	 */
 	public void setValue(Object value) {
-		_value.set(value);
+		_value.put(Thread.currentThread(),value);
 	}
 
 	/**
@@ -105,4 +121,9 @@ public class BindParameter {
 	public Object getKey() {
 		return _key;
 	}	
+	
+	boolean isEquivalent(Thread a, Thread b) {
+		if (a == b) return true;
+		return a.equals(b) || b.equals(a);
+	}
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=1235594&r1=1235593&r2=1235594&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java Wed Jan 25 02:01:30 2012
@@ -63,11 +63,39 @@ import org.apache.openjpa.util.Id;
 import org.apache.openjpa.util.InternalException;
 
 /**
- * Standard {@link Select} implementation. Usage note: though this class
- * implements {@link Joins}, it should not be used for joining directly.
- * Instead, use the return value of {@link #newJoins}.
+ * Standard {@link Select} implementation. 
+ * <br>
+ * This critical construct holds information to form a SQL <tt>SELECT</tt> statement.
+ * The structure imitates SQL components such a {@link Selects projection terms}, 
+ * {@link SelectImpl#_where <tt>WHERE</tt>} clause, {@link SelectImpl#_ordering 
+ * <tt>ORDER BY</tt>} clause, {@link SelectImpl#_subsels sub-queries} etc. 
+ * It also maintains tables and columns involved in the selection along with
+ * their join information. 
+ * <br>
+ * This structure is capable of holding other independent instances for fetching
+ * data for related fields by either eager or parallel execution. 
+ * <br>
+ * This instance is {@link #execute(JDBCStore, JDBCFetchConfiguration) executable}.
+ * After execution, this instance becomes {@link #isReadOnly() immutable} i.e. any 
+ * structural modification is {@link #assertMutable() prohibited}. The only modification 
+ * possible is by {@link #bindParameter(SQLBuffer, Object[], Column[], PathJoins) binding}
+ * different values to existing {@link BindParameter parameters}.
+ * <br>
+ * The {@link SelectResult result} from executing this instance of a <tt>JDBC</tt>-enabled
+ * database is available for field values to be populated in in-memory persistent entities.
+ * The access mechanics is critical to performance, and hence an {@link Selects#isOptimizable() 
+ * heuristics} is applied for optimization.
+ * <br>
+ * Usage note: 
+ * <LI>a) though this class implements {@link Joins}, it should not be used for 
+ * joining directly. Instead, use the return value of {@link #newJoins}.
+ * <LI>b) if this instance is concurrently shared based on {@link JDBCConfiguration#getSelectCacheEnabled()
+ * <tt>openjpa.jdbc.CachesSelect</tt>} setting, then the caller must ensure that the 
+ * parameters are bound in the same or {@link BindParameter#isEquivalent(Thread, Thread) equivalent}
+ * thread in which this instance is executed. 
  *
  * @author Abe White
+ * @author Pinaki Poddar
  * @nojavadoc
  */
 public class SelectImpl

Modified: openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceThread.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceThread.java?rev=1235594&r1=1235593&r2=1235594&view=diff
==============================================================================
--- openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceThread.java (original)
+++ openjpa/trunk/openjpa-slice/src/main/java/org/apache/openjpa/slice/SliceThread.java Wed Jan 25 02:01:30 2012
@@ -50,6 +50,36 @@ public class SliceThread extends Thread 
         return _parent;
     }
     
+    /**
+     * This thread equals itself (of course), its parent and any of its siblings.
+     * Essentially all slice threads are equal.
+     * <br>
+     * Note: this definition of equality breaks the core definition i.e. if 
+     * <tt>P</tt> is parent thread of a slice child <tt>S</tt>, then
+     * <tt>S.equals(P)</tt>, but <em>not</em> <tt>P.equals(S)</tt>.
+     */
+    @Override
+    public boolean equals(Object other) {
+    	if (other == this) return true;
+    	if (other instanceof SliceThread) {
+    		return ((SliceThread)other)._parent == this._parent;
+    	}
+    	return this._parent == other; 
+    }
+    
+    /**
+     * Hash code of this thread is same as its parent.
+     */
+    @Override
+    public int hashCode() {
+    	return _parent.hashCode();
+    }
+    
+    @Override 
+    public String toString() {
+    	return '[' + getClass().getSimpleName() + '-'+ getName() + " child of " + _parent + ']';
+    }
+    
     /** 
      * Create a cached pool of <em>slice</em> threads.
      * The thread factory creates specialized threads for preferential locking treatment.

Modified: openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java?rev=1235594&r1=1235593&r2=1235594&view=diff
==============================================================================
--- openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java (original)
+++ openjpa/trunk/openjpa-slice/src/test/java/org/apache/openjpa/slice/TestBasic.java Wed Jan 25 02:01:30 2012
@@ -356,5 +356,18 @@ public class TestBasic extends SliceTest
         assertNotNull(newP);
         assertEquals("newslice", SlicePersistence.getSlice(newP));
     }
+    
+    public void testSliceThreadEqualsParentAndSiblings() {
+    	Thread parent = new Thread();
+    	SliceThread s1 = new SliceThread(parent, null);
+    	SliceThread s2 = new SliceThread(parent, null);
+    	
+    	assertEquals(s1, parent);
+    	assertEquals(s2, parent);
+    	assertEquals(s1, s2);
+    	assertNotSame(parent, s1);
+    	assertNotSame(parent, s2);
+    	assertNotSame(s1, s2);
+    }
 
 }