@Override public Object get(Object key) { // Check for null as Cache should not store null values / keys if (key == null) { throw new NullPointerException("key is null"); } CacheValue cacheValue = map.get(key); // Check for null if (cacheValue == null) { return null; } // Check if to be autoexpired, autoExpireTimeInMs = 0 means expire immediately / no caching // Note: This point will never be reached if the value was put in cache when autoExpireTimeInMs // was 0 if (this.autoExpireTimeInMs >= 0) { // Check if expired long now = new Date().getTime(); if (cacheValue.getLastUpateTime() + this.autoExpireTimeInMs < now) { // Expired, remove remove(key); return null; } } // Not expired, return the value return cacheValue.getValue(); }
/** 预填充 */ private void prefillCache(String key, CacheValue cacheValue) { long currentTime = System.currentTimeMillis() / 1000; if (cacheValue.getEndTime() >= currentTime - PREFILL_SECOND) { PrefillCallback prefillCallback = prefillCallbackMap.get(key); if (prefillCallback != null) { this.set(key, cacheValue.getExpireTime(), prefillCallback.prefill(), prefillCallback); } } }
@Override public void remove(Directory dir, boolean deleteAfterCoreClose) throws IOException { synchronized (this) { CacheValue val = byDirectoryCache.get(dir); if (val == null) { throw new IllegalArgumentException("Unknown directory " + dir); } val.setDeleteOnClose(true, deleteAfterCoreClose); } }
@Override public void remove(String path, boolean deleteAfterCoreClose) throws IOException { synchronized (this) { CacheValue val = byPathCache.get(normalize(path)); if (val == null) { throw new IllegalArgumentException("Unknown directory " + path); } val.setDeleteOnClose(true, deleteAfterCoreClose); } }
@Override public long getLastUpateTime(Object key) { // Check for null as Cache should not store null values / keys if (key == null) { throw new NullPointerException("key is null"); } CacheValue value = map.get(key); if (value != null) { return value.getLastUpateTime(); } else { return -1; } }
protected CacheValue createCacheValue(String key, ClassResource classResource) { CacheValue answer = new CacheValue(); SortedSet<String> classNames = answer.getClassNames(); String packageName = classResource.getPackageName(); URL resource = classResource.getResource(); if (resource != null) { String resourceText = resource.toString(); LOG.debug("Searching resource " + resource); if (resourceText.startsWith("jar:")) { processJarClassNames(classResource, classNames); } else { processDirectoryClassNames(new File(resource.getPath()), packageName, classNames); } } return answer; }
@Override public Object get(String key) { Object value = super.get(key); if (!(value instanceof CacheValue)) { return value; } CacheValue cacheValue = (CacheValue) value; if (cacheValue == null) { return cacheValue; } // 获取分布式锁 prefillCache(key, cacheValue); return cacheValue.getValue(); }
@Override public void doneWithDirectory(Directory directory) throws IOException { synchronized (this) { CacheValue cacheValue = byDirectoryCache.get(directory); if (cacheValue == null) { throw new IllegalArgumentException( "Unknown directory: " + directory + " " + byDirectoryCache); } cacheValue.doneWithDir = true; log.debug("Done with dir: {}", cacheValue); if (cacheValue.refCnt == 0 && !closed) { boolean cl = closeCacheValue(cacheValue); if (cl) { removeFromCache(cacheValue); } } } }
public SortedSet<String> findClassNamesInPackages( String search, Integer limit, Map<Package, ClassLoader[]> packages) { SortedSet<String> answer = new TreeSet<String>(); SortedSet<String> classes = new TreeSet<String>(); Set<Map.Entry<Package, ClassLoader[]>> entries = packages.entrySet(); for (Map.Entry<Package, ClassLoader[]> entry : entries) { Package aPackage = entry.getKey(); ClassLoader[] classLoaders = entry.getValue(); CacheValue cacheValue = packageCache.get(aPackage); if (cacheValue == null) { cacheValue = createPackageCacheValue(aPackage, classLoaders); packageCache.put(aPackage, cacheValue); } classes.addAll(cacheValue.getClassNames()); } /* for (Map.Entry<String, ClassResource> entry : entries) { String key = entry.getKey(); ClassResource classResource = entry.getValue(); CacheValue cacheValue = cache.get(key); if (cacheValue == null) { cacheValue = createCacheValue(key, classResource); cache.put(key, cacheValue); } classes.addAll(cacheValue.getClassNames()); //addClassesForPackage(classResource, search, limit, classes); } */ if (withinLimit(limit, answer)) { for (String aClass : classes) { if (classNameMatches(aClass, search)) { answer.add(aClass); if (!withinLimit(limit, answer)) { break; } } } } return answer; }
private CacheValue createPackageCacheValue(Package aPackage, ClassLoader[] classLoaders) { Map<String, ClassResource> urlSet = new HashMap<String, ClassResource>(); addPackageResources(aPackage, urlSet, classLoaders); CacheValue answer = new CacheValue(); SortedSet<String> classNames = answer.getClassNames(); Set<Map.Entry<String, ClassResource>> entries = urlSet.entrySet(); for (Map.Entry<String, ClassResource> entry : entries) { String key = entry.getKey(); ClassResource classResource = entry.getValue(); CacheValue cacheValue = cache.get(key); if (cacheValue == null) { cacheValue = createCacheValue(key, classResource); cache.put(key, cacheValue); } classNames.addAll(cacheValue.getClassNames()); } return answer; }
// be sure this is called with the this sync lock // returns true if we closed the cacheValue, false if it will be closed later private boolean closeCacheValue(CacheValue cacheValue) { log.info("looking to close " + cacheValue.path + " " + cacheValue.closeEntries.toString()); List<CloseListener> listeners = closeListeners.remove(cacheValue.directory); if (listeners != null) { for (CloseListener listener : listeners) { try { listener.preClose(); } catch (Exception e) { SolrException.log(log, "Error executing preClose for directory", e); } } } cacheValue.closeCacheValueCalled = true; if (cacheValue.deleteOnClose) { // see if we are a subpath Collection<CacheValue> values = byPathCache.values(); Collection<CacheValue> cacheValues = new ArrayList<>(values); cacheValues.remove(cacheValue); for (CacheValue otherCacheValue : cacheValues) { // if we are a parent path and a sub path is not already closed, get a sub path to close us // later if (isSubPath(cacheValue, otherCacheValue) && !otherCacheValue.closeCacheValueCalled) { // we let the sub dir remove and close us if (!otherCacheValue.deleteAfterCoreClose && cacheValue.deleteAfterCoreClose) { otherCacheValue.deleteAfterCoreClose = true; } otherCacheValue.removeEntries.addAll(cacheValue.removeEntries); otherCacheValue.closeEntries.addAll(cacheValue.closeEntries); cacheValue.closeEntries.clear(); cacheValue.removeEntries.clear(); return false; } } } boolean cl = false; for (CacheValue val : cacheValue.closeEntries) { close(val); if (val == cacheValue) { cl = true; } } for (CacheValue val : cacheValue.removeEntries) { if (!val.deleteAfterCoreClose) { log.info("Removing directory before core close: " + val.path); try { removeDirectory(val); } catch (Exception e) { SolrException.log(log, "Error removing directory", e); } } else { removeEntries.add(val); } } if (listeners != null) { for (CloseListener listener : listeners) { try { listener.postClose(); } catch (Exception e) { SolrException.log(log, "Error executing postClose for directory", e); } } } return cl; }