use of org.datanucleus.identity.IdentityReference in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method putObjectIntoLevel2CacheInternal.
/**
* Convenience method to add/update an object in the L2 cache.
* @param op ObjectProvider of the object to add.
* @param updateIfPresent Whether to update the L2 cache if it is present
*/
protected void putObjectIntoLevel2CacheInternal(ObjectProvider op, boolean updateIfPresent) {
Object id = op.getInternalObjectId();
if (id == null || id instanceof IdentityReference) {
return;
}
Level2Cache l2Cache = nucCtx.getLevel2Cache();
if (!updateIfPresent && l2Cache.containsOid(id)) {
// Already present and not wanting to update
return;
}
CachedPC currentCachedPC = l2Cache.get(id);
CachedPC cachedPC = getL2CacheableObject(op, currentCachedPC);
if (cachedPC != null) {
l2Cache.put(id, cachedPC);
}
if (op.getClassMetaData().getUniqueMetaData() != null) {
// Cache against any unique keys defined for this object
List<UniqueMetaData> unimds = op.getClassMetaData().getUniqueMetaData();
if (unimds != null && !unimds.isEmpty()) {
for (UniqueMetaData unimd : unimds) {
CacheUniqueKey uniKey = getCacheUniqueKeyForObjectProvider(op, unimd);
if (uniKey != null) {
l2Cache.putUnique(uniKey, cachedPC);
}
}
}
}
}
use of org.datanucleus.identity.IdentityReference 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();
}
use of org.datanucleus.identity.IdentityReference in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method putObjectsIntoLevel2Cache.
/**
* Method to put the passed objects into the L2 cache.
* Performs the "put" in batches
* @param ops The ObjectProviders whose objects are to be cached
*/
protected void putObjectsIntoLevel2Cache(Set<ObjectProvider> ops) {
int batchSize = nucCtx.getConfiguration().getIntProperty(PropertyNames.PROPERTY_CACHE_L2_BATCHSIZE);
Level2Cache l2Cache = nucCtx.getLevel2Cache();
Map<Object, CachedPC> dataToUpdate = new HashMap<>();
Map<CacheUniqueKey, CachedPC> dataUniqueToUpdate = new HashMap<>();
for (ObjectProvider op : ops) {
Object id = op.getInternalObjectId();
if (id == null || !nucCtx.isClassCacheable(op.getClassMetaData())) {
continue;
}
CachedPC currentCachedPC = l2Cache.get(id);
CachedPC cachedPC = getL2CacheableObject(op, currentCachedPC);
if (cachedPC != null && id != null && !(id instanceof IdentityReference)) {
// Only cache if something to be cached and has identity
dataToUpdate.put(id, cachedPC);
if (dataToUpdate.size() == batchSize) {
// Put this batch of objects in the L2 cache
l2Cache.putAll(dataToUpdate);
dataToUpdate.clear();
}
}
if (op.getClassMetaData().getUniqueMetaData() != null) {
// Check for any unique keys on this object, and cache against the unique key also
List<UniqueMetaData> unimds = op.getClassMetaData().getUniqueMetaData();
if (unimds != null && !unimds.isEmpty()) {
for (UniqueMetaData unimd : unimds) {
CacheUniqueKey uniKey = getCacheUniqueKeyForObjectProvider(op, unimd);
if (uniKey != null) {
dataUniqueToUpdate.put(uniKey, cachedPC);
if (dataUniqueToUpdate.size() == batchSize) {
// Put this batch of unique keyed objects in the L2 cache
l2Cache.putUniqueAll(dataUniqueToUpdate);
dataUniqueToUpdate.clear();
}
}
}
}
}
}
// Put all remaining objects
if (!dataToUpdate.isEmpty()) {
l2Cache.putAll(dataToUpdate);
dataToUpdate.clear();
}
if (!dataUniqueToUpdate.isEmpty()) {
l2Cache.putUniqueAll(dataUniqueToUpdate);
dataUniqueToUpdate.clear();
}
}
Aggregations