use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method getObjectFromLevel2CacheForUnique.
/**
* Convenience method to access the identity that corresponds to a unique key, in the Level 2 cache.
* @param uniKey The CacheUniqueKey to use in lookups
* @return Identity of the associated object
*/
protected Object getObjectFromLevel2CacheForUnique(CacheUniqueKey uniKey) {
Object pc = null;
if (l2CacheEnabled) {
String cacheRetrieveMode = getLevel2CacheRetrieveMode();
if ("bypass".equalsIgnoreCase(cacheRetrieveMode)) {
// Cache retrieval currently turned off
return null;
}
Level2Cache l2Cache = nucCtx.getLevel2Cache();
CachedPC cachedPC = l2Cache.getUnique(uniKey);
if (cachedPC != null) {
Object id = cachedPC.getId();
// Create active version of cached object with ObjectProvider connected and same id
ObjectProvider op = nucCtx.getObjectProviderFactory().newForCachedPC(this, id, cachedPC);
// Object in P_CLEAN state
pc = op.getObject();
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("004006", IdentityUtils.getPersistableIdentityForId(id), StringUtils.intArrayToString(cachedPC.getLoadedFieldNumbers()), cachedPC.getVersion(), StringUtils.toJVMIDString(pc)));
}
if (tx.isActive() && tx.getOptimistic()) {
// Optimistic txns, so return as P_NONTRANS (as per JDO spec)
op.makeNontransactional();
} else if (!tx.isActive() && getApiAdapter().isTransactional(pc)) {
// Non-tx context, so return as P_NONTRANS (as per JDO spec)
op.makeNontransactional();
}
return pc;
}
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("004005", uniKey));
}
}
return null;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method deleteObjectWork.
/**
* Method to delete an object from the datastore.
* NOT to be called by internal methods. Only callable by external APIs (JDO/JPA).
* @param obj The object
*/
void deleteObjectWork(Object obj) {
ObjectProvider op = findObjectProvider(obj);
if (op == null && getApiAdapter().isDetached(obj)) {
// Delete of detached, so find a managed attached version and delete that
Object attachedObj = findObject(getApiAdapter().getIdForObject(obj), true, false, obj.getClass().getName());
op = findObjectProvider(attachedObj);
}
if (op != null) {
// Add the object to the relevant list of dirty ObjectProviders
if (indirectDirtyOPs.contains(op)) {
// Object is dirty indirectly, but now user-requested so move to direct list of dirty objects
indirectDirtyOPs.remove(op);
dirtyOPs.add(op);
} else if (!dirtyOPs.contains(op)) {
dirtyOPs.add(op);
if (l2CacheTxIds != null && nucCtx.isClassCacheable(op.getClassMetaData())) {
l2CacheTxIds.add(op.getInternalObjectId());
}
}
}
// Delete the object
deleteObjectInternal(obj);
if (pbrAtCommitHandler != null && tx.isActive()) {
if (op != null) {
if (getApiAdapter().isDeleted(obj)) {
pbrAtCommitHandler.addDeletedObject(op.getInternalObjectId());
}
}
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method getManagedObjects.
/**
* Accessor for the currently managed objects for the current transaction.
* If the transaction is not active this returns null.
* @param states States that we want the enlisted objects for
* @param classes Classes that we want the enlisted objects for
* @return Collection of managed objects enlisted in the current transaction
*/
public Set getManagedObjects(String[] states, Class[] classes) {
if (!tx.isActive()) {
return null;
}
Set objs = new HashSet();
for (ObjectProvider op : enlistedOPCache.values()) {
boolean matches = false;
for (int i = 0; i < states.length; i++) {
if (getApiAdapter().getObjectState(op.getObject()).equals(states[i])) {
for (int j = 0; j < classes.length; j++) {
if (classes[j] == op.getObject().getClass()) {
matches = true;
objs.add(op.getObject());
break;
}
}
}
if (matches) {
break;
}
}
}
return objs;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method getObjectsFromLevel2Cache.
/**
* Convenience method to access a collection of objects from the Level 2 cache.
* @param ids Collection of ids to retrieve
* @return Map of persistable objects (with connected ObjectProvider) keyed by their id if found in the L2 cache
*/
protected Map getObjectsFromLevel2Cache(Collection ids) {
if (l2CacheEnabled) {
// TODO Restrict to only those ids that are cacheable
Level2Cache l2Cache = nucCtx.getLevel2Cache();
Map<Object, CachedPC> cachedPCs = l2Cache.getAll(ids);
Map pcsById = new HashMap(cachedPCs.size());
for (Map.Entry<Object, CachedPC> entry : cachedPCs.entrySet()) {
Object id = entry.getKey();
CachedPC cachedPC = entry.getValue();
if (cachedPC != null) {
// Create active version of cached object with ObjectProvider connected and same id
ObjectProvider op = nucCtx.getObjectProviderFactory().newForCachedPC(this, id, cachedPC);
// Object in P_CLEAN state
Object pc = op.getObject();
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("004006", IdentityUtils.getPersistableIdentityForId(id), StringUtils.intArrayToString(cachedPC.getLoadedFieldNumbers()), cachedPC.getVersion(), StringUtils.toJVMIDString(pc)));
}
if (tx.isActive() && tx.getOptimistic()) {
// Optimistic txns, so return as P_NONTRANS (as per JDO spec)
op.makeNontransactional();
} else if (!tx.isActive() && getApiAdapter().isTransactional(pc)) {
// Non-tx context, so return as P_NONTRANS (as per JDO spec)
op.makeNontransactional();
}
pcsById.put(id, pc);
} else {
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("004005", IdentityUtils.getPersistableIdentityForId(id)));
}
}
}
return pcsById;
}
return null;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method performLevel2CacheUpdateAtCommit.
/**
* Method invoked during commit() to perform updates to the L2 cache.
* <ul>
* <li>Any objects modified during the current transaction will be added/updated in the L2 cache.</li>
* <li>Any objects that aren't modified but have been enlisted will be added to the L2 cache.</li>
* <li>Any objects that are modified but no longer enlisted (due to garbage collection) will be
* removed from the L2 cache (to avoid giving out old data).</li>
* </ul>
*/
private void performLevel2CacheUpdateAtCommit() {
if (l2CacheTxIds == null) {
return;
}
String cacheStoreMode = getLevel2CacheStoreMode();
if ("bypass".equalsIgnoreCase(cacheStoreMode)) {
// L2 cache storage turned off right now
return;
}
// Process all modified objects adding/updating/removing from L2 cache as appropriate
Set<ObjectProvider> opsToCache = null;
Set<Object> idsToRemove = null;
for (Object id : l2CacheTxIds) {
ObjectProvider op = enlistedOPCache.get(id);
if (op == null) {
// Modified object either no longer enlisted (GCed) OR is an embedded object without own identity. Remove from L2 if present
if (NucleusLogger.CACHE.isDebugEnabled()) {
if (nucCtx.getLevel2Cache().containsOid(id)) {
NucleusLogger.CACHE.debug(Localiser.msg("004014", id));
}
}
if (idsToRemove == null) {
idsToRemove = new HashSet<Object>();
}
idsToRemove.add(id);
} else {
// Modified object still enlisted so cacheable
Object obj = op.getObject();
Object objID = getApiAdapter().getIdForObject(obj);
if (objID == null || objID instanceof IdentityReference) {
// Must be embedded
} else if (getApiAdapter().isDeleted(obj)) {
// Object has been deleted so remove from L2 cache
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("004007", StringUtils.toJVMIDString(obj), op.getInternalObjectId()));
}
if (idsToRemove == null) {
idsToRemove = new HashSet<Object>();
}
idsToRemove.add(objID);
} else if (!getApiAdapter().isDetached(obj)) {
// Object has been added/modified so update in L2 cache
if (opsToCache == null) {
opsToCache = new HashSet<>();
}
opsToCache.add(op);
if (l2CacheObjectsToEvictUponRollback == null) {
l2CacheObjectsToEvictUponRollback = new LinkedList<Object>();
}
l2CacheObjectsToEvictUponRollback.add(id);
}
}
}
if (idsToRemove != null && !idsToRemove.isEmpty()) {
// Bulk evict from L2 cache
nucCtx.getLevel2Cache().evictAll(idsToRemove);
}
if (opsToCache != null && !opsToCache.isEmpty()) {
// Bulk put into L2 cache of required ObjectProviders
putObjectsIntoLevel2Cache(opsToCache);
}
l2CacheTxIds.clear();
l2CacheTxFieldsToUpdateById.clear();
}
Aggregations