X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fservices%2FSalTableServiceImpl.java;h=ef757c9c4f80bce02bd22f370d24f8e27193fd0d;hb=e79eecfecbf3e1b1abf28de1623c8ef55d6a3ff2;hp=0d403b2f514ab8a126703b85758efe24b3f7a4ed;hpb=7beb41f5716c02589dd3dd89c5ca1e32447e6e9c;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java index 0d403b2f51..ef757c9c4f 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java @@ -7,19 +7,36 @@ */ package org.opendaylight.openflowplugin.impl.services; -import com.google.common.base.Function; - import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.JdkFutureAdapters; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; -import org.opendaylight.openflowplugin.api.OFConstants; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.TableFeaturesConvertor; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.Future; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; +import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack; +import org.opendaylight.openflowplugin.api.openflow.device.TxFacade; +import org.opendaylight.openflowplugin.api.openflow.device.Xid; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableFeaturesCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeatures; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.MultipartRequestTableFeaturesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features._case.multipart.request.table.features.TableFeatures; @@ -27,100 +44,145 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.Sal import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; -import java.math.BigInteger; -import java.util.List; -import java.util.concurrent.Future; - -/** - * @author joe - */ -public class SalTableServiceImpl extends CommonService implements SalTableService { +public final class SalTableServiceImpl extends AbstractMultipartService implements SalTableService { private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SalTableServiceImpl.class); + private final TxFacade txFacade; + private final ConvertorExecutor convertorExecutor; + private final VersionConvertorData data; + + public SalTableServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext, final ConvertorExecutor convertorExecutor) { + super(requestContextStack, deviceContext); + this.txFacade = deviceContext; + this.convertorExecutor = convertorExecutor; + data = new VersionConvertorData(getVersion()); + } @Override public Future> updateTable(final UpdateTableInput input) { - class FunctionImpl implements Function>> { + final ListenableFuture>> multipartFuture = handleServiceCall(input); + final SettableFuture> finalFuture = SettableFuture.create(); + class CallBackImpl implements FutureCallback>> { @Override - public Future> apply(final BigInteger IDConnection) { - - final SettableFuture> result = SettableFuture.create(); - - final long xid = deviceContext.getNextXid().getValue(); - - final MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder(); - final MultipartRequestTableFeaturesBuilder requestBuilder = new MultipartRequestTableFeaturesBuilder(); - final List ofTableFeatureList = TableFeaturesConvertor.toTableFeaturesRequest(input - .getUpdatedTable()); - requestBuilder.setTableFeatures(ofTableFeatureList); - caseBuilder.setMultipartRequestTableFeatures(requestBuilder.build()); - - // Set request body to main multipart request - final MultipartRequestInputBuilder mprInput = createMultipartHeader(MultipartType.OFPMPTABLEFEATURES, - xid); - mprInput.setMultipartRequestBody(caseBuilder.build()); - - final Future> resultFromOFLib = provideConnectionAdapter(PRIMARY_CONNECTION) - .multipartRequest(mprInput.build()); - final ListenableFuture> resultLib = JdkFutureAdapters - .listenInPoolThread(resultFromOFLib); - - Futures.addCallback(resultLib, new ResultCallback(result) { - @Override - public UpdateTableOutput createResult() { - final UpdateTableOutputBuilder queueStatsFromPortBuilder = new UpdateTableOutputBuilder() - .setTransactionId(new TransactionId(BigInteger.valueOf(xid))); - return queueStatsFromPortBuilder.build(); + public void onSuccess(final RpcResult> result) { + + if (result.isSuccessful()) { + final List multipartReplies = result.getResult(); + if (multipartReplies.isEmpty()) { + LOG.debug("Multipart reply to table features request shouldn't be empty list."); + finalFuture.set(RpcResultBuilder.failed() + .withError(ErrorType.RPC, "Multipart reply list is empty.").build()); + } else { + final Long xid = multipartReplies.get(0).getXid(); + LOG.debug( + "OnSuccess, rpc result successful, multipart response for rpc update-table with xid {} obtained.", + xid); + final UpdateTableOutputBuilder updateTableOutputBuilder = new UpdateTableOutputBuilder(); + updateTableOutputBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(xid))); + finalFuture.set(RpcResultBuilder.success(updateTableOutputBuilder.build()).build()); + try { + writeResponseToOperationalDatastore(multipartReplies); + } catch (Exception e) { + LOG.warn("Not able to write to operational datastore: {}", e.getMessage()); + } } - }); + } else { + LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful."); + finalFuture.set(RpcResultBuilder.failed().withRpcErrors(result.getErrors()) + .build()); + } + } - return result; + @Override + public void onFailure(final Throwable t) { + LOG.error("Failure multipart response for table features request. Exception: {}", t); + finalFuture.set(RpcResultBuilder.failed() + .withError(ErrorType.RPC, "Future error", t).build()); } } - return this.handleServiceCall( PRIMARY_CONNECTION, - new FunctionImpl()); + Futures.addCallback(multipartFuture, new CallBackImpl()); + + return finalFuture; + } + + /** + * @param multipartReplies + */ + private void writeResponseToOperationalDatastore(final List multipartReplies) throws Exception { + + final List salTableFeatures = convertToSalTableFeatures(multipartReplies); + + final InstanceIdentifier flowCapableNodeII = InstanceIdentifier.create(Nodes.class) + .child(Node.class, new NodeKey(getDeviceInfo().getNodeId())).augmentation(FlowCapableNode.class); + for (final org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures tableFeatureData : salTableFeatures) { + final Short tableId = tableFeatureData.getTableId(); + final KeyedInstanceIdentifier tableFeaturesII = flowCapableNodeII + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures.class, + new TableFeaturesKey(tableId)); + txFacade.writeToTransaction(LogicalDatastoreType.OPERATIONAL, tableFeaturesII, + tableFeatureData); + } + + txFacade.submitTransaction(); + } + + protected List convertToSalTableFeatures( + final List multipartReplies) { + final List salTableFeaturesAll = new ArrayList<>(); + for (final MultipartReply multipartReply : multipartReplies) { + if (multipartReply.getType().equals(MultipartType.OFPMPTABLEFEATURES)) { + final MultipartReplyBody multipartReplyBody = multipartReply.getMultipartReplyBody(); + if (multipartReplyBody instanceof MultipartReplyTableFeaturesCase) { + final MultipartReplyTableFeaturesCase tableFeaturesCase = ((MultipartReplyTableFeaturesCase) multipartReplyBody); + final MultipartReplyTableFeatures salTableFeatures = tableFeaturesCase + .getMultipartReplyTableFeatures(); + + final Optional> salTableFeaturesPartial = + convertorExecutor.convert(salTableFeatures, data); + + if (salTableFeaturesPartial.isPresent()) { + salTableFeaturesAll.addAll(salTableFeaturesPartial.get()); + } + + LOG.debug("TableFeature {} for xid {}.", salTableFeatures, multipartReply.getXid()); + } + } + } + return salTableFeaturesAll; } private MultipartRequestInputBuilder createMultipartHeader(final MultipartType multipart, final Long xid) { final MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder(); mprInput.setType(multipart); - mprInput.setVersion(version); + mprInput.setVersion(getVersion()); mprInput.setXid(xid); mprInput.setFlags(new MultipartRequestFlags(false)); return mprInput; } - private abstract static class ResultCallback implements FutureCallback> { - - private final SettableFuture> result; + @Override + protected OfHeader buildRequest(final Xid xid, final UpdateTableInput input) throws ServiceException { + final MultipartRequestTableFeaturesCaseBuilder caseBuilder = new MultipartRequestTableFeaturesCaseBuilder(); + final MultipartRequestTableFeaturesBuilder requestBuilder = new MultipartRequestTableFeaturesBuilder(); - /** - * @param result - */ - public ResultCallback(final SettableFuture> result) { - this.result = result; - } + final Optional> ofTableFeatureList = convertorExecutor.convert(input.getUpdatedTable(), data); + requestBuilder.setTableFeatures(ofTableFeatureList.orElse(Collections.emptyList())); + caseBuilder.setMultipartRequestTableFeatures(requestBuilder.build()); - public abstract T createResult(); + // Set request body to main multipart request + final MultipartRequestInputBuilder mprInput = createMultipartHeader(MultipartType.OFPMPTABLEFEATURES, + xid.getValue()); + mprInput.setMultipartRequestBody(caseBuilder.build()); - @Override - public void onSuccess(final RpcResult resultArg) { - result.set(RpcResultBuilder.success(createResult()).build()); - } - - @Override - public void onFailure(final Throwable t) { - result.set(RpcResultBuilder - .failed() - .withWarning(ErrorType.RPC, OFConstants.ERROR_TAG_TIMEOUT, "something wrong happened", - OFConstants.APPLICATION_TAG, "", t).build()); - } + return mprInput.build(); } - }