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);
+ }
}