|
17 | 17 |
|
18 | 18 | package org.apache.ignite.cdc; |
19 | 19 |
|
20 | | -import java.io.IOException; |
21 | | -import java.nio.file.Files; |
22 | 20 | import java.nio.file.Path; |
23 | 21 | import java.util.HashSet; |
24 | 22 | import java.util.Iterator; |
25 | | -import java.util.List; |
26 | | -import java.util.Optional; |
27 | 23 | import java.util.Set; |
28 | | -import java.util.regex.Pattern; |
29 | | -import java.util.regex.PatternSyntaxException; |
30 | 24 | import java.util.stream.Collectors; |
31 | 25 |
|
32 | 26 | import org.apache.ignite.IgniteCheckedException; |
|
44 | 38 | import org.apache.ignite.metric.MetricRegistry; |
45 | 39 | import org.apache.ignite.resources.LoggerResource; |
46 | 40 |
|
47 | | -import static java.nio.file.StandardCopyOption.ATOMIC_MOVE; |
48 | | -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; |
49 | 41 | import static org.apache.ignite.cdc.kafka.IgniteToKafkaCdcStreamer.DFLT_IS_ONLY_PRIMARY; |
50 | 42 |
|
51 | 43 | /** |
@@ -78,33 +70,21 @@ public abstract class AbstractIgniteCdcStreamer implements CdcConsumerEx { |
78 | 70 | /** */ |
79 | 71 | public static final String LAST_EVT_SENT_TIME_DESC = "Timestamp of last applied event to destination cluster"; |
80 | 72 |
|
81 | | - /** File with saved names of caches added by cache masks. */ |
82 | | - private static final String SAVED_CACHES_FILE = "caches"; |
83 | | - |
84 | | - /** Temporary file with saved names of caches added by cache masks. */ |
85 | | - private static final String SAVED_CACHES_TMP_FILE = "caches_tmp"; |
86 | | - |
87 | | - /** CDC directory path. */ |
88 | | - private Path cdcDir; |
89 | | - |
90 | 73 | /** Handle only primary entry flag. */ |
91 | 74 | private boolean onlyPrimary = DFLT_IS_ONLY_PRIMARY; |
92 | 75 |
|
93 | 76 | /** Cache names. */ |
94 | 77 | private Set<String> caches; |
95 | 78 |
|
| 79 | + /** Regexp manager. */ |
| 80 | + private CdcRegexManager regexManager; |
| 81 | + |
96 | 82 | /** Include regex templates for cache names. */ |
97 | 83 | private Set<String> includeTemplates = new HashSet<>(); |
98 | 84 |
|
99 | | - /** Compiled include regex patterns for cache names. */ |
100 | | - private Set<Pattern> includeFilters; |
101 | | - |
102 | 85 | /** Exclude regex templates for cache names. */ |
103 | 86 | private Set<String> excludeTemplates = new HashSet<>(); |
104 | 87 |
|
105 | | - /** Compiled exclude regex patterns for cache names. */ |
106 | | - private Set<Pattern> excludeFilters; |
107 | | - |
108 | 88 | /** Cache IDs. */ |
109 | 89 | protected Set<Integer> cachesIds; |
110 | 90 |
|
@@ -139,24 +119,18 @@ public abstract class AbstractIgniteCdcStreamer implements CdcConsumerEx { |
139 | 119 | @Override public void start(MetricRegistry reg, Path cdcDir) { |
140 | 120 | A.notEmpty(caches, "caches"); |
141 | 121 |
|
142 | | - this.cdcDir = cdcDir; |
| 122 | + regexManager = new CdcRegexManager(cdcDir, log); |
143 | 123 |
|
144 | 124 | cachesIds = caches.stream() |
145 | 125 | .mapToInt(CU::cacheId) |
146 | 126 | .boxed() |
147 | 127 | .collect(Collectors.toSet()); |
148 | 128 |
|
149 | | - prepareRegexFilters(); |
| 129 | + regexManager.compileRegexp(includeTemplates, excludeTemplates); |
150 | 130 |
|
151 | | - try { |
152 | | - loadCaches().stream() |
153 | | - .filter(this::matchesFilters) |
154 | | - .map(CU::cacheId) |
155 | | - .forEach(cachesIds::add); |
156 | | - } |
157 | | - catch (IOException e) { |
158 | | - throw new IgniteException(e); |
159 | | - } |
| 131 | + regexManager.getSavedCaches().stream() |
| 132 | + .map(CU::cacheId) |
| 133 | + .forEach(cachesIds::add); |
160 | 134 |
|
161 | 135 | MetricRegistryImpl mreg = (MetricRegistryImpl)reg; |
162 | 136 |
|
@@ -195,147 +169,26 @@ public abstract class AbstractIgniteCdcStreamer implements CdcConsumerEx { |
195 | 169 | /** {@inheritDoc} */ |
196 | 170 | @Override public void onCacheChange(Iterator<CdcCacheEvent> cacheEvents) { |
197 | 171 | cacheEvents.forEachRemaining(e -> { |
198 | | - matchWithRegexTemplates(e.configuration().getName()); |
| 172 | + matchWithRegex(e.configuration().getName()); |
199 | 173 | }); |
200 | 174 | } |
201 | 175 |
|
202 | 176 | /** |
203 | 177 | * Finds match between cache name and user's regex templates. |
204 | | - * If match is found, adds this cache's id to id's list and saves cache name to file. |
| 178 | + * If match is found, adds this cache's id to id's list. |
205 | 179 | * |
206 | 180 | * @param cacheName Cache name. |
207 | 181 | */ |
208 | | - private void matchWithRegexTemplates(String cacheName) { |
| 182 | + private void matchWithRegex(String cacheName) { |
209 | 183 | int cacheId = CU.cacheId(cacheName); |
210 | 184 |
|
211 | | - if (!cachesIds.contains(cacheId) && matchesFilters(cacheName)) { |
| 185 | + if (!cachesIds.contains(cacheId) && regexManager.match(cacheName)) |
212 | 186 | cachesIds.add(cacheId); |
213 | | - |
214 | | - try { |
215 | | - List<String> caches = loadCaches(); |
216 | | - |
217 | | - caches.add(cacheName); |
218 | | - |
219 | | - save(caches); |
220 | | - } |
221 | | - catch (IOException e) { |
222 | | - throw new IgniteException(e); |
223 | | - } |
224 | | - |
225 | | - if (log.isInfoEnabled()) |
226 | | - log.info("Cache has been added to replication [cacheName=" + cacheName + "]"); |
227 | | - } |
228 | | - } |
229 | | - |
230 | | - /** |
231 | | - * Writes caches list to file |
232 | | - * |
233 | | - * @param caches Caches list. |
234 | | - */ |
235 | | - private void save(List<String> caches) throws IOException { |
236 | | - if (cdcDir == null) { |
237 | | - throw new IgniteException("Can't write to '" + SAVED_CACHES_FILE + "' file. Cdc directory is null"); |
238 | | - } |
239 | | - Path savedCachesPath = cdcDir.resolve(SAVED_CACHES_FILE); |
240 | | - Path tmpSavedCachesPath = cdcDir.resolve(SAVED_CACHES_TMP_FILE); |
241 | | - |
242 | | - StringBuilder cacheList = new StringBuilder(); |
243 | | - |
244 | | - for (String cache : caches) { |
245 | | - cacheList.append(cache); |
246 | | - |
247 | | - cacheList.append('\n'); |
248 | | - } |
249 | | - |
250 | | - Files.write(tmpSavedCachesPath, cacheList.toString().getBytes()); |
251 | | - |
252 | | - Files.move(tmpSavedCachesPath, savedCachesPath, ATOMIC_MOVE, REPLACE_EXISTING); |
253 | | - } |
254 | | - |
255 | | - /** |
256 | | - * Loads saved caches from file. |
257 | | - * |
258 | | - * @return List of saved caches names. |
259 | | - */ |
260 | | - private List<String> loadCaches() throws IOException { |
261 | | - if (cdcDir == null) { |
262 | | - throw new IgniteException("Can't load '" + SAVED_CACHES_FILE + "' file. Cdc directory is null"); |
263 | | - } |
264 | | - Path savedCachesPath = cdcDir.resolve(SAVED_CACHES_FILE); |
265 | | - |
266 | | - if (Files.notExists(savedCachesPath)) { |
267 | | - Files.createFile(savedCachesPath); |
268 | | - |
269 | | - if (log.isInfoEnabled()) |
270 | | - log.info("Cache list created: " + savedCachesPath); |
271 | | - } |
272 | | - |
273 | | - return Files.readAllLines(savedCachesPath); |
274 | | - } |
275 | | - |
276 | | - /** |
277 | | - * Compiles regex patterns from user templates. |
278 | | - * |
279 | | - * @throws PatternSyntaxException If the template's syntax is invalid |
280 | | - */ |
281 | | - private void prepareRegexFilters() { |
282 | | - includeFilters = includeTemplates.stream() |
283 | | - .map(Pattern::compile) |
284 | | - .collect(Collectors.toSet()); |
285 | | - |
286 | | - excludeFilters = excludeTemplates.stream() |
287 | | - .map(Pattern::compile) |
288 | | - .collect(Collectors.toSet()); |
289 | | - } |
290 | | - |
291 | | - /** |
292 | | - * Matches cache name with compiled regex patterns. |
293 | | - * |
294 | | - * @param cacheName Cache name. |
295 | | - * @return True if cache name match include patterns and don't match exclude patterns. |
296 | | - */ |
297 | | - private boolean matchesFilters(String cacheName) { |
298 | | - boolean matchesInclude = includeFilters.stream() |
299 | | - .anyMatch(pattern -> pattern.matcher(cacheName).matches()); |
300 | | - |
301 | | - boolean notMatchesExclude = excludeFilters.stream() |
302 | | - .noneMatch(pattern -> pattern.matcher(cacheName).matches()); |
303 | | - |
304 | | - return matchesInclude && notMatchesExclude; |
305 | 187 | } |
306 | 188 |
|
307 | 189 | /** {@inheritDoc} */ |
308 | 190 | @Override public void onCacheDestroy(Iterator<Integer> caches) { |
309 | | - caches.forEachRemaining(this::deleteRegexpCacheIfPresent); |
310 | | - } |
311 | | - |
312 | | - /** |
313 | | - * Removes cache added by regexp from cache list, if this cache is present in file, to prevent file size overflow. |
314 | | - * |
315 | | - * @param cacheId Cache id. |
316 | | - */ |
317 | | - private void deleteRegexpCacheIfPresent(Integer cacheId) { |
318 | | - try { |
319 | | - List<String> caches = loadCaches(); |
320 | | - |
321 | | - Optional<String> cacheName = caches.stream() |
322 | | - .filter(name -> CU.cacheId(name) == cacheId) |
323 | | - .findAny(); |
324 | | - |
325 | | - if (cacheName.isPresent()) { |
326 | | - String name = cacheName.get(); |
327 | | - |
328 | | - caches.remove(name); |
329 | | - |
330 | | - save(caches); |
331 | | - |
332 | | - if (log.isInfoEnabled()) |
333 | | - log.info("Cache has been removed from replication [cacheName=" + name + ']'); |
334 | | - } |
335 | | - } |
336 | | - catch (IOException e) { |
337 | | - throw new IgniteException(e); |
338 | | - } |
| 191 | + caches.forEachRemaining(regexManager::deleteRegexpCacheIfPresent); |
339 | 192 | } |
340 | 193 |
|
341 | 194 | /** {@inheritDoc} */ |
|
0 commit comments