001
014
015 package com.liferay.portal.kernel.cache.index;
016
017 import com.liferay.portal.kernel.cache.CacheListener;
018 import com.liferay.portal.kernel.cache.PortalCache;
019 import com.liferay.portal.kernel.concurrent.ConcurrentHashSet;
020
021 import java.util.Collections;
022 import java.util.HashSet;
023 import java.util.Set;
024 import java.util.concurrent.ConcurrentHashMap;
025 import java.util.concurrent.ConcurrentMap;
026
027
030 public class PortalCacheIndexer<I, K extends IndexedCacheKey<I>, V> {
031
032 public PortalCacheIndexer(PortalCache<K, V> portalCache) {
033 _portalCache = portalCache;
034
035 _portalCache.registerCacheListener(new IndexerCacheListener());
036
037 for (K indexedCacheKey : _portalCache.getKeys()) {
038 _addIndexedCacheKey(indexedCacheKey);
039 }
040 }
041
042 public Set<K> getIndexedCacheKeys(I index) {
043 Set<K> indexedCacheKeys = _indexedCacheKeys.get(index);
044
045 if (indexedCacheKeys == null) {
046 return Collections.emptySet();
047 }
048
049 return new HashSet<>(indexedCacheKeys);
050 }
051
052 public void removeIndexedCacheKeys(I index) {
053 Set<K> indexedCacheKeys = _indexedCacheKeys.remove(index);
054
055 if (indexedCacheKeys == null) {
056 return;
057 }
058
059 for (K indexedCacheKey : indexedCacheKeys) {
060 _portalCache.remove(indexedCacheKey);
061 }
062 }
063
064 private void _addIndexedCacheKey(K indexedCacheKey) {
065 I index = indexedCacheKey.getIndex();
066
067 Set<K> indexedCacheKeys = _indexedCacheKeys.get(index);
068
069 if (indexedCacheKeys == null) {
070 Set<K> newIndexedCacheKeys = new ConcurrentHashSet<>();
071
072 newIndexedCacheKeys.add(indexedCacheKey);
073
074 indexedCacheKeys = _indexedCacheKeys.putIfAbsent(
075 index, newIndexedCacheKeys);
076
077 if (indexedCacheKeys == null) {
078 return;
079 }
080 }
081
082 indexedCacheKeys.add(indexedCacheKey);
083 }
084
085 private void _removeIndexedCacheKey(K indexedCacheKey) {
086 I index = indexedCacheKey.getIndex();
087
088 Set<K> indexedCacheKeys = _indexedCacheKeys.get(index);
089
090 if (indexedCacheKeys == null) {
091 return;
092 }
093
094 indexedCacheKeys.remove(indexedCacheKey);
095
096 if (indexedCacheKeys.isEmpty() &&
097 _indexedCacheKeys.remove(index, indexedCacheKeys)) {
098
099 for (K victimIndexedCacheKey : indexedCacheKeys) {
100 _addIndexedCacheKey(victimIndexedCacheKey);
101 }
102 }
103 }
104
105 private final ConcurrentMap<I, Set<K>> _indexedCacheKeys =
106 new ConcurrentHashMap<>();
107 private final PortalCache<K, V> _portalCache;
108
109 private class IndexerCacheListener implements CacheListener<K, V> {
110
111 @Override
112 public void dispose() {
113 _indexedCacheKeys.clear();
114 }
115
116 @Override
117 public void notifyEntryEvicted(
118 PortalCache<K, V> portalCache, K indexedCacheKey, V value,
119 int timeToLive) {
120
121 _removeIndexedCacheKey(indexedCacheKey);
122 }
123
124 @Override
125 public void notifyEntryExpired(
126 PortalCache<K, V> portalCache, K indexedCacheKey, V value,
127 int timeToLive) {
128
129 _removeIndexedCacheKey(indexedCacheKey);
130 }
131
132 @Override
133 public void notifyEntryPut(
134 PortalCache<K, V> portalCache, K indexedCacheKey, V value,
135 int timeToLive) {
136
137 _addIndexedCacheKey(indexedCacheKey);
138 }
139
140 @Override
141 public void notifyEntryRemoved(
142 PortalCache<K, V> portalCache, K indexedCacheKey, V value,
143 int timeToLive) {
144
145 _removeIndexedCacheKey(indexedCacheKey);
146 }
147
148 @Override
149 public void notifyEntryUpdated(
150 PortalCache<K, V> portalCache, K indexedCacheKey, V value,
151 int timeToLive) {
152 }
153
154 @Override
155 public void notifyRemoveAll(PortalCache<K, V> portalCache) {
156 _indexedCacheKeys.clear();
157 }
158
159 }
160
161 }