11/**
2- * Licensed to the Apache Software Foundation (ASF) under one
3- * or more contributor license agreements. See the NOTICE file
4- * distributed with this work for additional information
5- * regarding copyright ownership. The ASF licenses this file
6- * to you under the Apache License, Version 2.0 (the
7- * "License"); you may not use this file except in compliance
8- * with the License. You may obtain a copy of the License at
9- *
10- * http://www.apache.org/licenses/LICENSE-2.0
11- *
12- * Unless required by applicable law or agreed to in writing, software
13- * distributed under the License is distributed on an "AS IS" BASIS,
14- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15- * See the License for the specific language governing permissions and
16- * limitations under the License.
17- */
2+ * Licensed to the Apache Software Foundation (ASF) under one
3+ * or more contributor license agreements. See the NOTICE file
4+ * distributed with this work for additional information
5+ * regarding copyright ownership. The ASF licenses this file
6+ * to you under the Apache License, Version 2.0 (the
7+ * "License"); you may not use this file except in compliance
8+ * with the License. You may obtain a copy of the License at
9+ * <p>
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ * <p>
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
1818
1919package org .apache .tez .client .registry .zookeeper ;
2020
3737import org .apache .hadoop .registry .client .types .ServiceRecord ;
3838import org .apache .tez .client .registry .AMRecord ;
3939import org .apache .tez .client .registry .AMRegistryClient ;
40- import org .apache .tez .client .registry .AMRegistryClientListener ;
4140import org .apache .tez .dag .api .TezConfiguration ;
4241
4342import com .google .common .base .Preconditions ;
4645import org .slf4j .LoggerFactory ;
4746
4847/**
49- * Curator/Zookeeper impl of AMRegistryClient
50- */
48+ * Curator/Zookeeper implementation of {@link AMRegistryClient}.
49+ */
5150@ InterfaceAudience .Public
5251public class ZkAMRegistryClient extends AMRegistryClient {
5352 private static final Logger LOG = LoggerFactory .getLogger (ZkAMRegistryClient .class );
@@ -57,7 +56,6 @@ public class ZkAMRegistryClient extends AMRegistryClient {
5756 //Cache of known AMs
5857 private ConcurrentHashMap <String , AMRecord > amRecordCache = new ConcurrentHashMap <>();
5958 private CuratorFramework client ;
60- private PathChildrenCache cache ;
6159
6260 private static Map <String , ZkAMRegistryClient > INSTANCES = new HashMap <>();
6361
@@ -79,7 +77,7 @@ private ZkAMRegistryClient(final Configuration conf) {
7977 public void start () throws Exception {
8078 ZkConfig zkConf = new ZkConfig (this .conf );
8179 client = zkConf .createCuratorFramework ();
82- cache = new PathChildrenCache (client , zkConf .getZkNamespace (), true );
80+ PathChildrenCache cache = new PathChildrenCache (client , zkConf .getZkNamespace (), true );
8381 client .start ();
8482 cache .start (PathChildrenCache .StartMode .BUILD_INITIAL_CACHE );
8583 for (ChildData childData : cache .getCurrentData ()) {
@@ -91,7 +89,15 @@ public void start() throws Exception {
9189 cache .getListenable ().addListener (new ZkRegistryListener ());
9290 }
9391
94- //Deserialize ServiceRecord from Zookeeper to populate AMRecord in cache
92+ /**
93+ * Deserializes a {@link ServiceRecord} from ZooKeeper data and converts it into an {@link AMRecord}
94+ * for caching.
95+ *
96+ * @param childData the ZooKeeper node data containing a serialized {@link ServiceRecord}
97+ * @return an {@link AMRecord} constructed from the deserialized {@link ServiceRecord}, or {@code null}
98+ * if no data is present
99+ * @throws IOException if the data cannot be deserialized into a {@link ServiceRecord}
100+ */
95101 public static AMRecord getAMRecord (final ChildData childData ) throws IOException {
96102 byte [] data = childData .getData ();
97103 // only the path appeared, there is no data yet
@@ -104,75 +110,76 @@ public static AMRecord getAMRecord(final ChildData childData) throws IOException
104110 return new AMRecord (serviceRecord );
105111 }
106112
107- @ Override public AMRecord getRecord (String appId ) {
113+ @ Override
114+ public AMRecord getRecord (String appId ) {
108115 if (amRecordCache .get (appId ) == null ) {
109116 return null ;
110117 }
111118 //Return a copy
112119 return new AMRecord (amRecordCache .get (appId ));
113120 }
114121
115- @ Override public List <AMRecord > getAllRecords () {
116- return amRecordCache .values ().stream ()
117- .map (record -> new AMRecord (record )).collect (Collectors .toList ());
118- }
119-
120- @ Override public synchronized void addListener (AMRegistryClientListener listener ) {
121- listeners .add (listener );
122+ @ Override
123+ public List <AMRecord > getAllRecords () {
124+ return amRecordCache .values ().stream ().map (AMRecord ::new ).collect (Collectors .toList ());
122125 }
123126
124- //Callback for Zookeeper to update local cache
127+ /**
128+ * Callback listener for ZooKeeper events that updates the local cache
129+ * when child nodes under the monitored path change.
130+ */
125131 private class ZkRegistryListener implements PathChildrenCacheListener {
126132
127- @ Override public void childEvent (final CuratorFramework client , final PathChildrenCacheEvent event )
128- throws Exception {
129- Preconditions .checkArgument (client != null && client .getState () == CuratorFrameworkState .STARTED ,
133+ @ Override
134+ public void childEvent (final CuratorFramework clientParam , final PathChildrenCacheEvent event )
135+ throws Exception {
136+ Preconditions .checkArgument (clientParam != null && clientParam .getState () == CuratorFrameworkState .STARTED ,
130137 "Curator client is not started" );
131138
132- ChildData childData = event .getData ();
133- switch (event .getType ()) {
134- case CHILD_ADDED :
135- if (isEmpty (childData )) {
136- LOG .info ("AppId allocated: {}" , childData .getPath ());
137- } else {
138- AMRecord amRecord = getAMRecord (childData );
139- if (amRecord != null ) {
140- LOG .info ("AM registered with data: {}. Notifying {} listeners." , amRecord , listeners .size ());
141- amRecordCache .put (amRecord .getApplicationId ().toString (), amRecord );
142- notifyOnAdded (amRecord );
139+ ChildData childData = event .getData ();
140+ switch (event .getType ()) {
141+ case CHILD_ADDED :
142+ if (isEmpty (childData )) {
143+ LOG .info ("AppId allocated: {}" , childData .getPath ());
144+ } else {
145+ AMRecord amRecord = getAMRecord (childData );
146+ if (amRecord != null ) {
147+ LOG .info ("AM registered with data: {}. Notifying {} listeners." , amRecord , listeners .size ());
148+ amRecordCache .put (amRecord .getApplicationId ().toString (), amRecord );
149+ notifyOnAdded (amRecord );
150+ }
151+ }
152+ break ;
153+ case CHILD_UPDATED :
154+ if (isEmpty (childData )) {
155+ throw new RuntimeException ("AM updated with empty data" );
156+ } else {
157+ AMRecord amRecord = getAMRecord (childData );
158+ if (amRecord != null ) {
159+ LOG .info ("AM updated data: {}. Notifying {} listeners." , amRecord , listeners .size ());
160+ amRecordCache .put (amRecord .getApplicationId ().toString (), amRecord );
161+ notifyOnAdded (amRecord );
162+ }
143163 }
144- }
145- break ;
146- case CHILD_UPDATED :
147- if ( isEmpty ( childData )) {
148- throw new RuntimeException ( "AM updated with empty data" );
149- } else {
150- AMRecord amRecord = getAMRecord ( childData );
151- if ( amRecord != null ) {
152- LOG . info ( "AM updated data: {}. Notifying {} listeners." , amRecord , listeners . size () );
153- amRecordCache . put ( amRecord . getApplicationId (). toString (), amRecord );
154- notifyOnAdded ( amRecord );
164+ break ;
165+ case CHILD_REMOVED :
166+ if ( isEmpty ( childData )) {
167+ LOG . info ( "Unused AppId unregistered: {}" , childData . getPath ());
168+ } else {
169+ AMRecord amRecord = getAMRecord ( childData );
170+ if ( amRecord != null ) {
171+ LOG . info ( "AM removed: {}. Notifying {} listeners." , amRecord , listeners . size ());
172+ amRecordCache . remove ( amRecord . getApplicationId (). toString (), amRecord );
173+ notifyOnRemoved ( amRecord );
174+ }
155175 }
156- }
157- break ;
158- case CHILD_REMOVED :
159- if (isEmpty (childData )) {
160- LOG .info ("Unused AppId unregistered: {}" , childData .getPath ());
161- } else {
162- AMRecord amRecord = getAMRecord (childData );
163- if (amRecord != null ) {
164- LOG .info ("AM removed: {}. Notifying {} listeners." , amRecord , listeners .size ());
165- amRecordCache .remove (amRecord .getApplicationId ().toString (), amRecord );
166- notifyOnRemoved (amRecord );
176+ break ;
177+ default :
178+ if (childData == null ) {
179+ LOG .info ("Ignored event {}" , event .getType ());
180+ } else {
181+ LOG .info ("Ignored event {} for {}" , event .getType (), childData .getPath ());
167182 }
168- }
169- break ;
170- default :
171- if (childData == null ) {
172- LOG .info ("Ignored event {}" , event .getType ());
173- } else {
174- LOG .info ("Ignored event {} for {}" , event .getType (), childData .getPath ());
175- }
176183 }
177184 }
178185
0 commit comments