1 package com.trendmicro.grid.acl.ds.cache.aspects;
2
3 import com.trendmicro.grid.acl.ds.cache.CacheAdapter;
4 import com.trendmicro.grid.acl.ds.cache.CacheSource;
5 import com.trendmicro.grid.acl.ds.cache.commands.GetFromCacheCommand;
6 import com.trendmicro.grid.acl.ds.cache.commands.GetFromPJPSourceCommand;
7 import com.trendmicro.grid.acl.ds.cache.commands.RemoveCommand;
8 import com.trendmicro.grid.acl.ds.cache.translation.FileAwareValueExistsTranslator;
9 import com.trendmicro.grid.acl.ds.cache.translation.FileDetailsToInformationTranslator;
10 import com.trendmicro.grid.acl.ds.cache.translation.ValueExistsTranslator;
11 import com.trendmicro.grid.acl.ds.datatypes.SharedFileDetails;
12 import com.trendmicro.grid.acl.ds.datatypes.SharedFileInformation;
13 import com.trendmicro.grid.acl.l0.datatypes.*;
14 import net.sf.tinyjee.cache.config.CacheRegion;
15 import org.aspectj.lang.ProceedingJoinPoint;
16 import org.aspectj.lang.annotation.AfterReturning;
17 import org.aspectj.lang.annotation.Around;
18 import org.aspectj.lang.annotation.Aspect;
19 import org.infinispan.Cache;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 import org.springframework.stereotype.Service;
23
24 import java.util.Collection;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.concurrent.Callable;
29
30 import static com.trendmicro.grid.acl.ds.cache.CacheSettings.*;
31
32
33
34
35
36
37
38 @Aspect
39 @Service
40 public class FileDetailsCacheAspect extends AbstractCacheAspect {
41
42 private static final Logger log = LoggerFactory.getLogger(FileDetailsCacheAspect.class);
43
44 @CacheRegion(name = CACHE_REGION_FILE_DETAILS)
45 Cache<FileIdentifier, SharedFileDetails> cachedFileDetails;
46 @CacheRegion(name = CACHE_REGION_FILE_INFORMATION)
47 Cache<FileIdentifier, SharedFileInformation> cachedFileInformation;
48
49 @CacheRegion(name = CACHE_REGION_UNKNOWN_FILE_IDENTIFIERS)
50 Cache<FileIdentifier, Boolean> unknownFileIdentifiersCache;
51
52 private CacheAdapter<FileIdentifier, SharedFileDetails> detailsCacheAdapter;
53 private CacheSource<FileIdentifier, SharedFileInformation> informationFromDetails;
54 private CacheAdapter<FileIdentifier, SharedFileInformation> informationCacheAdapter;
55 private CacheSource<FileIdentifier, Boolean>[] fileExistsSources;
56
57 private CacheAdapter<FileIdentifier, Boolean> unknownFileIdentifiers;
58
59
60
61
62
63
64
65
66
67 @Around(value = "execution(* com.trendmicro.grid.acl.ds.FileProvider.isFilesKnown(..)) && " +
68 "args(files) && @annotation(com.trendmicro.grid.acl.ds.RemoteCacheable)", argNames = "pjp,files")
69 public Collection<Boolean> isFilesKnown(final ProceedingJoinPoint pjp, Collection<FileIdentifier> files) throws Exception {
70
71 return call(new GetFromCacheCommand<FileIdentifier, Boolean>(files, fileExistsSources) {
72 @Override
73 protected Callable<Map<FileIdentifier, Boolean>> createGetFromSourceCommand(Collection<FileIdentifier> keys) {
74 return new GetFromPJPSourceCommand<FileIdentifier, Boolean>(getCacheStatistics().getFetchedKeyCount(), keys, pjp);
75 }
76 });
77 }
78
79
80
81
82
83
84
85
86
87
88 @Around(value = "execution(* com.trendmicro.grid.acl.ds.FileProvider.getFileInformationList(..)) && " +
89 "args(files) && @annotation(com.trendmicro.grid.acl.ds.RemoteCacheable)", argNames = "pjp,files")
90 public Collection<SharedFileInformation> getFileInformationList(
91 final ProceedingJoinPoint pjp, final Collection<FileIdentifier> files) throws Exception {
92
93 return call(new GetFromCacheCommand<FileIdentifier, SharedFileInformation>(files, informationCacheAdapter, informationFromDetails) {
94 @Override
95 protected Callable<Map<FileIdentifier, SharedFileInformation>> createGetFromSourceCommand(Collection<FileIdentifier> keys) {
96 return new GetFromPJPSourceCommand<FileIdentifier, SharedFileInformation>(getCacheStatistics().getFetchedKeyCount(), keys, pjp);
97 }
98 }.useDestination(informationCacheAdapter, cacheWriteMode).useUnknownKeysLookup(unknownFileIdentifiers, cacheWriteMode));
99 }
100
101
102
103
104
105
106
107
108
109
110 @Around(value = "execution(* com.trendmicro.grid.acl.ds.FileProvider.getFileDetailsList(..)) && " +
111 "args(files) && @annotation(com.trendmicro.grid.acl.ds.RemoteCacheable)", argNames = "pjp,files")
112 public Collection<SharedFileDetails> getFileDetailsList(
113 final ProceedingJoinPoint pjp, final Collection<FileIdentifier> files) throws Exception {
114
115 return call(new GetFromCacheCommand<FileIdentifier, SharedFileDetails>(files, detailsCacheAdapter) {
116 @Override
117 protected Callable<Map<FileIdentifier, SharedFileDetails>> createGetFromSourceCommand(Collection<FileIdentifier> keys) {
118 return new GetFromPJPSourceCommand<FileIdentifier, SharedFileDetails>(getCacheStatistics().getFetchedKeyCount(), keys, pjp);
119 }
120 }.useDestination(detailsCacheAdapter, cacheWriteMode).useUnknownKeysLookup(unknownFileIdentifiers, cacheWriteMode));
121 }
122
123
124
125
126
127
128
129 @AfterReturning(value = "execution(* com.trendmicro.grid.acl.ds.ProcessingResultReceiver.receive(..)) && " +
130 "args(dataSets)", argNames = "dataSets")
131 public void invalidateCachesAfterReceivingUpdates(final Collection<ProcessPackageDataSet> dataSets) throws Exception {
132
133 final List<FileIdentifier> keysToRemove = new LinkedList<FileIdentifier>();
134 for (ProcessPackageDataSet dataSet : dataSets) {
135 final PackageDetails processedPackage = dataSet.getProcessedPackage();
136 final FileMetadata fm = processedPackage.getFileMetadata();
137 if (fm != null) {
138 keysToRemove.addAll(fm.getIdentifier().getVariants());
139
140 if (log.isTraceEnabled()) {
141 log.trace("Invalidated cached file entries for package '{}', identifier '{}'",
142 processedPackage.getPackageInformation().getName(), fm.getIdentifier());
143 }
144 }
145
146 for (PackageMember member : dataSet.getPackageMember()) {
147 keysToRemove.addAll(member.getIdentifier().extractIdentifier().getVariants());
148
149 if (log.isTraceEnabled()) log.trace("Invalidated cached file entries for member '{}'", member.getIdentifier());
150 }
151 }
152
153 call(new RemoveCommand<FileIdentifier, Object>(keysToRemove,
154 detailsCacheAdapter, informationCacheAdapter, unknownFileIdentifiers).asBatchCommand());
155 }
156
157
158
159
160
161
162 public void setCachedFileDetails(Cache<FileIdentifier, SharedFileDetails> cachedFileDetails) {
163 this.cachedFileDetails = cachedFileDetails;
164 detailsCacheAdapter = new CacheAdapter<FileIdentifier, SharedFileDetails>(cachedFileDetails, sync);
165
166 FileDetailsToInformationTranslator<FileIdentifier> t = new FileDetailsToInformationTranslator<FileIdentifier>();
167 informationFromDetails = t.newSource(detailsCacheAdapter);
168
169 updateFileExistsSources();
170 }
171
172
173
174
175
176
177 public void setCachedFileInformation(Cache<FileIdentifier, SharedFileInformation> cachedFileInformation) {
178 this.cachedFileInformation = cachedFileInformation;
179 informationCacheAdapter = new CacheAdapter<FileIdentifier, SharedFileInformation>(cachedFileInformation, sync);
180
181 updateFileExistsSources();
182 }
183
184 public void setUnknownFileIdentifiersCache(Cache<FileIdentifier, Boolean> unknownFileIdentifiersCache) {
185 this.unknownFileIdentifiersCache = unknownFileIdentifiersCache;
186 unknownFileIdentifiers = new CacheAdapter<FileIdentifier, Boolean>(unknownFileIdentifiersCache, sync);
187
188 updateFileExistsSources();
189 }
190
191 private void updateFileExistsSources() {
192 if (detailsCacheAdapter != null && informationCacheAdapter != null) {
193 ValueExistsTranslator<FileIdentifier> t = new FileAwareValueExistsTranslator<FileIdentifier>();
194
195 @SuppressWarnings("unchecked")
196 final CacheSource<FileIdentifier, Boolean>[] sources = new CacheSource[]{
197 t.newSource(detailsCacheAdapter), t.newSource(informationCacheAdapter), unknownFileIdentifiers};
198
199 fileExistsSources = sources;
200 }
201 }
202 }