use of org.datanucleus.cache.Level2Cache in project tests by datanucleus.
the class CacheTest method testL2CacheAfterReadApplicationIdentity.
/**
* Test for storage of an object in the L2 cache from a query or from getObjectById.
*/
public void testL2CacheAfterReadApplicationIdentity() {
Properties userProps = new Properties();
userProps.setProperty(PropertyNames.PROPERTY_CACHE_L1_TYPE, "weak");
userProps.setProperty(PropertyNames.PROPERTY_CACHE_L2_TYPE, "weak");
PersistenceManagerFactory cachePMF = getPMF(1, userProps);
try {
// Create some data we can use for access
PersistenceManager pm = cachePMF.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
DataStoreCache l2Cache = cachePMF.getDataStoreCache();
l2Cache.pinAll(true, Vote.class);
tx.begin();
Vote vote1 = new Vote(1, "Vote 1");
pm.makePersistent(vote1);
Vote vote2 = new Vote(2, "Vote 2");
pm.makePersistent(vote2);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Error persisting basic data necessary to run optimistic L2 test");
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
Level2Cache l2Cache = ((JDODataStoreCache) cachePMF.getDataStoreCache()).getLevel2Cache();
assertEquals("Incorrect number of pinned objects", 2, l2Cache.getNumberOfPinnedObjects());
assertEquals("Incorrect number of unpinned objects", 0, l2Cache.getNumberOfUnpinnedObjects());
l2Cache.evictAll();
assertEquals("Incorrect number of pinned objects after evict", 0, l2Cache.getNumberOfPinnedObjects());
assertEquals("Incorrect number of unpinned objects after evict", 0, l2Cache.getNumberOfUnpinnedObjects());
// Try getObjectById
pm = cachePMF.getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
Vote vote1 = pm.getObjectById(Vote.class, 1);
Vote vote2 = pm.getObjectById(Vote.class, 2);
assertNotNull(vote1);
assertNotNull(vote2);
assertEquals("Incorrect number of pinned objects after getObjectById", 2, l2Cache.getNumberOfPinnedObjects());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Error updating object that was retrieved from the L2 cache : " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
assertEquals("Incorrect number of pinned objects", 2, l2Cache.getNumberOfPinnedObjects());
assertEquals("Incorrect number of unpinned objects", 0, l2Cache.getNumberOfUnpinnedObjects());
l2Cache.evictAll();
assertEquals("Incorrect number of pinned objects after evict", 0, l2Cache.getNumberOfPinnedObjects());
assertEquals("Incorrect number of unpinned objects after evict", 0, l2Cache.getNumberOfUnpinnedObjects());
// Try Query
pm = cachePMF.getPersistenceManager();
tx = pm.currentTransaction();
try {
tx.begin();
Query query = pm.newQuery(Vote.class);
Collection votes = (Collection) query.execute();
Iterator iter = votes.iterator();
while (iter.hasNext()) {
iter.next();
}
assertEquals("Incorrect number of pinned objects after Query", 2, l2Cache.getNumberOfPinnedObjects());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Error retrieving object from the L2 cache : " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
} finally {
clean(cachePMF, Vote.class);
cachePMF.close();
}
}
use of org.datanucleus.cache.Level2Cache in project datanucleus-core by datanucleus.
the class StateManagerImpl method loadFieldsFromLevel2Cache.
/**
* Convenience method to retrieve field values from an L2 cached object if they are loaded in that object.
* If the object is not in the L2 cache then just returns, and similarly if the required fields aren't available.
* @param fieldNumbers Numbers of fields to load from the L2 cache
* @return The fields that couldn't be loaded
*/
protected int[] loadFieldsFromLevel2Cache(int[] fieldNumbers) {
// Only continue if there are fields, and not being deleted/flushed etc
if (fieldNumbers == null || fieldNumbers.length == 0 || myEC.isFlushing() || myLC.isDeleted() || isDeleting() || getExecutionContext().getTransaction().isCommitting()) {
return fieldNumbers;
}
// TODO Drop this check when we're confident that this doesn't affect some use-cases
if (!myEC.getNucleusContext().getConfiguration().getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_LOADFIELDS, true)) {
return fieldNumbers;
}
Level2Cache l2cache = myEC.getNucleusContext().getLevel2Cache();
if (l2cache != null && myEC.getNucleusContext().isClassCacheable(cmd)) {
CachedPC<Persistable> cachedPC = l2cache.get(myID);
if (cachedPC != null) {
int[] cacheFieldsToLoad = ClassUtils.getFlagsSetTo(cachedPC.getLoadedFields(), fieldNumbers, true);
if (cacheFieldsToLoad != null && cacheFieldsToLoad.length > 0) {
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("026034", StringUtils.toJVMIDString(getObject()), myID, StringUtils.intArrayToString(cacheFieldsToLoad)));
}
L2CacheRetrieveFieldManager l2RetFM = new L2CacheRetrieveFieldManager(this, cachedPC);
this.replaceFields(cacheFieldsToLoad, l2RetFM);
int[] fieldsNotLoaded = l2RetFM.getFieldsNotLoaded();
if (fieldsNotLoaded != null) {
for (int i = 0; i < fieldsNotLoaded.length; i++) {
loadedFields[fieldsNotLoaded[i]] = false;
}
}
}
}
}
return ClassUtils.getFlagsSetTo(loadedFields, fieldNumbers, false);
}
use of org.datanucleus.cache.Level2Cache in project datanucleus-core by datanucleus.
the class StateManagerImpl method updateLevel2CacheForFields.
/**
* Convenience method to update a Level2 cached version of this object if cacheable
* and has not been modified during this transaction.
* @param fieldNumbers Numbers of fields to update in L2 cached object
*/
protected void updateLevel2CacheForFields(int[] fieldNumbers) {
String updateMode = (String) myEC.getProperty(PropertyNames.PROPERTY_CACHE_L2_UPDATE_MODE);
if (updateMode != null && updateMode.equalsIgnoreCase("commit-only")) {
return;
}
if (fieldNumbers == null || fieldNumbers.length == 0) {
return;
}
Level2Cache l2cache = myEC.getNucleusContext().getLevel2Cache();
if (l2cache != null && myEC.getNucleusContext().isClassCacheable(cmd) && !myEC.isObjectModifiedInTransaction(myID)) {
CachedPC<Persistable> cachedPC = l2cache.get(myID);
if (cachedPC != null) {
// This originally just updated the L2 cache for fields where the L2 cache didn't have a value for that field, like this
/*
int[] cacheFieldsToLoad = ClassUtils.getFlagsSetTo(cachedPC.getLoadedFields(), fieldNumbers, false);
if (cacheFieldsToLoad == null || cacheFieldsToLoad.length == 0)
{
return;
}
*/
int[] cacheFieldsToLoad = fieldNumbers;
CachedPC copyCachedPC = cachedPC.getCopy();
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("026033", StringUtils.toJVMIDString(getObject()), myID, StringUtils.intArrayToString(cacheFieldsToLoad)));
}
provideFields(cacheFieldsToLoad, new L2CachePopulateFieldManager(this, copyCachedPC));
// Replace the current L2 cached object with this one
myEC.getNucleusContext().getLevel2Cache().put(getInternalObjectId(), copyCachedPC);
}
}
}
use of org.datanucleus.cache.Level2Cache 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();
}
}
use of org.datanucleus.cache.Level2Cache in project tests by datanucleus.
the class CacheTest method testL2LoadedFields.
/**
* Test to check the retrieval of an object from the L2 cache and the observance of its loaded fields.
*/
public void testL2LoadedFields() {
Properties userProps = new Properties();
userProps.setProperty(PropertyNames.PROPERTY_CACHE_L1_TYPE, "soft");
userProps.setProperty(PropertyNames.PROPERTY_CACHE_L2_TYPE, "weak");
PersistenceManagerFactory cachePMF = getPMF(1, userProps);
try {
// Create a PM and add an object
Object id = null;
PersistenceManager pm = cachePMF.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
Person p1 = new Person(102, "George", "Bush", "george.bush@whitehouse.gov");
pm.makePersistent(p1);
id = pm.getObjectId(p1);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
pm.close();
}
// Clear the L2 cache so we dont have this object
Level2Cache l2Cache = ((JDODataStoreCache) cachePMF.getDataStoreCache()).getLevel2Cache();
l2Cache.evictAll();
// Pin all Person objects
l2Cache.pinAll(Person.class, false);
// Retrieve the object with just some fields
PersistenceManager pm1 = cachePMF.getPersistenceManager();
tx = pm1.currentTransaction();
pm1.getFetchPlan().setGroup("groupA");
try {
// Load the Person object - will only have firstName, lastName loaded.
// Will be added to L2 cache, so pin it
tx.begin();
pm1.getObjectById(id);
// George Bush will now be pinned since all Person objects are pinned
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Exception thrown while retrieving object to store in L2 cache with only few fields : " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
// Object should now be in L2 cache
// Retrieve the object with all fields and check an unretrieved field
PersistenceManager pm2 = cachePMF.getPersistenceManager();
tx = pm2.currentTransaction();
try {
tx.begin();
Person p1 = (Person) pm2.getObjectById(id);
assertTrue("Additional field of L2 cached object hasn't been retrieved correctly (wasnt in original FetchPlan)", p1.getEmailAddress() != null);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
fail("Exception thrown while retrieving object from L2 cache : " + e.getMessage());
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
pm1.close();
pm2.close();
} finally {
// Clean out created data
clean(cachePMF, Person.class);
cachePMF.close();
}
}
Aggregations