Search in sources :

Example 1 with Persistable

use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.

the class StateManagerImpl method initialiseForEmbedded.

/**
 * Initialises a state manager to manage a Persistable instance that will be EMBEDDED/SERIALISED into another Persistable object.
 * The instance will not be assigned an identity in the process since it is a SCO.
 * @param pc The Persistable to manage (see copyPc also)
 * @param copyPc Whether the SM should manage a copy of the passed PC or that one
 */
public void initialiseForEmbedded(Persistable pc, boolean copyPc) {
    // Default to an embedded PC object
    objectType = ObjectProvider.EMBEDDED_PC;
    // It is embedded at this point so dont need an ID since we're not persisting it
    myID = null;
    myLC = myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.P_CLEAN);
    persistenceFlags = Persistable.LOAD_REQUIRED;
    myPC = pc;
    // Set SM for embedded PC to be this
    replaceStateManager(myPC, this);
    if (copyPc) {
        // Create a new PC with the same field values
        Persistable pcCopy = myPC.dnNewInstance(this);
        pcCopy.dnCopyFields(myPC, cmd.getAllMemberPositions());
        // Swap the managed PC to be the copy and not the input
        replaceStateManager(pcCopy, this);
        myPC = pcCopy;
        disconnectClone(pc);
    }
    // Mark all fields as loaded since we are using the passed Persistable
    for (int i = 0; i < loadedFields.length; i++) {
        loadedFields[i] = true;
    }
}
Also used : Persistable(org.datanucleus.enhancement.Persistable)

Example 2 with Persistable

use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.

the class StateManagerImpl method detachCopy.

/**
 * Method to make detached copy of this instance
 * If the object is detachable then the copy will be migrated to DETACHED state, otherwise will migrate
 * the copy to TRANSIENT. Used by "ExecutionContext.detachObjectCopy()".
 * @param state State for the detachment process
 * @return the detached Persistable instance
 */
public Persistable detachCopy(FetchPlanState state) {
    if (myLC.isDeleted()) {
        throw new NucleusUserException(Localiser.msg("026023", myPC.getClass().getName(), myID));
    }
    if (myEC.getApiAdapter().isDetached(myPC)) {
        throw new NucleusUserException(Localiser.msg("026024", myPC.getClass().getName(), myID));
    }
    if (dirty) {
        myEC.flushInternal(false);
    }
    if (isDetaching()) {
        // Object in the process of detaching (recursive) so return the object which will be the detached object
        return getReferencedPC();
    }
    // Look for an existing detached copy
    DetachState detachState = (DetachState) state;
    DetachState.Entry existingDetached = detachState.getDetachedCopyEntry(myPC);
    Persistable detachedPC;
    if (existingDetached == null) {
        // No existing detached copy - create new one
        detachedPC = myPC.dnNewInstance(this);
        detachState.setDetachedCopyEntry(myPC, detachedPC);
    } else {
        // Found one - if it's sufficient for current FetchPlanState, return it immediately
        detachedPC = (Persistable) existingDetached.getDetachedCopyObject();
        if (existingDetached.checkCurrentState()) {
            return detachedPC;
        }
    // Need to process the detached copy using current FetchPlanState
    }
    myEC.setAttachDetachReferencedObject(this, detachedPC);
    // Check if detachable ... if so then we detach a copy, otherwise we return a transient copy
    boolean detachable = myEC.getApiAdapter().isDetachable(myPC);
    // make sure a detaching PC is not read by another thread while we are detaching
    Object referencedPC = getReferencedPC();
    synchronized (referencedPC) {
        int[] detachFieldNums = getFieldsNumbersToDetach();
        if (detachable) {
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                int[] fieldsToLoad = null;
                if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
                    fieldsToLoad = ClassUtils.getFlagsSetTo(loadedFields, myFP.getMemberNumbers(), false);
                }
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("010010", StringUtils.toJVMIDString(myPC), "" + state.getCurrentFetchDepth(), StringUtils.toJVMIDString(detachedPC), StringUtils.intArrayToString(detachFieldNums), StringUtils.intArrayToString(fieldsToLoad)));
            }
            // Call any "pre-detach" listeners
            getCallbackHandler().preDetach(myPC);
        }
        try {
            setDetaching(true);
            // Handle any field loading/unloading before the detach
            if ((myEC.getFetchPlan().getDetachmentOptions() & FetchPlan.DETACH_LOAD_FIELDS) != 0) {
                // Load any unloaded fetch-plan fields
                loadUnloadedFieldsInFetchPlan();
            }
            if (myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.HOLLOW) || myLC == myEC.getNucleusContext().getApiAdapter().getLifeCycleState(LifeCycleState.P_NONTRANS)) {
                // Migrate any HOLLOW/P_NONTRANS to P_CLEAN etc
                myLC = myLC.transitionReadField(this, true);
            }
            // Create a SM for our copy object
            ObjectProvider smDetachedPC = new StateManagerImpl(myEC, cmd);
            smDetachedPC.initialiseForDetached(detachedPC, getExternalObjectId(myPC), getVersion(myPC));
            myEC.setAttachDetachReferencedObject(smDetachedPC, myPC);
            // If detached copy already existed, take note of fields previously loaded
            if (existingDetached != null) {
                smDetachedPC.retrieveDetachState(smDetachedPC);
            }
            smDetachedPC.replaceFields(detachFieldNums, new DetachFieldManager(this, cmd.getSCOMutableMemberFlags(), myFP, state, true));
            myEC.setAttachDetachReferencedObject(smDetachedPC, null);
            if (detachable) {
                // Update the object with its detached state - not to be confused with the "state" object above
                detachedPC.dnReplaceFlags();
                ((Detachable) detachedPC).dnReplaceDetachedState();
            } else {
                smDetachedPC.makeTransient(null);
            }
            // Remove its StateManager since now detached or transient
            replaceStateManager(detachedPC, null);
        } catch (Exception e) {
            // What could possibly be wrong here ? Log it and let the user provide a testcase, yeah right
            NucleusLogger.PERSISTENCE.warn("DETACH ERROR : Error thrown while detaching " + StringUtils.toJVMIDString(myPC) + " (id=" + myID + "). Provide a testcase that demonstrates this", e);
        } finally {
            setDetaching(false);
            referencedPC = null;
        }
        if (detachable && !myEC.getApiAdapter().isDetached(detachedPC)) {
            // Sanity check on the objects detached state
            throw new NucleusUserException(Localiser.msg("026025", detachedPC.getClass().getName(), myID));
        }
        if (detachable) {
            // Call any "post-detach" listeners
            getCallbackHandler().postDetach(myPC, detachedPC);
        }
    }
    return detachedPC;
}
Also used : Detachable(org.datanucleus.enhancement.Detachable) Persistable(org.datanucleus.enhancement.Persistable) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) DetachFieldManager(org.datanucleus.store.fieldmanager.DetachFieldManager) DetachState(org.datanucleus.DetachState) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) NucleusException(org.datanucleus.exceptions.NucleusException) EndOfFetchPlanGraphException(org.datanucleus.store.fieldmanager.AbstractFetchDepthFieldManager.EndOfFetchPlanGraphException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassNotResolvedException(org.datanucleus.exceptions.ClassNotResolvedException) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException)

Example 3 with Persistable

use of org.datanucleus.enhancement.Persistable in project datanucleus-core by datanucleus.

the class AppIdObjectIdFieldConsumer method storeObjectField.

public void storeObjectField(int fieldNumber, Object value) {
    if (api.isPersistable(value)) {
        // Embedded PC, so cascade down its PK fields
        Persistable pc = (Persistable) value;
        pc.dnCopyKeyFieldsFromObjectId(this, pc.dnGetObjectId());
        return;
    }
    fm.storeObjectField(fieldNumber, value);
}
Also used : Persistable(org.datanucleus.enhancement.Persistable)

Example 4 with Persistable

use of org.datanucleus.enhancement.Persistable in project datanucleus-api-jdo by datanucleus.

the class NucleusJDOHelper method getDirtyFields.

/**
 * Accessor for the names of the dirty fields of the persistable object.
 * @param obj The persistable object
 * @param pm The Persistence Manager (only required if the object is detached)
 * @return Names of the dirty fields
 */
public static String[] getDirtyFields(Object obj, PersistenceManager pm) {
    if (obj == null || !(obj instanceof Persistable)) {
        return null;
    }
    Persistable pc = (Persistable) obj;
    if (isDetached(pc)) {
        ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
        // Temporarily attach a StateManager to access the detached field information
        ObjectProvider op = ec.getNucleusContext().getObjectProviderFactory().newForDetached(ec, pc, getObjectId(pc), null);
        pc.dnReplaceStateManager(op);
        op.retrieveDetachState(op);
        String[] dirtyFieldNames = op.getDirtyFieldNames();
        pc.dnReplaceStateManager(null);
        return dirtyFieldNames;
    }
    ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
    ObjectProvider op = ec.findObjectProvider(pc);
    if (op == null) {
        return null;
    }
    return op.getDirtyFieldNames();
}
Also used : Persistable(org.datanucleus.enhancement.Persistable) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider)

Example 5 with Persistable

use of org.datanucleus.enhancement.Persistable in project datanucleus-api-jdo by datanucleus.

the class NucleusJDOHelper method getLoadedFields.

/**
 * Accessor for the names of the loaded fields of the persistable object.
 * @param obj Persistable object
 * @param pm The Persistence Manager (only required if the object is detached)
 * @return Names of the loaded fields
 */
public static String[] getLoadedFields(Object obj, PersistenceManager pm) {
    if (obj == null || !(obj instanceof Persistable)) {
        return null;
    }
    Persistable pc = (Persistable) obj;
    if (isDetached(pc)) {
        // Temporarily attach a StateManager to access the detached field information
        ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
        ObjectProvider op = ec.getNucleusContext().getObjectProviderFactory().newForDetached(ec, pc, getObjectId(pc), null);
        pc.dnReplaceStateManager(op);
        op.retrieveDetachState(op);
        String[] loadedFieldNames = op.getLoadedFieldNames();
        pc.dnReplaceStateManager(null);
        return loadedFieldNames;
    }
    ExecutionContext ec = ((JDOPersistenceManager) pm).getExecutionContext();
    ObjectProvider op = ec.findObjectProvider(pc);
    if (op == null) {
        return null;
    }
    return op.getLoadedFieldNames();
}
Also used : Persistable(org.datanucleus.enhancement.Persistable) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider)

Aggregations

Persistable (org.datanucleus.enhancement.Persistable)14 ExecutionContext (org.datanucleus.ExecutionContext)4 ObjectProvider (org.datanucleus.state.ObjectProvider)4 L2CachePopulateFieldManager (org.datanucleus.cache.L2CachePopulateFieldManager)3 L2CacheRetrieveFieldManager (org.datanucleus.cache.L2CacheRetrieveFieldManager)3 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)3 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)3 DetachFieldManager (org.datanucleus.store.fieldmanager.DetachFieldManager)3 ApiAdapter (org.datanucleus.api.ApiAdapter)2 Level2Cache (org.datanucleus.cache.Level2Cache)2 Detachable (org.datanucleus.enhancement.Detachable)2 ClassNotResolvedException (org.datanucleus.exceptions.ClassNotResolvedException)2 EndOfFetchPlanGraphException (org.datanucleus.store.fieldmanager.AbstractFetchDepthFieldManager.EndOfFetchPlanGraphException)2 AttachFieldManager (org.datanucleus.store.fieldmanager.AttachFieldManager)2 DeleteFieldManager (org.datanucleus.store.fieldmanager.DeleteFieldManager)2 FieldManager (org.datanucleus.store.fieldmanager.FieldManager)2 LoadFieldManager (org.datanucleus.store.fieldmanager.LoadFieldManager)2 MakeTransientFieldManager (org.datanucleus.store.fieldmanager.MakeTransientFieldManager)2 PersistFieldManager (org.datanucleus.store.fieldmanager.PersistFieldManager)2 SingleTypeFieldManager (org.datanucleus.store.fieldmanager.SingleTypeFieldManager)2