18 package com.mysql.clusterj.core;
20 import com.mysql.clusterj.ClusterJException;
21 import com.mysql.clusterj.ClusterJFatalInternalException;
22 import com.mysql.clusterj.ClusterJUserException;
23 import com.mysql.clusterj.DynamicObject;
24 import com.mysql.clusterj.LockMode;
25 import com.mysql.clusterj.Query;
26 import com.mysql.clusterj.Transaction;
28 import com.mysql.clusterj.core.spi.DomainTypeHandler;
29 import com.mysql.clusterj.core.spi.ValueHandler;
31 import com.mysql.clusterj.core.query.QueryDomainTypeImpl;
32 import com.mysql.clusterj.core.query.QueryBuilderImpl;
33 import com.mysql.clusterj.core.query.QueryImpl;
35 import com.mysql.clusterj.core.spi.SessionSPI;
37 import com.mysql.clusterj.core.store.ClusterTransaction;
38 import com.mysql.clusterj.core.store.Db;
39 import com.mysql.clusterj.core.store.Dictionary;
40 import com.mysql.clusterj.core.store.Index;
41 import com.mysql.clusterj.core.store.IndexOperation;
42 import com.mysql.clusterj.core.store.IndexScanOperation;
43 import com.mysql.clusterj.core.store.Operation;
44 import com.mysql.clusterj.core.store.PartitionKey;
45 import com.mysql.clusterj.core.store.ResultData;
46 import com.mysql.clusterj.core.store.ScanOperation;
47 import com.mysql.clusterj.core.store.Table;
49 import com.mysql.clusterj.core.util.I18NHelper;
50 import com.mysql.clusterj.core.util.Logger;
51 import com.mysql.clusterj.core.util.LoggerFactoryService;
53 import com.mysql.clusterj.query.QueryBuilder;
54 import com.mysql.clusterj.query.QueryDefinition;
55 import com.mysql.clusterj.query.QueryDomainType;
57 import java.util.ArrayList;
58 import java.util.BitSet;
59 import java.util.Collections;
60 import java.util.Iterator;
61 import java.util.List;
105 protected final int SCAN_FINISHED = 1;
106 protected final int CACHE_EMPTY = 2;
109 protected List<StateManager>
changeList =
new ArrayList<StateManager>();
133 private Runnable postExecuteCallbackHandler =
new Runnable() {
136 postExecuteCallback.run();
138 postExecuteOperations.clear();
159 public <T> Query<T> createQuery(QueryDefinition<T> qd) {
160 if (!(qd instanceof QueryDomainTypeImpl)) {
162 local.
message(
"ERR_Exception_On_Method",
"createQuery"));
164 return new QueryImpl<T>(
this, (QueryDomainTypeImpl<T>)qd);
175 public <T> T find(Class<T> cls, Object key) {
178 ValueHandler keyHandler = domainTypeHandler.createKeyValueHandler(key);
179 ValueHandler instanceHandler = domainTypeHandler.getValueHandler(instance);
181 return (T) initializeFromDatabase(
182 domainTypeHandler, instance, instanceHandler, keyHandler);
200 public <T> T initializeFromDatabase(DomainTypeHandler<T> domainTypeHandler,
202 ValueHandler instanceHandler, ValueHandler keyHandler) {
205 ResultData rs =
selectUnique(domainTypeHandler, keyHandler, null);
208 if (instanceHandler == null) {
209 if (logger.isDetailEnabled()) logger.detail(
"Creating instanceHandler for class " + domainTypeHandler.getName() +
" table: " + domainTypeHandler.getTableName() + keyHandler.pkToString(domainTypeHandler));
211 instance = domainTypeHandler.newInstance();
212 instanceHandler = domainTypeHandler.getValueHandler(instance);
213 }
else if (instance == null) {
214 if (logger.isDetailEnabled()) logger.detail(
"Creating instance for class " + domainTypeHandler.getName() +
" table: " + domainTypeHandler.getTableName() + keyHandler.pkToString(domainTypeHandler));
216 instance = domainTypeHandler.getInstance(instanceHandler);
219 instanceHandler.found(Boolean.TRUE);
221 domainTypeHandler.objectSetValues(rs, instanceHandler);
223 domainTypeHandler.objectSetCacheManager(
this, instanceHandler);
225 domainTypeHandler.objectResetModified(instanceHandler);
227 if (logger.isDetailEnabled()) logger.detail(
"No instance found in database for class " + domainTypeHandler.getName() +
" table: " + domainTypeHandler.getTableName() + keyHandler.pkToString(domainTypeHandler));
229 if (instanceHandler != null) {
231 instanceHandler.found(Boolean.FALSE);
236 }
catch (ClusterJException ex) {
249 private void setPartitionKey(DomainTypeHandler<?> domainTypeHandler,
250 ValueHandler keyHandler) {
254 domainTypeHandler.createPartitionKey(keyHandler);
264 public <T> T newInstance(Class<T> cls) {
274 public <T> T newInstance(Class<T> cls, Object key) {
277 domainTypeHandler.objectSetKeys(key, instance);
290 public <T> T load(
final T
object) {
291 if (
object == null) {
294 if (Iterable.class.isAssignableFrom(
object.getClass())) {
295 Iterable<?> instances = (Iterable<?>)
object;
296 for (Object instance:instances) {
301 if (
object.getClass().isArray()) {
302 Object[] instances = (Object[])
object;
303 for (Object instance:instances) {
311 final ValueHandler instanceHandler = domainTypeHandler.getValueHandler(
object);
312 setPartitionKey(domainTypeHandler, instanceHandler);
313 Table storeTable = domainTypeHandler.getStoreTable();
317 domainTypeHandler.operationSetKeys(instanceHandler, op);
319 domainTypeHandler.operationGetValues(op);
320 final ResultData rs = op.resultData(
false);
321 final SessionImpl cacheManager =
this;
323 Runnable postExecuteOperation =
new Runnable() {
327 instanceHandler.found(Boolean.TRUE);
329 domainTypeHandler.objectSetValues(rs, instanceHandler);
331 domainTypeHandler.objectSetCacheManager(cacheManager, instanceHandler);
333 domainTypeHandler.objectResetModified(instanceHandler);
336 instanceHandler.found(Boolean.FALSE);
353 public Boolean
found(Object instance) {
354 if (instance == null) {
358 return ((DynamicObject)instance).found();
370 public <T> T makePersistent(T
object) {
371 if (
object == null) {
374 if (Iterable.class.isAssignableFrom(
object.getClass())) {
376 Iterable<?> instances = (Iterable<?>)
object;
377 for (Object instance:instances) {
378 makePersistent(instance);
383 if (
object.getClass().isArray()) {
385 Object[] instances = (Object[])
object;
386 for (Object instance:instances) {
387 makePersistent(instance);
393 ValueHandler valueHandler = domainTypeHandler.getValueHandler(
object);
394 insert(domainTypeHandler, valueHandler);
398 public Operation insert(
399 DomainTypeHandler<?> domainTypeHandler, ValueHandler valueHandler) {
401 setPartitionKey(domainTypeHandler, valueHandler);
403 Table storeTable = null;
405 storeTable = domainTypeHandler.getStoreTable();
408 domainTypeHandler.operationSetKeys(valueHandler, op);
409 domainTypeHandler.operationSetModifiedNonPKValues(valueHandler, op);
411 domainTypeHandler.objectResetModified(valueHandler);
412 }
catch (ClusterJUserException cjuex) {
415 }
catch (ClusterJException cjex) {
417 logger.error(local.
message(
"ERR_Insert", storeTable.getName()));
418 throw new ClusterJException(
419 local.
message(
"ERR_Insert", storeTable.getName()), cjex);
420 }
catch (RuntimeException rtex) {
422 logger.error(local.
message(
"ERR_Insert", storeTable.getName()));
423 throw new ClusterJException(
424 local.
message(
"ERR_Insert", storeTable.getName()), rtex);
437 List<Object> result =
new ArrayList<Object>();
438 for (Object instance:instances) {
439 result.add(makePersistent(instance));
452 public <T>
void deletePersistent(Class<T> cls, Object key) {
454 ValueHandler keyValueHandler = domainTypeHandler.createKeyValueHandler(key);
455 delete(domainTypeHandler, keyValueHandler);
464 if (
object == null) {
468 ValueHandler valueHandler = domainTypeHandler.getValueHandler(
object);
469 delete(domainTypeHandler, valueHandler);
474 Table storeTable = domainTypeHandler.getStoreTable();
475 setPartitionKey(domainTypeHandler, valueHandler);
479 domainTypeHandler.operationSetKeys(valueHandler, op);
483 local.
message(
"ERR_Delete", storeTable.getName()), ex);
494 for (Iterator it = objects.iterator(); it.hasNext();) {
495 deletePersistent(it.next());
514 Table storeTable = domainTypeHandler.getStoreTable();
515 String tableName = storeTable.getName();
519 op =
clusterTransaction.getTableScanOperationLockModeExclusiveScanFlagKeyInfo(storeTable);
525 local.
message(
"ERR_Delete_All", tableName), ex);
539 boolean done =
false;
540 boolean fetch =
true;
546 int result = op.nextResult(fetch);
549 op.deleteCurrentTuple();
556 if (cacheCount != 0) {
568 local.
message(
"ERR_Next_Result_Illegal", result));
586 setPartitionKey(domainTypeHandler, keyHandler);
587 Table storeTable = domainTypeHandler.getStoreTable();
591 domainTypeHandler.operationSetKeys(keyHandler, op);
593 domainTypeHandler.operationGetValues(op);
606 if (
object == null) {
610 if (logger.isDetailEnabled()) logger.detail(
"UpdatePersistent on object " +
object);
611 ValueHandler valueHandler = domainTypeHandler.getValueHandler(
object);
612 update(domainTypeHandler, valueHandler);
617 setPartitionKey(domainTypeHandler, valueHandler);
618 Table storeTable = null;
621 storeTable = domainTypeHandler.getStoreTable();
623 domainTypeHandler.operationSetKeys(valueHandler, op);
624 domainTypeHandler.operationSetModifiedNonPKValues(valueHandler, op);
625 if (logger.isDetailEnabled()) logger.detail(
"Updated object " +
630 local.
message(
"ERR_Update", storeTable.getName()) ,ex);
641 for (Iterator it = objects.iterator(); it.hasNext();) {
650 public <T> T savePersistent(T instance) {
652 if (logger.isDetailEnabled()) logger.detail(
"UpdatePersistent on object " + instance);
653 ValueHandler valueHandler = domainTypeHandler.getValueHandler(instance);
655 setPartitionKey(domainTypeHandler, valueHandler);
656 Table storeTable = null;
658 storeTable = domainTypeHandler.getStoreTable();
661 domainTypeHandler.operationSetKeys(valueHandler, op);
662 domainTypeHandler.operationSetModifiedNonPKValues(valueHandler, op);
663 if (logger.isDetailEnabled()) logger.detail(
"Wrote object " +
668 local.
message(
"ERR_Write", storeTable.getName()) ,ex);
678 List<Object> result =
new ArrayList<Object>();
680 for (Iterator it = instances.iterator(); it.hasNext();) {
681 result.add(savePersistent(it.next()));
717 local.
message(
"ERR_Session_Closed"));
725 if (logger.isDebugEnabled()) logger.debug(
"begin transaction.");
727 handleTransactionException();
738 if (partitionKey != null) {
745 local.
message(
"ERR_Ndb_Start"), ex);
753 if (logger.isDebugEnabled()) logger.debug(
"commit transaction.");
755 handleTransactionException();
766 local.
message(
"ERR_Transaction_Rollback_Only"));
769 local.
message(
"ERR_Transaction_Rollback_Only"), ex);
786 if (logger.isDebugEnabled()) logger.debug(
"roll back transaction.");
788 handleTransactionException();
801 local.
message(
"ERR_Transaction_Execute",
"rollback"), ex);
815 if (logger.isDebugEnabled()) logger.debug(
"start AutoTransaction");
817 handleTransactionException();
824 if (logger.isDebugEnabled()) logger.debug(
"end AutoTransaction");
826 handleTransactionException();
833 if (logger.isDebugEnabled()) logger.debug(
"fail AutoTransaction");
837 protected void handleTransactionException() {
838 if (transactionException == null) {
842 transactionException = null;
880 public boolean isActive() {
889 transactionException = ex;
896 local.
message(
"ERR_Transaction_Must_Be_Active_For_Method",
903 local.
message(
"ERR_Transaction_Must_Be_Active_For_Method",
913 return transactionStateAutocommit;
915 transactionException = ex;
922 local.
message(
"ERR_Transaction_Auto_Start",
"end"));
927 local.
message(
"ERR_Transaction_Auto_Start",
"end"));
936 public boolean isActive() {
942 local.
message(
"ERR_Transaction_Must_Not_Be_Active_For_Method",
953 transactionException = ex;
963 transactionException = ex;
985 protected TransactionState transactionStateAutocommit =
986 new TransactionState() {
988 public boolean isActive() {
992 public TransactionState
begin() {
994 local.
message(
"ERR_Transaction_Auto_End",
"begin"));
997 public TransactionState
commit() {
998 throw new ClusterJFatalInternalException(
999 local.
message(
"ERR_Transaction_Auto_End",
"commit"));
1002 public TransactionState
rollback() {
1003 throw new ClusterJFatalInternalException(
1004 local.
message(
"ERR_Transaction_Auto_End",
"rollback"));
1007 public TransactionState start() {
1010 return transactionStateAutocommit;
1013 public TransactionState end() {
1015 return transactionStateAutocommit;
1019 }
catch (ClusterJException ex) {
1020 transactionException = ex;
1024 throw new ClusterJFatalInternalException(
1025 local.
message(
"ERR_Transaction_Auto_Start",
"end"));
1029 public TransactionState fail() {
1034 }
catch (ClusterJException ex) {
1048 DomainTypeHandler<T> domainTypeHandler =
1050 return domainTypeHandler;
1059 DomainTypeHandler<T> domainTypeHandler =
1061 return domainTypeHandler;
1072 boolean isActive() {
1089 private void assertActive() {
1092 local.
message(
"ERR_Transaction_Must_Be_Active"));
1100 private void assertNotActive(
String methodName) {
1102 throw new ClusterJUserException(
1103 local.
message(
"ERR_Transaction_Must_Not_Be_Active_For_Method",
1114 throw new UnsupportedOperationException(
1115 local.
message(
"ERR_NotImplemented"));
1139 local.
message(
"ERR_Index_Scan", storeTable.getName(), storeIndex.
getName()), ex);
1156 local.
message(
"ERR_Index_Scan", storeTable.getName(), storeIndex.
getName()), ex);
1173 local.
message(
"ERR_Index_Scan", storeTable.getName(), storeIndex.
getName()), ex);
1189 local.
message(
"ERR_Table_Scan", storeTable.getName()), ex);
1205 local.
message(
"ERR_Table_Scan", storeTable.getName()), ex);
1222 local.
message(
"ERR_Unique_Index", storeTable.getName(), storeIndex.
getName()), ex);
1238 local.
message(
"ERR_Select", storeTable), ex);
1254 local.
message(
"ERR_Delete", storeTable), ex);
1271 local.
message(
"ERR_Unique_Index_Delete", storeTable.getName(), storeIndex.
getName()), ex);
1276 if (logger.isDetailEnabled()) logger.detail(
"flush changes with changeList size: " +
changeList.size());
1289 public List getChangeList() {
1290 return Collections.unmodifiableList(
changeList);
1294 makePersistent(instance);
1297 public void remove(Object instance) {
1298 deletePersistent(instance);
1307 String tableName = domainTypeHandler.getTableName();
1311 local.
message(
"ERR_Set_Partition_Key_After_Enlistment", tableName));
1314 if (this.partitionKey != null) {
1316 local.
message(
"ERR_Set_Partition_Key_Twice", tableName));
1319 this.partitionKey= domainTypeHandler.createPartitionKey(handler);
1334 domainTypeHandler.objectMarkModified(handler, fieldName);
1358 public <T> QueryDomainType<T> createQueryDomainType(DomainTypeHandler<T> domainTypeHandler) {
1360 return builder.createQueryDefinition(domainTypeHandler);
1384 this.lockmode = lockmode;