2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.ovsdb.utils.mdsal.utils;
10 import java.util.Collection;
11 import java.util.HashSet;
12 import java.util.List;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.yangtools.concepts.ListenerRegistration;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * This class provides methods for checking or waiting for various md-sal operations to complete.
28 * Once an instance is created one must invoke the registerDataChangeListener method
31 public class NotifyingDataChangeListener implements AutoCloseable, DataTreeChangeListener<DataObject> {
32 private static final Logger LOG = LoggerFactory.getLogger(NotifyingDataChangeListener.class);
33 private LogicalDatastoreType type;
34 private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
35 private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
36 private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
37 private InstanceIdentifier<?> iid;
38 private final static int RETRY_WAIT = 100;
39 private final static int MDSAL_TIMEOUT_OPERATIONAL = 10000;
40 private final static int MDSAL_TIMEOUT_CONFIG = 1000;
41 private ListenerRegistration<?> listenerRegistration;
42 private List<NotifyingDataChangeListener> waitList = null;
43 private int mdsalTimeout = MDSAL_TIMEOUT_OPERATIONAL;
44 private Boolean listen;
45 public static final int BIT_CREATE = 1;
46 public static final int BIT_UPDATE = 2;
47 public static final int BIT_DELETE = 4;
48 public static final int BIT_ALL = 7;
51 public NotifyingDataChangeListener(LogicalDatastoreType type, int mask,
52 InstanceIdentifier<?> iid, List<NotifyingDataChangeListener> waitList) {
53 this(type, iid, waitList);
58 * Create a new NotifyingDataChangeListener
59 * @param type DataStore type
60 * @param iid of the md-sal object we're waiting for
61 * @param waitList for tracking outstanding changes
63 public NotifyingDataChangeListener(LogicalDatastoreType type,
64 InstanceIdentifier<?> iid, List<NotifyingDataChangeListener> waitList) {
67 this.waitList = waitList;
68 if (this.waitList != null) {
69 this.waitList.add(this);
72 mdsalTimeout = MDSAL_TIMEOUT_OPERATIONAL;
73 if (type == LogicalDatastoreType.CONFIGURATION) {
74 mdsalTimeout = MDSAL_TIMEOUT_CONFIG;
81 * Completely reset the state of this NotifyingDataChangeListener.
82 * @param type DataStore type
83 * @param iid of the md-sal object we're waiting for
86 public void modify(LogicalDatastoreType type, InstanceIdentifier<?> iid) throws Exception {
93 public void setlisten(Boolean listen) {
97 public void setMask(int mask) {
102 public void onDataTreeChanged(Collection<DataTreeModification<DataObject>> changes) {
107 for (DataTreeModification<DataObject> change: changes) {
108 DataObjectModification<DataObject> rootNode = change.getRootNode();
109 final InstanceIdentifier<DataObject> identifier = change.getRootPath().getRootIdentifier();
110 switch (rootNode.getModificationType()) {
111 case SUBTREE_MODIFIED:
113 if (rootNode.getDataBefore() == null) {
114 if ((mask & BIT_CREATE) == BIT_CREATE) {
115 LOG.info("{} DataTreeChanged: created {}", type, identifier);
116 createdIids.add(identifier);
118 } else if ((mask & BIT_UPDATE) == BIT_UPDATE) {
119 LOG.info("{} DataTreeChanged: updated {}", type, identifier);
120 updatedIids.add(identifier);
124 if ((mask & BIT_DELETE) == BIT_DELETE) {
125 LOG.info("{} DataTreeChanged: removed {}", type, identifier);
126 removedIids.add(identifier);
134 synchronized (this) {
139 public boolean isCreated(InstanceIdentifier<?> iid) {
140 return createdIids.remove(iid);
143 public boolean isUpdated(InstanceIdentifier<?> iid) {
144 return updatedIids.remove(iid);
147 public boolean isRemoved(InstanceIdentifier<?> iid) {
148 return removedIids.remove(iid);
151 public void clear() {
157 @SuppressWarnings({ "rawtypes", "unchecked" })
158 public void registerDataChangeListener(DataBroker dataBroker) {
159 listenerRegistration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(type,
160 (InstanceIdentifier)iid), this);
163 public void waitForCreation() throws InterruptedException {
164 waitForCreation(mdsalTimeout);
167 public void waitForCreation(long timeout) throws InterruptedException {
168 synchronized (this) {
169 long _start = System.currentTimeMillis();
170 LOG.info("Waiting for {} DataChanged creation on {}", type, iid);
171 while (!isCreated(iid) && System.currentTimeMillis() - _start < timeout) {
174 LOG.info("Woke up, waited {}ms for creation of {}", System.currentTimeMillis() - _start, iid);
178 public void waitForUpdate() throws InterruptedException {
179 waitForUpdate(mdsalTimeout);
182 public void waitForUpdate(long timeout) throws InterruptedException {
183 synchronized (this) {
184 long _start = System.currentTimeMillis();
185 LOG.info("Waiting for {} DataChanged update on {}", type, iid);
186 while (!isUpdated(iid) && System.currentTimeMillis() - _start < timeout) {
189 LOG.info("Woke up, waited {}ms for update of {}", System.currentTimeMillis() - _start, iid);
193 public void waitForDeletion() throws InterruptedException {
194 waitForDeletion(mdsalTimeout);
197 public void waitForDeletion(long timeout) throws InterruptedException {
198 synchronized (this) {
199 long _start = System.currentTimeMillis();
200 LOG.info("Waiting for {} DataChanged deletion on {}", type, iid);
201 while (!isRemoved(iid) && System.currentTimeMillis() - _start < timeout) {
204 LOG.info("Woke up, waited {}ms for deletion of {}", System.currentTimeMillis() - _start, iid);
209 public void close() throws Exception {
210 if (listenerRegistration != null) {
212 listenerRegistration.close();
213 } catch (final Exception ex) {
214 LOG.warn("Failed to close registration {}, iid {}", listenerRegistration, iid, ex);
217 if (waitList != null) {
218 waitList.remove(this);
220 listenerRegistration = null;