2 * Copyright (c) 2015 Cisco Systems, 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.openflowplugin.impl.device;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.SettableFuture;
13 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
20 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
21 import org.opendaylight.openflowplugin.api.openflow.device.*;
22 import org.opendaylight.openflowplugin.api.openflow.device.exception.DeviceDataException;
23 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
24 import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.Error;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableFeatures;
28 import org.opendaylight.yangtools.yang.binding.ChildOf;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.common.RpcError;
31 import org.opendaylight.yangtools.yang.common.RpcResult;
32 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import javax.annotation.Nonnull;
37 import java.math.BigInteger;
38 import java.util.HashMap;
39 import java.util.List;
41 import java.util.concurrent.Future;
46 public class DeviceContextImpl implements DeviceContext, DeviceReplyProcessor, TransactionChainListener {
48 private static final Logger LOG = LoggerFactory.getLogger(DeviceContextImpl.class);
50 private final ConnectionContext primaryConnectionContext;
51 private final DeviceState deviceState;
52 private final DataBroker dataBroker;
53 private final XidGenerator xidGenerator;
54 private Map<Long, RequestContext> requests =
55 new HashMap<Long, RequestContext>();
57 private final Map<SwitchConnectionDistinguisher, ConnectionContext> auxiliaryConnectionContexts;
58 private BindingTransactionChain txChainFactory;
61 DeviceContextImpl(@Nonnull final ConnectionContext primaryConnectionContext,
62 @Nonnull final DeviceState deviceState, @Nonnull final DataBroker dataBroker) {
63 this.primaryConnectionContext = Preconditions.checkNotNull(primaryConnectionContext);
64 this.deviceState = Preconditions.checkNotNull(deviceState);
65 this.dataBroker = Preconditions.checkNotNull(dataBroker);
66 xidGenerator = new XidGenerator();
67 txChainFactory = dataBroker.createTransactionChain(DeviceContextImpl.this);
68 auxiliaryConnectionContexts = new HashMap<>();
69 requests = new HashMap<>();
73 public <M extends ChildOf<DataObject>> void onMessage(final M message, final RequestContext requestContext) {
74 // TODO Auto-generated method stub
79 public void addAuxiliaryConenctionContext(final ConnectionContext connectionContext) {
80 final SwitchConnectionDistinguisher connectionDistinguisher = new SwitchConnectionCookieOFImpl(connectionContext.getFeatures().getAuxiliaryId());
81 auxiliaryConnectionContexts.put(connectionDistinguisher, connectionContext);
85 public void removeAuxiliaryConenctionContext(final ConnectionContext connectionContext) {
86 // TODO Auto-generated method stub
91 public DeviceState getDeviceState() {
96 public ReadTransaction getReadTransaction() {
97 return dataBroker.newReadOnlyTransaction();
101 public WriteTransaction getWriteTransaction() {
102 // FIXME : we wana to have only one WriteTransaction exposed in one time
103 // so thing about blocking notification mechanism for wait to new transaction
104 return txChainFactory.newWriteOnlyTransaction();
108 public TableFeatures getCapabilities() {
109 // TODO Auto-generated method stub
114 public ConnectionContext getPrimaryConnectionContext() {
115 return primaryConnectionContext;
119 public ConnectionContext getAuxiliaryConnectiobContexts(final BigInteger cookie) {
120 return auxiliaryConnectionContexts.get(new SwitchConnectionCookieOFImpl(cookie.longValue()));
124 public Xid getNextXid() {
125 return xidGenerator.generate();
128 public Map<Long, RequestContext> getRequests() {
133 public void hookRequestCtx(Xid xid, RequestContext requestFutureContext) {
134 // TODO Auto-generated method stub
135 requests.put(xid.getValue(), requestFutureContext);
139 public void processReply(OfHeader ofHeader) {
140 RequestContext requestContext = getRequests().get(ofHeader.getXid());
141 SettableFuture replyFuture = requestContext.getFuture();
142 getRequests().remove(ofHeader.getXid());
143 RpcResult<OfHeader> rpcResult;
145 if(ofHeader instanceof Error) {
146 Error error = (Error) ofHeader;
147 String message = "Operation on device failed";
148 rpcResult= RpcResultBuilder
150 .withError(RpcError.ErrorType.APPLICATION, message, new DeviceDataException(message, error))
153 rpcResult= RpcResultBuilder
155 .withResult(ofHeader)
159 replyFuture.set(rpcResult);
161 requestContext.close();
162 } catch (Exception e) {
163 LOG.error("Closing RequestContext failed: ", e);
168 public void processReply(Xid xid, List<OfHeader> ofHeaderList) {
169 RequestContext requestContext = getRequests().get(xid.getValue());
170 SettableFuture replyFuture = requestContext.getFuture();
171 getRequests().remove(xid.getValue());
172 RpcResult<List<OfHeader>> rpcResult= RpcResultBuilder
173 .<List<OfHeader>>success()
174 .withResult(ofHeaderList)
176 replyFuture.set(rpcResult);
178 requestContext.close();
179 } catch (Exception e) {
180 LOG.error("Closing RequestContext failed: ", e);
185 public void processException(Xid xid, DeviceDataException deviceDataException) {
186 RequestContext requestContext = getRequests().get(xid.getValue());
188 SettableFuture replyFuture = requestContext.getFuture();
189 getRequests().remove(xid.getValue());
190 RpcResult<List<OfHeader>> rpcResult= RpcResultBuilder
191 .<List<OfHeader>>failed()
192 .withError(RpcError.ErrorType.APPLICATION, "Message processing failed", deviceDataException)
194 replyFuture.set(rpcResult);
196 requestContext.close();
197 } catch (Exception e) {
198 LOG.error("Closing RequestContext failed: ", e);
203 public void onTransactionChainFailed(TransactionChain<?, ?> chain,
204 AsyncTransaction<?, ?> transaction, Throwable cause) {
205 txChainFactory.close();
206 txChainFactory = dataBroker.createTransactionChain(DeviceContextImpl.this);
211 public void onTransactionChainSuccessful(TransactionChain<?, ?> chain) {
212 // NOOP - only yet, here is probably place for notification to get new WriteTransaction