HONEYCOMB-206: change package name to match groupId
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / vpp / BridgeDomainCustomizer.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.translate.v3po.vpp;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
22 import com.google.common.base.Preconditions;
23 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
24 import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator;
25 import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer;
26 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
27 import io.fd.honeycomb.translate.vpp.util.NamingContext;
28 import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
29 import io.fd.honeycomb.translate.write.WriteContext;
30 import io.fd.honeycomb.translate.write.WriteFailedException;
31 import javax.annotation.Nonnull;
32 import javax.annotation.concurrent.GuardedBy;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.openvpp.jvpp.VppBaseCallException;
37 import org.openvpp.jvpp.core.dto.BridgeDomainAddDel;
38 import org.openvpp.jvpp.core.dto.BridgeDomainAddDelReply;
39 import org.openvpp.jvpp.core.future.FutureJVppCore;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class BridgeDomainCustomizer
44         extends FutureJVppCustomizer
45         implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey>, ByteDataTranslator, JvppReplyConsumer {
46
47     private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
48
49     private static final byte ADD_OR_UPDATE_BD = (byte) 1;
50     private final NamingContext bdContext;
51     @GuardedBy("this")
52     private int bridgeDomainIndexCounter = 1;
53
54     public BridgeDomainCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
55                                   @Nonnull final NamingContext bdContext) {
56         super(futureJVppCore);
57         this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null");
58     }
59
60     private BridgeDomainAddDelReply addOrUpdateBridgeDomain(@Nonnull final InstanceIdentifier<BridgeDomain> id,
61                                                             final int bdId, @Nonnull final BridgeDomain bd)
62             throws VppBaseCallException, WriteTimeoutException {
63         final BridgeDomainAddDelReply reply;
64         final BridgeDomainAddDel request = new BridgeDomainAddDel();
65         request.bdId = bdId;
66         request.flood = booleanToByte(bd.isFlood());
67         request.forward = booleanToByte(bd.isForward());
68         request.learn = booleanToByte(bd.isLearn());
69         request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
70         request.arpTerm = booleanToByte(bd.isArpTermination());
71         request.isAdd = ADD_OR_UPDATE_BD;
72
73         reply = getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
74         LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId);
75         return reply;
76     }
77
78     @Override
79     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
80                                        @Nonnull final BridgeDomain dataBefore,
81                                        @Nonnull final WriteContext ctx)
82             throws WriteFailedException {
83         LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx);
84         final String bdName = dataBefore.getName();
85
86         // Invoke 1. check index, 2. increase index 3. create ND 4. store mapping in a synchronized block to prevent
87         // race conditions in case of concurrent invocation
88         synchronized (this) {
89             try {
90                 int index;
91                 if (bdContext.containsIndex(bdName, ctx.getMappingContext())) {
92                     index = bdContext.getIndex(bdName, ctx.getMappingContext());
93                 } else {
94                     // Critical section due to bridgeDomainIndexCounter read and write access
95                     // TODO HONEYCOMB-199 move this "get next available index" into naming context or an adapter
96                     // or a dedicated object
97
98                     // Use counter to assign bridge domain index, but still check naming context if it's not taken there
99                     while (bdContext.containsName(bridgeDomainIndexCounter, ctx.getMappingContext())) {
100                         bridgeDomainIndexCounter++;
101                     }
102                     index = bridgeDomainIndexCounter;
103                 }
104                 addOrUpdateBridgeDomain(id, index, dataBefore);
105                 bdContext.addName(index, bdName, ctx.getMappingContext());
106             } catch (VppBaseCallException e) {
107                 LOG.warn("Failed to create bridge domain", e);
108                 throw new WriteFailedException.CreateFailedException(id, dataBefore, e);
109             }
110         }
111     }
112
113     @Override
114     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
115                                         @Nonnull final BridgeDomain dataBefore,
116                                         @Nonnull final WriteContext ctx)
117             throws WriteFailedException {
118         LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
119         final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
120         int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
121         try {
122
123             final BridgeDomainAddDel request = new BridgeDomainAddDel();
124             request.bdId = bdId;
125
126             getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
127             LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId);
128         } catch (VppBaseCallException e) {
129             LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId);
130             throw new WriteFailedException.DeleteFailedException(id, e);
131         }
132     }
133
134     @Override
135     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
136                                         @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
137                                         @Nonnull final WriteContext ctx)
138             throws WriteFailedException {
139         LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter,
140                 ctx);
141
142         final String bdName = checkNotNull(dataAfter.getName());
143         checkArgument(bdName.equals(dataBefore.getName()),
144                 "BridgeDomain name changed. It should be deleted and then created.");
145
146         try {
147             addOrUpdateBridgeDomain(id, bdContext.getIndex(bdName, ctx.getMappingContext()), dataAfter);
148         } catch (VppBaseCallException e) {
149             LOG.warn("Failed to create bridge domain", e);
150             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
151         }
152     }
153
154 }