Search in sources :

Example 46 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.

the class SCOUtils method validateObjectForWriting.

/**
 * Method to check if an object to be stored in a SCO container is already persistent, or is managed by a
 * different ExecutionContext. If not persistent, this call will persist it.
 * If not yet flushed to the datastore this call will flush it.
 * @param ec ExecutionContext
 * @param object The object
 * @param fieldValues Values for any fields when persisting (if the object needs persisting)
 * @return Whether the object was persisted during this call
 */
public static boolean validateObjectForWriting(ExecutionContext ec, Object object, FieldValues fieldValues) {
    boolean persisted = false;
    ApiAdapter api = ec.getApiAdapter();
    if (api.isPersistable(object)) {
        ExecutionContext objectEC = api.getExecutionContext(object);
        if (objectEC != null && ec != objectEC) {
            throw new NucleusUserException(Localiser.msg("023009", StringUtils.toJVMIDString(object)), api.getIdForObject(object));
        } else if (!api.isPersistent(object)) {
            // Not persistent, so either is detached, or needs persisting for first time
            boolean exists = false;
            if (api.isDetached(object)) {
                if (ec.getBooleanProperty(PropertyNames.PROPERTY_ATTACH_SAME_DATASTORE)) {
                    // Assume that it is detached from this datastore
                    exists = true;
                } else {
                    // Check if the (attached) object exists in this datastore
                    try {
                        Object obj = ec.findObject(api.getIdForObject(object), true, false, object.getClass().getName());
                        if (obj != null) {
                            // PM.getObjectById creates a dummy object to represent this object and
                            // automatically
                            // enlists it in the txn. Evict it to avoid issues with reachability
                            ObjectProvider objSM = ec.findObjectProvider(obj);
                            if (objSM != null) {
                                ec.evictFromTransaction(objSM);
                            }
                        }
                        exists = true;
                    } catch (NucleusObjectNotFoundException onfe) {
                        exists = false;
                    }
                }
            }
            if (!exists) {
                // Persist the object
                ec.persistObjectInternal(object, fieldValues, ObjectProvider.PC);
                persisted = true;
            }
        } else {
            // Persistent state, but is it flushed to the datastore?
            ObjectProvider objectSM = ec.findObjectProvider(object);
            if (objectSM.isWaitingToBeFlushedToDatastore()) {
                // Process any fieldValues
                if (fieldValues != null) {
                    objectSM.loadFieldValues(fieldValues);
                }
                // Now flush it
                objectSM.flush();
                // Mark as being persisted since is now in the datastore
                persisted = true;
            }
        }
    }
    return persisted;
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) ExecutionContext(org.datanucleus.ExecutionContext) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ObjectProvider(org.datanucleus.state.ObjectProvider) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException)

Example 47 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.

the class FlushOrdered method execute.

/* (non-Javadoc)
     * @see org.datanucleus.FlushProcess#execute(org.datanucleus.ExecutionContext, java.util.List, java.util.List, org.datanucleus.flush.OperationQueue)
     */
public List<NucleusOptimisticException> execute(ExecutionContext ec, List<ObjectProvider> primaryOPs, List<ObjectProvider> secondaryOPs, OperationQueue opQueue) {
    // Note that opQueue is not processed directly here, but instead will be processed via callbacks from the persistence of other objects
    // TODO The opQueue needs to be processed from here instead of via the callbacks, see NUCCORE-904
    List<NucleusOptimisticException> optimisticFailures = null;
    // Make copy of ObjectProviders so we don't have ConcurrentModification issues
    Object[] toFlushPrimary = null;
    Object[] toFlushSecondary = null;
    try {
        if (// Why lock here? should be on overall flush
        ec.getMultithreaded()) {
            ec.getLock().lock();
        }
        if (primaryOPs != null) {
            toFlushPrimary = primaryOPs.toArray();
            primaryOPs.clear();
        }
        if (secondaryOPs != null) {
            toFlushSecondary = secondaryOPs.toArray();
            secondaryOPs.clear();
        }
    } finally {
        if (ec.getMultithreaded()) {
            ec.getLock().unlock();
        }
    }
    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
        int total = 0;
        if (toFlushPrimary != null) {
            total += toFlushPrimary.length;
        }
        if (toFlushSecondary != null) {
            total += toFlushSecondary.length;
        }
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("010003", total));
    }
    Set<Class> classesToFlush = null;
    if (ec.getNucleusContext().getStoreManager().getQueryManager().getQueryResultsCache() != null) {
        classesToFlush = new HashSet();
    }
    // a). primary dirty objects
    if (toFlushPrimary != null) {
        for (int i = 0; i < toFlushPrimary.length; i++) {
            ObjectProvider op = (ObjectProvider) toFlushPrimary[i];
            try {
                op.flush();
                if (classesToFlush != null && op.getObject() != null) {
                    classesToFlush.add(op.getObject().getClass());
                }
            } catch (NucleusOptimisticException oe) {
                if (optimisticFailures == null) {
                    optimisticFailures = new ArrayList();
                }
                optimisticFailures.add(oe);
            }
        }
    }
    // b). secondary dirty objects
    if (toFlushSecondary != null) {
        for (int i = 0; i < toFlushSecondary.length; i++) {
            ObjectProvider op = (ObjectProvider) toFlushSecondary[i];
            try {
                op.flush();
                if (classesToFlush != null && op.getObject() != null) {
                    classesToFlush.add(op.getObject().getClass());
                }
            } catch (NucleusOptimisticException oe) {
                if (optimisticFailures == null) {
                    optimisticFailures = new ArrayList();
                }
                optimisticFailures.add(oe);
            }
        }
    }
    if (opQueue != null) {
        if (!ec.getStoreManager().usesBackedSCOWrappers()) {
            // This ExecutionContext is not using backing store SCO wrappers, so process SCO Operations for cascade delete etc.
            opQueue.processOperationsForNoBackingStoreSCOs(ec);
        }
        opQueue.clearPersistDeleteUpdateOperations();
    }
    if (classesToFlush != null) {
        // Flush any query results from cache for these types
        Iterator<Class> queryClsIter = classesToFlush.iterator();
        while (queryClsIter.hasNext()) {
            Class cls = queryClsIter.next();
            ec.getNucleusContext().getStoreManager().getQueryManager().evictQueryResultsForType(cls);
        }
    }
    return optimisticFailures;
}
Also used : NucleusOptimisticException(org.datanucleus.exceptions.NucleusOptimisticException) ArrayList(java.util.ArrayList) ObjectProvider(org.datanucleus.state.ObjectProvider) HashSet(java.util.HashSet)

Example 48 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.

the class FlushNonReferential method flushDeleteInsertUpdateGrouped.

/**
 * Method that does the flushing of the passed ObjectProviders, grouping them into all DELETEs, then all INSERTs,
 * finally all UPDATEs. The StorePersistenceHandler will get calls to <i>deleteObjects</i>, <i>insertObjects</i>
 * and <i>updateObject</i> (for each other one). Note that this is in a separate method to allow calls by
 * other FlushProcesses that want to take advantage of the basic flush method without
 * @param opsToFlush The ObjectProviders to process
 * @param ec ExecutionContext
 * @return Any optimistic verification exceptions thrown during flush
 */
public List<NucleusOptimisticException> flushDeleteInsertUpdateGrouped(Set<ObjectProvider> opsToFlush, ExecutionContext ec) {
    List<NucleusOptimisticException> optimisticFailures = null;
    Set<Class> classesToFlush = null;
    if (ec.getNucleusContext().getStoreManager().getQueryManager().getQueryResultsCache() != null) {
        classesToFlush = new HashSet();
    }
    Set<ObjectProvider> opsToDelete = new HashSet<ObjectProvider>();
    Set<ObjectProvider> opsToInsert = new HashSet<ObjectProvider>();
    Iterator<ObjectProvider> opIter = opsToFlush.iterator();
    while (opIter.hasNext()) {
        ObjectProvider op = opIter.next();
        if (op.isEmbedded()) {
            // Embedded have nothing to flush since the owner manages it
            op.markAsFlushed();
            opIter.remove();
        } else {
            if (classesToFlush != null && op.getObject() != null) {
                classesToFlush.add(op.getObject().getClass());
            }
            if (op.getLifecycleState().isNew() && !op.isFlushedToDatastore() && !op.isFlushedNew()) {
                // P_NEW and not yet flushed to datastore
                opsToInsert.add(op);
                opIter.remove();
            } else if (op.getLifecycleState().isDeleted() && !op.isFlushedToDatastore()) {
                if (!op.getLifecycleState().isNew()) {
                    // P_DELETED
                    opsToDelete.add(op);
                    opIter.remove();
                } else if (op.getLifecycleState().isNew() && op.isFlushedNew()) {
                    // P_NEW_DELETED already persisted
                    opsToDelete.add(op);
                    opIter.remove();
                }
            }
        }
    }
    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("010046", opsToDelete.size(), opsToInsert.size(), opsToFlush.size()));
    }
    StorePersistenceHandler persistenceHandler = ec.getStoreManager().getPersistenceHandler();
    if (!opsToDelete.isEmpty()) {
        // TODO This omits some parts of sm.internalDeletePersistent
        for (ObjectProvider op : opsToDelete) {
            op.setFlushing(true);
            ec.getCallbackHandler().preDelete(op.getObject());
        }
        try {
            persistenceHandler.deleteObjects(opsToDelete.toArray(new ObjectProvider[opsToDelete.size()]));
        } catch (NucleusOptimisticException noe) {
            optimisticFailures = new ArrayList();
            Throwable[] nestedExcs = noe.getNestedExceptions();
            if (nestedExcs != null && nestedExcs.length > 1) {
                NucleusOptimisticException[] noes = (NucleusOptimisticException[]) nestedExcs;
                for (int i = 0; i < nestedExcs.length; i++) {
                    optimisticFailures.add(noes[i]);
                }
            } else {
                optimisticFailures.add(noe);
            }
        }
        for (ObjectProvider op : opsToDelete) {
            ec.getCallbackHandler().postDelete(op.getObject());
            op.setFlushedNew(false);
            op.markAsFlushed();
            op.setFlushing(false);
        }
    }
    if (!opsToInsert.isEmpty()) {
        // TODO This omits some parts of sm.internalMakePersistent
        for (ObjectProvider op : opsToInsert) {
            op.setFlushing(true);
            ec.getCallbackHandler().preStore(op.getObject());
        // TODO Make sure identity is set since user could have updated fields in preStore
        }
        persistenceHandler.insertObjects(opsToInsert.toArray(new ObjectProvider[opsToInsert.size()]));
        for (ObjectProvider op : opsToInsert) {
            ec.getCallbackHandler().postStore(op.getObject());
            op.setFlushedNew(true);
            op.markAsFlushed();
            op.setFlushing(false);
            // Update the object in the cache(s) now that version/id are set
            ec.putObjectIntoLevel1Cache(op);
        }
    }
    if (!opsToFlush.isEmpty()) {
        // Objects to update
        for (ObjectProvider op : opsToFlush) {
            try {
                op.flush();
            } catch (NucleusOptimisticException oe) {
                if (optimisticFailures == null) {
                    optimisticFailures = new ArrayList();
                }
                optimisticFailures.add(oe);
            }
        }
    }
    if (classesToFlush != null) {
        // Flush any query results from cache for these types
        Iterator<Class> queryClsIter = classesToFlush.iterator();
        while (queryClsIter.hasNext()) {
            Class cls = queryClsIter.next();
            ec.getNucleusContext().getStoreManager().getQueryManager().evictQueryResultsForType(cls);
        }
    }
    return optimisticFailures;
}
Also used : NucleusOptimisticException(org.datanucleus.exceptions.NucleusOptimisticException) ArrayList(java.util.ArrayList) ObjectProvider(org.datanucleus.state.ObjectProvider) StorePersistenceHandler(org.datanucleus.store.StorePersistenceHandler) HashSet(java.util.HashSet)

Example 49 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.

the class DeleteFieldManager method processPersistable.

/**
 * Utility method to process the passed persistable object.
 * @param pc The PC object
 */
protected void processPersistable(Object pc) {
    ObjectProvider pcOP = op.getExecutionContext().findObjectProvider(pc);
    if (pcOP != null) {
        if (pcOP.isDeleting() || pcOP.becomingDeleted()) {
            // Already becoming deleted so jump out
            return;
        }
    }
    // Delete it
    op.getExecutionContext().deleteObjectInternal(pc);
}
Also used : ObjectProvider(org.datanucleus.state.ObjectProvider)

Example 50 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.

the class PersistFieldManager method processMapContainer.

private void processMapContainer(int fieldNumber, Object container, AbstractMemberMetaData mmd) {
    TypeManager typeManager = op.getExecutionContext().getTypeManager();
    ContainerHandler<Object, MapContainerAdapter<Object>> containerHandler = typeManager.getContainerHandler(mmd.getType());
    ApiAdapter api = op.getExecutionContext().getApiAdapter();
    // Process all keys, values of the Map that are PC
    MapContainerAdapter<Object> mapAdapter = containerHandler.getAdapter(container);
    for (Entry<Object, Object> entry : mapAdapter.entries()) {
        Object mapKey = entry.getKey();
        Object mapValue = entry.getValue();
        Object newMapKey = mapKey;
        Object newMapValue = mapValue;
        if (api.isPersistable(mapKey)) {
            // Persist (or attach) the key
            int mapKeyObjectType = mmd.getMap().isEmbeddedKey() || mmd.getMap().isSerializedKey() ? ObjectProvider.EMBEDDED_MAP_KEY_PC : ObjectProvider.PC;
            newMapKey = processPersistable(mapKey, fieldNumber, mapKeyObjectType);
        }
        if (api.isPersistable(mapValue)) {
            // Persist (or attach) the value
            int mapValueObjectType = mmd.getMap().isEmbeddedValue() || mmd.getMap().isSerializedValue() ? ObjectProvider.EMBEDDED_MAP_VALUE_PC : ObjectProvider.PC;
            newMapValue = processPersistable(mapValue, fieldNumber, mapValueObjectType);
        }
        if (newMapKey != mapKey || newMapValue != mapValue) {
            // Maybe we have just have attached key or value
            boolean updateKey = false;
            boolean updateValue = false;
            if (newMapKey != mapKey) {
                ObjectProvider keyOP = op.getExecutionContext().findObjectProvider(newMapKey);
                if (keyOP.getReferencedPC() != null) {
                    // Attaching the key
                    updateKey = true;
                }
            }
            if (newMapValue != mapValue) {
                ObjectProvider valOP = op.getExecutionContext().findObjectProvider(newMapValue);
                if (valOP.getReferencedPC() != null) {
                    // Attaching the value
                    updateValue = true;
                }
            }
            if (updateKey) {
                mapAdapter.remove(mapKey);
                mapAdapter.put(newMapKey, updateValue ? newMapValue : mapValue);
            } else if (updateValue) {
                mapAdapter.put(mapKey, newMapValue);
            }
        }
    }
}
Also used : MapContainerAdapter(org.datanucleus.store.types.MapContainerAdapter) ApiAdapter(org.datanucleus.api.ApiAdapter) TypeManager(org.datanucleus.store.types.TypeManager) ObjectProvider(org.datanucleus.state.ObjectProvider)

Aggregations

ObjectProvider (org.datanucleus.state.ObjectProvider)160 ExecutionContext (org.datanucleus.ExecutionContext)85 Iterator (java.util.Iterator)43 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)34 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)25 Map (java.util.Map)22 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)22 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)21 SQLException (java.sql.SQLException)17 Collection (java.util.Collection)16 ApiAdapter (org.datanucleus.api.ApiAdapter)16 NucleusObjectNotFoundException (org.datanucleus.exceptions.NucleusObjectNotFoundException)16 SCOCollectionIterator (org.datanucleus.store.types.SCOCollectionIterator)16 ArrayList (java.util.ArrayList)14 HashSet (java.util.HashSet)14 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)14 NucleusException (org.datanucleus.exceptions.NucleusException)13 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)13 ListIterator (java.util.ListIterator)12 SQLController (org.datanucleus.store.rdbms.SQLController)12