Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.datacache;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.openjpa.enhance.PCDataGenerator;
import org.apache.openjpa.kernel.DataCacheRetrieveMode;
import org.apache.openjpa.kernel.DataCacheStoreMode;
import org.apache.openjpa.kernel.DelegatingStoreManager;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.LockLevels;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PCState;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.StoreManager;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.util.OpenJPAId;
import org.apache.openjpa.util.OptimisticException;
/**
* StoreManager proxy that delegates to a data cache when possible.
*
* @author Patrick Linskey
*/
public class DataCacheStoreManager extends DelegatingStoreManager {
// all the state managers changed in this transaction
private Collection _inserts = null;
private Map _updates = null;
private Collection _deletes = null;
// the owning context
private StoreContext _ctx = null;
private DataCacheManager _mgr = null;
// pc data generator
private PCDataGenerator _gen = null;
/**
* Constructor.
*
* @param sm the store manager to delegate to
*/
public DataCacheStoreManager(StoreManager sm) {
super(sm);
}
@Override
public void setContext(StoreContext ctx) {
_ctx = ctx;
_mgr = ctx.getConfiguration().getDataCacheManagerInstance();
_gen = _mgr.getPCDataGenerator();
super.setContext(ctx);
}
@Override
public void begin() {
super.begin();
}
@Override
public void commit() {
try {
super.commit();
updateCaches();
} finally {
_inserts = null;
_updates = null;
_deletes = null;
}
}
@Override
public void rollback() {
try {
super.rollback();
} finally {
_inserts = null;
_updates = null;
_deletes = null;
}
}
/**
* Evict all members of the given classes.
*/
private void evictTypes(Collection> classes) {
if (classes.isEmpty())
return;
MetaDataRepository mdr = _ctx.getConfiguration().getMetaDataRepositoryInstance();
ClassLoader loader = _ctx.getClassLoader();
DataCache cache;
for (Class> cls : classes) {
cache = mdr.getMetaData(cls, loader, false).getDataCache();
if (cache != null && cache.getEvictOnBulkUpdate())
cache.removeAll(cls, false);
}
}
/**
* Update all caches with the committed inserts, updates, and deletes.
*/
private void updateCaches() {
if(_ctx.getFetchConfiguration().getCacheStoreMode() != DataCacheStoreMode.BYPASS ) {
// map each data cache to the modifications we need to perform
Map modMap = null;
if ((_ctx.getPopulateDataCache() && _inserts != null) || _updates != null || _deletes != null)
modMap = new HashMap<>();
Modifications mods;
DataCachePCData data;
DataCache cache;
// create pc datas for inserts
if (_ctx.getPopulateDataCache() && _inserts != null) {
for (OpenJPAStateManager sm : _inserts) {
cache = _mgr.selectCache(sm);
if (cache == null)
continue;
mods = getModifications(modMap, cache);
data = newPCData(sm, cache);
data.store(sm);
mods.additions.add(new PCDataHolder(data, sm));
CacheStatistics stats = cache.getStatistics();
if (stats.isEnabled()) {
((CacheStatisticsSPI)stats).newPut(data.getType());
}
}
}
// update pcdatas for updates
if (_updates != null) {
BitSet fields;
OpenJPAStateManager sm;
for (Map.Entry entry : _updates.entrySet()) {
sm = entry.getKey();
fields = entry.getValue();
cache = _mgr.selectCache(sm);
if (cache == null) {
continue;
}
// it's ok not to clone the object that we get from the cache,
// since we're inside the commit() method, so any modifications
// to the underlying cache are valid. If the commit had not
// already succeeded, then we'd want to clone the retrieved
// object.
data = cache.get(sm.getObjectId());
mods = getModifications(modMap, cache);
// data should always be non-null, since the object is
// dirty, but maybe it got dropped from the cache in the
// interim
if (data == null) {
data = newPCData(sm, cache);
data.store(sm);
mods.newUpdates.add(new PCDataHolder(data, sm));
} else {
data.store(sm, fields);
mods.existingUpdates.add(new PCDataHolder(data, sm));
}
CacheStatistics stats = cache.getStatistics();
if (stats.isEnabled()) {
((CacheStatisticsSPI)stats).newPut(data.getType());
}
}
}
// remove pcdatas for deletes
if (_deletes != null) {
for (OpenJPAStateManager sm : _deletes) {
cache = _mgr.selectCache(sm);
if (cache == null)
continue;
mods = getModifications(modMap, cache);
mods.deletes.add(sm.getObjectId());
}
}
// notify the caches of the changes
if (modMap != null) {
for (Map.Entry entry : modMap.entrySet()) {
cache = entry.getKey();
mods = entry.getValue();
// make sure we're not caching old versions
cache.writeLock();
try {
cache.commit(
transformToVersionSafePCDatas(cache, mods.additions),
transformToVersionSafePCDatas(cache, mods.newUpdates),
transformToVersionSafePCDatas(cache, mods.existingUpdates),
mods.deletes);
} finally {
cache.writeUnlock();
}
}
}
// if we were in largeTransaction mode, then we have recorded
// the classes of updated/deleted objects and these now need to be
// evicted
if (_ctx.isTrackChangesByType()) {
evictTypes(_ctx.getDeletedTypes());
evictTypes(_ctx.getUpdatedTypes());
}
}
}
/**
* Transforms a collection of {@link PCDataHolder}s that might contain
* stale instances into a collection of up-to-date {@link DataCachePCData}s.
*/
private List transformToVersionSafePCDatas(DataCache cache, List holders) {
List transformed = new ArrayList<>(holders.size());
Map