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;