Skip to content

Commit abd94bd

Browse files
committed
GH-3435: Upgrade to curator-recipes 5.3.0
Fixes #3435 * Migrate `ZookeeperMetadataStore` from deprecated `PathChildrenCache` to the `CuratorCache` and respective `CuratorCacheListener`
1 parent 0f7b3e6 commit abd94bd

File tree

2 files changed

+77
-92
lines changed

2 files changed

+77
-92
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ ext {
5757
commonsDbcp2Version = '2.9.0'
5858
commonsIoVersion = '2.11.0'
5959
commonsNetVersion = '3.8.0'
60-
curatorVersion = '4.3.0'
60+
curatorVersion = '5.3.0'
6161
derbyVersion = '10.14.2.0'
6262
findbugsVersion = '3.0.1'
6363
ftpServerVersion = '1.2.0'

spring-integration-zookeeper/src/main/java/org/springframework/integration/zookeeper/metadata/ZookeeperMetadataStore.java

Lines changed: 76 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2020 the original author or authors.
2+
* Copyright 2015-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,9 +24,8 @@
2424

2525
import org.apache.curator.framework.CuratorFramework;
2626
import org.apache.curator.framework.recipes.cache.ChildData;
27-
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
28-
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
29-
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
27+
import org.apache.curator.framework.recipes.cache.CuratorCache;
28+
import org.apache.curator.framework.recipes.cache.CuratorCacheListener;
3029
import org.apache.curator.utils.CloseableUtils;
3130
import org.apache.zookeeper.KeeperException;
3231
import org.apache.zookeeper.data.Stat;
@@ -51,8 +50,6 @@ public class ZookeeperMetadataStore implements ListenableMetadataStore, SmartLif
5150

5251
private static final String KEY_MUST_NOT_BE_NULL = "'key' must not be null.";
5352

54-
private final Object lifecycleMonitor = new Object();
55-
5653
private final CuratorFramework client;
5754

5855
private final List<MetadataStoreListener> listeners = new CopyOnWriteArrayList<>();
@@ -67,13 +64,13 @@ public class ZookeeperMetadataStore implements ListenableMetadataStore, SmartLif
6764

6865
private String encoding = StandardCharsets.UTF_8.name();
6966

70-
private PathChildrenCache cache;
67+
private CuratorCache cache;
7168

7269
private boolean autoStartup = true;
7370

7471
private int phase = Integer.MAX_VALUE;
7572

76-
private volatile boolean running = false;
73+
private boolean running;
7774

7875
public ZookeeperMetadataStore(CuratorFramework client) {
7976
Assert.notNull(client, "Client cannot be null");
@@ -197,27 +194,27 @@ public String get(String key) {
197194
Assert.notNull(key, KEY_MUST_NOT_BE_NULL);
198195
Assert.state(isRunning(), "ZookeeperMetadataStore has to be started before using.");
199196
synchronized (this.updateMap) {
200-
ChildData currentData = this.cache.getCurrentData(getPath(key));
201-
if (currentData == null) {
202-
if (this.updateMap.containsKey(key)) {
203-
// we have saved the value, but the cache hasn't updated yet
204-
// if the value had changed via replication, we would have been notified by the listener
205-
return this.updateMap.get(key).getValue();
206-
}
207-
else {
208-
// the value just doesn't exist
209-
return null;
210-
}
211-
}
212-
else {
213-
// our version is more recent than the cache
214-
if (this.updateMap.containsKey(key) &&
215-
this.updateMap.get(key).getVersion() >= currentData.getStat().getVersion()) {
197+
return this.cache.get(getPath(key))
198+
.map(currentData -> {
199+
// our version is more recent than the cache
200+
if (this.updateMap.containsKey(key) &&
201+
this.updateMap.get(key).getVersion() >= currentData.getStat().getVersion()) {
216202

217-
return this.updateMap.get(key).getValue();
218-
}
219-
return IntegrationUtils.bytesToString(currentData.getData(), this.encoding);
220-
}
203+
return this.updateMap.get(key).getValue();
204+
}
205+
return IntegrationUtils.bytesToString(currentData.getData(), this.encoding);
206+
})
207+
.orElseGet(() -> {
208+
if (this.updateMap.containsKey(key)) {
209+
// we have saved the value, but the cache hasn't updated yet
210+
// if the value had changed via replication, we would have been notified by the listener
211+
return this.updateMap.get(key).getValue();
212+
}
213+
else {
214+
// the value just doesn't exist
215+
return null;
216+
}
217+
});
221218
}
222219
}
223220

@@ -264,46 +261,38 @@ public boolean isAutoStartup() {
264261
}
265262

266263
@Override
267-
public void start() {
264+
public synchronized void start() {
268265
if (!this.running) {
269-
synchronized (this.lifecycleMonitor) {
270-
if (!this.running) {
271-
try {
272-
this.client.checkExists()
273-
.creatingParentContainersIfNeeded()
274-
.forPath(this.root);
275-
276-
this.cache = new PathChildrenCache(this.client, this.root, true);
277-
this.cache.getListenable()
278-
.addListener(new MetadataStoreListenerInvokingPathChildrenCacheListener());
279-
this.cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
280-
this.running = true;
281-
}
282-
catch (Exception e) {
283-
throw new ZookeeperMetadataStoreException("Exception while starting bean", e);
284-
}
285-
}
266+
try {
267+
this.client.checkExists()
268+
.creatingParentContainersIfNeeded()
269+
.forPath(this.root);
270+
271+
this.cache = CuratorCache.builder(this.client, this.root).build();
272+
this.cache.listenable().addListener(new MetadataStoreCacheListener());
273+
this.client.createContainers(this.root);
274+
this.cache.start();
275+
this.running = true;
276+
}
277+
catch (Exception e) {
278+
throw new ZookeeperMetadataStoreException("Exception while starting bean", e);
286279
}
287280
}
288281
}
289282

290283
@Override
291-
public void stop() {
284+
public synchronized void stop() {
292285
if (this.running) {
293-
synchronized (this.lifecycleMonitor) {
294-
if (this.running) {
295-
if (this.cache != null) {
296-
CloseableUtils.closeQuietly(this.cache);
297-
}
298-
this.cache = null;
299-
this.running = false;
300-
}
286+
if (this.cache != null) {
287+
CloseableUtils.closeQuietly(this.cache);
301288
}
289+
this.cache = null;
290+
this.running = false;
302291
}
303292
}
304293

305294
@Override
306-
public boolean isRunning() {
295+
public synchronized boolean isRunning() {
307296
return this.running;
308297
}
309298

@@ -338,45 +327,41 @@ private int getVersion() {
338327

339328
}
340329

341-
private class MetadataStoreListenerInvokingPathChildrenCacheListener implements PathChildrenCacheListener {
330+
private class MetadataStoreCacheListener implements CuratorCacheListener {
342331

343-
MetadataStoreListenerInvokingPathChildrenCacheListener() {
332+
MetadataStoreCacheListener() {
344333
}
345334

346335
@Override
347-
public void childEvent(CuratorFramework framework, PathChildrenCacheEvent event) {
348-
synchronized (ZookeeperMetadataStore.this.updateMap) {
349-
String eventPath = event.getData().getPath();
350-
String eventKey = getKey(eventPath);
351-
String value =
352-
IntegrationUtils.bytesToString(event.getData().getData(), ZookeeperMetadataStore.this.encoding);
353-
switch (event.getType()) {
354-
case CHILD_ADDED:
355-
if (ZookeeperMetadataStore.this.updateMap.containsKey(eventKey) &&
356-
event.getData().getStat().getVersion() >=
357-
ZookeeperMetadataStore.this.updateMap.get(eventKey).getVersion()) {
358-
359-
ZookeeperMetadataStore.this.updateMap.remove(eventPath);
360-
}
361-
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onAdd(eventKey, value));
362-
break;
363-
case CHILD_UPDATED:
364-
if (ZookeeperMetadataStore.this.updateMap.containsKey(eventKey) &&
365-
event.getData().getStat().getVersion() >=
366-
ZookeeperMetadataStore.this.updateMap.get(eventKey).getVersion()) {
367-
368-
ZookeeperMetadataStore.this.updateMap.remove(eventPath);
369-
}
370-
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onUpdate(eventKey, value));
371-
break;
372-
case CHILD_REMOVED:
373-
ZookeeperMetadataStore.this.updateMap.remove(eventKey);
374-
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onRemove(eventKey, value));
375-
break;
376-
default:
377-
// ignore all other events
378-
break;
379-
}
336+
public void event(Type type, ChildData oldData, ChildData newData) {
337+
ChildData data = Type.NODE_DELETED.equals(type) ? oldData : newData;
338+
String eventPath = data.getPath();
339+
String eventKey = getKey(eventPath);
340+
String value = IntegrationUtils.bytesToString(data.getData(), ZookeeperMetadataStore.this.encoding);
341+
342+
switch (type) {
343+
case NODE_CREATED:
344+
if (ZookeeperMetadataStore.this.updateMap.containsKey(eventKey) &&
345+
data.getStat().getVersion() >=
346+
ZookeeperMetadataStore.this.updateMap.get(eventKey).getVersion()) {
347+
348+
ZookeeperMetadataStore.this.updateMap.remove(eventPath);
349+
}
350+
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onAdd(eventKey, value));
351+
break;
352+
case NODE_CHANGED:
353+
if (ZookeeperMetadataStore.this.updateMap.containsKey(eventKey) &&
354+
data.getStat().getVersion() >=
355+
ZookeeperMetadataStore.this.updateMap.get(eventKey).getVersion()) {
356+
357+
ZookeeperMetadataStore.this.updateMap.remove(eventPath);
358+
}
359+
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onUpdate(eventKey, value));
360+
break;
361+
case NODE_DELETED:
362+
ZookeeperMetadataStore.this.updateMap.remove(eventKey);
363+
ZookeeperMetadataStore.this.listeners.forEach((listener) -> listener.onRemove(eventKey, value));
364+
break;
380365
}
381366
}
382367

0 commit comments

Comments
 (0)