1
1
/*
2
- * Copyright 2015-2020 the original author or authors.
2
+ * Copyright 2015-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
24
24
25
25
import org .apache .curator .framework .CuratorFramework ;
26
26
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 ;
30
29
import org .apache .curator .utils .CloseableUtils ;
31
30
import org .apache .zookeeper .KeeperException ;
32
31
import org .apache .zookeeper .data .Stat ;
@@ -51,8 +50,6 @@ public class ZookeeperMetadataStore implements ListenableMetadataStore, SmartLif
51
50
52
51
private static final String KEY_MUST_NOT_BE_NULL = "'key' must not be null." ;
53
52
54
- private final Object lifecycleMonitor = new Object ();
55
-
56
53
private final CuratorFramework client ;
57
54
58
55
private final List <MetadataStoreListener > listeners = new CopyOnWriteArrayList <>();
@@ -67,13 +64,13 @@ public class ZookeeperMetadataStore implements ListenableMetadataStore, SmartLif
67
64
68
65
private String encoding = StandardCharsets .UTF_8 .name ();
69
66
70
- private PathChildrenCache cache ;
67
+ private CuratorCache cache ;
71
68
72
69
private boolean autoStartup = true ;
73
70
74
71
private int phase = Integer .MAX_VALUE ;
75
72
76
- private volatile boolean running = false ;
73
+ private boolean running ;
77
74
78
75
public ZookeeperMetadataStore (CuratorFramework client ) {
79
76
Assert .notNull (client , "Client cannot be null" );
@@ -197,27 +194,27 @@ public String get(String key) {
197
194
Assert .notNull (key , KEY_MUST_NOT_BE_NULL );
198
195
Assert .state (isRunning (), "ZookeeperMetadataStore has to be started before using." );
199
196
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 ()) {
216
202
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
+ });
221
218
}
222
219
}
223
220
@@ -264,46 +261,38 @@ public boolean isAutoStartup() {
264
261
}
265
262
266
263
@ Override
267
- public void start () {
264
+ public synchronized void start () {
268
265
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 );
286
279
}
287
280
}
288
281
}
289
282
290
283
@ Override
291
- public void stop () {
284
+ public synchronized void stop () {
292
285
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 );
301
288
}
289
+ this .cache = null ;
290
+ this .running = false ;
302
291
}
303
292
}
304
293
305
294
@ Override
306
- public boolean isRunning () {
295
+ public synchronized boolean isRunning () {
307
296
return this .running ;
308
297
}
309
298
@@ -338,45 +327,41 @@ private int getVersion() {
338
327
339
328
}
340
329
341
- private class MetadataStoreListenerInvokingPathChildrenCacheListener implements PathChildrenCacheListener {
330
+ private class MetadataStoreCacheListener implements CuratorCacheListener {
342
331
343
- MetadataStoreListenerInvokingPathChildrenCacheListener () {
332
+ MetadataStoreCacheListener () {
344
333
}
345
334
346
335
@ 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 ;
380
365
}
381
366
}
382
367
0 commit comments