OPENJPA-1591: Refactor/rename DataCacheScheduler to allow for greater extensibility.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@926249 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Richard G. Curtis 2010-03-22 18:29:15 +00:00
parent 86546e1e12
commit 1c0abb5207
8 changed files with 70 additions and 48 deletions

View File

@ -105,7 +105,7 @@ public abstract class AbstractDataCache extends AbstractConcurrentEventManager
public void initialize(DataCacheManager manager) { public void initialize(DataCacheManager manager) {
if (_schedule != null && !"".equals(_schedule)) { if (_schedule != null && !"".equals(_schedule)) {
DataCacheScheduler scheduler = manager.getDataCacheScheduler(); ClearableScheduler scheduler = manager.getClearableScheduler();
if (scheduler != null) if (scheduler != null)
scheduler.scheduleEviction(this, _schedule); scheduler.scheduleEviction(this, _schedule);
} }

View File

@ -21,18 +21,17 @@ package org.apache.openjpa.datacache;
import java.security.AccessController; import java.security.AccessController;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Clearable;
import org.apache.openjpa.lib.util.J2DoPrivHelper; import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.InvalidStateException; import org.apache.openjpa.util.InvalidStateException;
@ -41,40 +40,38 @@ import org.apache.openjpa.util.UserException;
import serp.util.Strings; import serp.util.Strings;
/** /**
* Cron-style cache eviction. Understands schedules based on cron format: * Cron-style clearable eviction. Understands schedules based on cron format:
* <code>minute hour mday month wday</code> * <li><code>minute hour mday month wday</code></li>
* <li><code>+minute</code></li>
* For example: * For example:
* <code>15,30 6,19 2,10 1 2 </code> * <code>15,30 6,19 2,10 1 2 </code>
* Would run at 15 and 30 past the 6AM and 7PM, on the 2nd and 10th * Would run at 15 and 30 past the 6AM and 7PM, on the 2nd and 10th
* of January when its a Monday. * of January when its a Monday.
* *
* @author Steve Kim
*/ */
public class DataCacheScheduler public class ClearableScheduler implements Runnable {
implements Runnable {
private static final Localizer _loc = Localizer.forPackage private static final Localizer _loc = Localizer.forPackage(ClearableScheduler.class);
(DataCacheScheduler.class);
private Map _caches = new ConcurrentHashMap(); private Map<Clearable,Schedule> _clearables = new ConcurrentHashMap<Clearable,Schedule>();
private boolean _stop = false; private boolean _stop = false;
private int _interval = 1; private int _interval = 1;
private Log _log; private Log _log;
private Thread _thread; private Thread _thread;
public DataCacheScheduler(OpenJPAConfiguration conf) { public ClearableScheduler(OpenJPAConfiguration conf) {
_log = conf.getLogFactory().getLog(OpenJPAConfiguration.LOG_DATACACHE); _log = conf.getLogFactory().getLog(OpenJPAConfiguration.LOG_DATACACHE);
} }
/** /**
* The interval time in minutes between cache checks. Defaults to 1. * The interval time in minutes between scheduler checks. Defaults to 1.
*/ */
public int getInterval() { public int getInterval() {
return _interval; return _interval;
} }
/** /**
* The interval time in minutes between cache checks. Defaults to 1. * The interval time in minutes between scheduler checks. Defaults to 1.
*/ */
public void setInterval(int interval) { public void setInterval(int interval) {
_interval = interval; _interval = interval;
@ -92,15 +89,15 @@ public class DataCacheScheduler
} }
/** /**
* Schedule the given cache for eviction. Starts the scheduling thread * Schedule the given Clearable for clear to be called. Starts the scheduling thread
* if not started. * if not started.
*/ */
public synchronized void scheduleEviction(DataCache cache, String times) { public synchronized void scheduleEviction(Clearable clearable, String times) {
if (times == null) if (times == null)
return; return;
Schedule schedule = new Schedule(times); Schedule schedule = new Schedule(times);
_caches.put(cache, schedule); _clearables.put(clearable, schedule);
_stop = false; _stop = false;
if (_thread == null) { if (_thread == null) {
_thread = _thread =
@ -114,11 +111,11 @@ public class DataCacheScheduler
} }
/** /**
* Remove the given cache from scheduling. * Remove the given Clearable from scheduling.
*/ */
public synchronized void removeFromSchedule(DataCache cache) { public synchronized void removeFromSchedule(Clearable clearable) {
_caches.remove(cache); _clearables.remove(clearable);
if (_caches.size() == 0) if (_clearables.size() == 0)
stop(); stop();
} }
@ -133,18 +130,13 @@ public class DataCacheScheduler
Thread.sleep(_interval * 60 * 1000); Thread.sleep(_interval * 60 * 1000);
Date now = new Date(); Date now = new Date();
DataCache cache; for(Entry<Clearable, Schedule> entry : _clearables.entrySet()){
Schedule schedule; Clearable clearable = entry.getKey();
Map.Entry entry; Schedule schedule = entry.getValue();
for (Iterator i = _caches.entrySet().iterator(); i.hasNext();) {
entry = (Map.Entry) i.next();
cache = (DataCache) entry.getKey();
schedule = (Schedule) entry.getValue();
if (schedule.matches(lastRun, now)) { if (schedule.matches(lastRun, now)) {
if (_log.isTraceEnabled()) if (_log.isTraceEnabled())
_log.trace(_loc.get("scheduler-clear", _log.trace(_loc.get("scheduler-clear", clearable, fom.format(now)));
cache.getName(), fom.format(now))); evict(clearable);
evict(cache);
} }
} }
lastRun = now; lastRun = now;
@ -161,7 +153,7 @@ public class DataCacheScheduler
} }
} }
protected void evict(DataCache cache) { protected void evict(Clearable cache) {
cache.clear(); cache.clear();
} }

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.openjpa.lib.util.Clearable;
import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Closeable;
/** /**
@ -40,7 +41,7 @@ import org.apache.openjpa.lib.util.Closeable;
* @author Pinaki Poddar * @author Pinaki Poddar
*/ */
public interface DataCache public interface DataCache
extends Closeable { extends Closeable, Clearable {
/** /**
* The name of the default data cache: <code>default</code> * The name of the default data cache: <code>default</code>

View File

@ -77,7 +77,7 @@ public interface DataCacheManager {
/** /**
* Return the runnable which schedules evictions. * Return the runnable which schedules evictions.
*/ */
public DataCacheScheduler getDataCacheScheduler(); public ClearableScheduler getClearableScheduler();
/** /**
* Select the cache where the given managed proxy instance should be cached. * Select the cache where the given managed proxy instance should be cached.

View File

@ -31,7 +31,7 @@ import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.ImplHelper;
/** /**
* Default data cache manager provides handle to utilities {@linkplain PCDataGenerator}, {@linkplain DataCacheScheduler} * Default data cache manager provides handle to utilities {@linkplain PCDataGenerator}, {@linkplain ClearableScheduler}
* and {@linkplain CacheDistributionPolicy} for the cache operation. This implementation also determines whether a * and {@linkplain CacheDistributionPolicy} for the cache operation. This implementation also determines whether a
* managed type is eligible to cache. * managed type is eligible to cache.
* *
@ -46,7 +46,7 @@ public class DataCacheManagerImpl
private DataCache _cache = null; private DataCache _cache = null;
private QueryCache _queryCache = null; private QueryCache _queryCache = null;
private DataCachePCDataGenerator _pcGenerator = null; private DataCachePCDataGenerator _pcGenerator = null;
private DataCacheScheduler _scheduler = null; private ClearableScheduler _scheduler = null;
private CacheDistributionPolicy _policy = new DefaultCacheDistributionPolicy(); private CacheDistributionPolicy _policy = new DefaultCacheDistributionPolicy();
private Map<ClassMetaData,Boolean> _cacheable = new HashMap<ClassMetaData, Boolean>(); private Map<ClassMetaData,Boolean> _cacheable = new HashMap<ClassMetaData, Boolean>();
@ -64,7 +64,7 @@ public class DataCacheManagerImpl
// create helpers before initializing caches // create helpers before initializing caches
if (conf.getDynamicDataStructs()) if (conf.getDynamicDataStructs())
_pcGenerator = new DataCachePCDataGenerator(conf); _pcGenerator = new DataCachePCDataGenerator(conf);
_scheduler = new DataCacheScheduler(conf); _scheduler = new ClearableScheduler(conf);
_policy = conf.getCacheDistributionPolicyInstance(); _policy = conf.getCacheDistributionPolicyInstance();
@ -104,7 +104,7 @@ public class DataCacheManagerImpl
return _pcGenerator; return _pcGenerator;
} }
public DataCacheScheduler getDataCacheScheduler() { public ClearableScheduler getClearableScheduler() {
return _scheduler; return _scheduler;
} }

View File

@ -63,12 +63,12 @@ query-cache-key-removed: Key "{0}" has been removed from the query cache.
reg-mbean: Registered MBean ({0}). reg-mbean: Registered MBean ({0}).
cant-reg-mbean: Unable to register Datastore Cache {0} MBean. cant-reg-mbean: Unable to register Datastore Cache {0} MBean.
query-cache-name: Query Cache query-cache-name: Query Cache
scheduler-start: Starting cache scheduler thread "{0}"... scheduler-start: Starting clearable scheduler thread "{0}"...
scheduler-name: OpenJPA Cache Scheduler scheduler-name: OpenJPA Clearable Scheduler
scheduler-interval: Cache schedule thread will check every "{0}" min. scheduler-interval: Clearable schedule thread will check every "{0}" min.
scheduler-clear: Scheduled cache eviction at time "{1}" for cache:"{0}" scheduler-clear: Scheduled clearable eviction at time "{1}" for clearable:"{0}"
scheduler-stop: Stopping scheduled cache eviction thread. scheduler-stop: Stopping scheduled clearable eviction thread.
scheduler-fail: Cache scheduler thread unexpectedly interrupted. Stopping \ scheduler-fail: Clearable scheduler thread unexpectedly interrupted. Stopping \
scheduler. scheduler.
bad-schedule: Invalid schedule string: "{0}" bad-schedule: Invalid schedule string: "{0}"
not-number: Token "{0}" is not a valid number or wildcard (*) for schedule. not-number: Token "{0}" is not a valid number or wildcard (*) for schedule.

View File

@ -0,0 +1,29 @@
/*
* 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.lib.util;
/**
* Generic interface for components that can be cleared so that helpers can treat them in a generic
* way.
*/
public interface Clearable {
public void clear();
}

View File

@ -26,12 +26,12 @@ import java.util.List;
import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.datacache.ConcurrentDataCache; import org.apache.openjpa.datacache.ConcurrentDataCache;
import org.apache.openjpa.datacache.DataCacheManager; import org.apache.openjpa.datacache.DataCacheManager;
import org.apache.openjpa.datacache.DataCacheScheduler; import org.apache.openjpa.datacache.ClearableScheduler;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI; import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.datacache.common.apps.ScheduledEviction; import org.apache.openjpa.persistence.datacache.common.apps.ScheduledEviction;
import org.apache.openjpa.persistence.test.SingleEMFTestCase; import org.apache.openjpa.persistence.test.SingleEMFTestCase;
public class TestDataCacheScheduler extends SingleEMFTestCase { public class TestClearableScheduler extends SingleEMFTestCase {
private static String getMinutesString() { private static String getMinutesString() {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
@ -54,7 +54,7 @@ public class TestDataCacheScheduler extends SingleEMFTestCase {
public void testBasic() throws Exception { public void testBasic() throws Exception {
OpenJPAEntityManagerSPI em = emf.createEntityManager(); OpenJPAEntityManagerSPI em = emf.createEntityManager();
OpenJPAConfiguration conf = ((OpenJPAEntityManagerSPI) em).getConfiguration(); OpenJPAConfiguration conf = ((OpenJPAEntityManagerSPI) em).getConfiguration();
DataCacheScheduler scheduler = new DataCacheScheduler(conf); ClearableScheduler scheduler = new ClearableScheduler(conf);
// Make the scheduler run every 1 minute // Make the scheduler run every 1 minute
scheduler.setInterval(1); scheduler.setInterval(1);
DummyCache cache1 = new DummyCache(); DummyCache cache1 = new DummyCache();