X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsamples%2Ftoaster-consumer%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsample%2Fkitchen%2Fimpl%2FKitchenServiceImpl.java;h=c6aa545935af5e2ae9771343706ac24a0518a363;hp=911a8c87d7166edc38c7faa2597678c8f55c611a;hb=8546c990b067c288f913d75b92dcdb652fb4dc86;hpb=04a788d2df5303c60cdbcff02254291f411566bd diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java index 911a8c87d7..c6aa545935 100644 --- a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java +++ b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/sample/kitchen/impl/KitchenServiceImpl.java @@ -1,10 +1,15 @@ package org.opendaylight.controller.sample.kitchen.impl; +import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.opendaylight.controller.config.yang.config.kitchen_service.impl.KitchenServiceRuntimeMXBean; import org.opendaylight.controller.sample.kitchen.api.EggsType; import org.opendaylight.controller.sample.kitchen.api.KitchenService; +import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInputBuilder; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterListener; @@ -12,16 +17,31 @@ import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120 import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterRestocked; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.WheatBread; +import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.util.concurrent.AsyncFunction; +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.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntimeMXBean, ToasterListener { private static final Logger log = LoggerFactory.getLogger( KitchenServiceImpl.class ); private final ToasterService toaster; + private final ListeningExecutorService executor = + MoreExecutors.listeningDecorator( Executors.newCachedThreadPool() ); + private volatile boolean toasterOutOfBread; public KitchenServiceImpl(ToasterService toaster) { @@ -29,39 +49,101 @@ public class KitchenServiceImpl implements KitchenService, KitchenServiceRuntime } @Override - public boolean makeBreakfast( EggsType eggs, Class toast, int toastDoneness ) { + public Future> makeBreakfast( EggsType eggsType, Class toastType, + int toastDoneness ) { + + // Call makeToast and use JdkFutureAdapters to convert the Future to a ListenableFuture, + // The OpendaylightToaster impl already returns a ListenableFuture so the conversion is + // actually a no-op. + + ListenableFuture> makeToastFuture = JdkFutureAdapters.listenInPoolThread( + makeToast( toastType, toastDoneness ), executor ); + + ListenableFuture> makeEggsFuture = makeEggs( eggsType ); + + // Combine the 2 ListenableFutures into 1 containing a list of RpcResults. + + ListenableFuture>> combinedFutures = + Futures.allAsList( ImmutableList.of( makeToastFuture, makeEggsFuture ) ); + + // Then transform the RpcResults into 1. + + return Futures.transform( combinedFutures, + new AsyncFunction>,RpcResult>() { + @Override + public ListenableFuture> apply( List> results ) + throws Exception { + boolean atLeastOneSucceeded = false; + Builder errorList = ImmutableList.builder(); + for( RpcResult result: results ) { + if( result.isSuccessful() ) { + atLeastOneSucceeded = true; + } + + if( result.getErrors() != null ) { + errorList.addAll( result.getErrors() ); + } + } + + return Futures.immediateFuture( + RpcResultBuilder. status( atLeastOneSucceeded ) + .withRpcErrors( errorList.build() ).build() ); + } + } ); + } + + private ListenableFuture> makeEggs( EggsType eggsType ) { + + return executor.submit( new Callable>() { + + @Override + public RpcResult call() throws Exception { + + // We don't actually do anything here - just return a successful result. + return RpcResultBuilder. success().build(); + } + } ); + } + + private Future> makeToast( Class toastType, + int toastDoneness ) { if( toasterOutOfBread ) { log.info( "We're out of toast but we can make eggs" ); - return true; + return Futures.immediateFuture( RpcResultBuilder. success() + .withWarning( ErrorType.APPLICATION, "partial-operation", + "Toaster is out of bread but we can make you eggs" ).build() ); } // Access the ToasterService to make the toast. - // We don't actually make the eggs for this example - sorry. - MakeToastInputBuilder toastInput = new MakeToastInputBuilder(); - toastInput.setToasterDoneness( (long) toastDoneness); - toastInput.setToasterToastType( toast ); - try { - RpcResult result = toaster.makeToast( toastInput.build() ).get(); + MakeToastInput toastInput = new MakeToastInputBuilder() + .setToasterDoneness( (long) toastDoneness ) + .setToasterToastType( toastType ) + .build(); + + return toaster.makeToast( toastInput ); + } + @Override + public Boolean makeScrambledWithWheat() { + try { + // This call has to block since we must return a result to the JMX client. + RpcResult result = makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ).get(); if( result.isSuccessful() ) { - log.info( "makeToast succeeded" ); + log.info( "makeBreakfast succeeded" ); } else { - log.warn( "makeToast failed: " + result.getErrors() ); + log.warn( "makeBreakfast failed: " + result.getErrors() ); } return result.isSuccessful(); + } catch( InterruptedException | ExecutionException e ) { - log.warn( "Error occurred during toast creation" ); + log.warn( "An error occurred while maing breakfast: " + e ); } - return false; - } - @Override - public Boolean makeScrambledWithWheat() { - return makeBreakfast( EggsType.SCRAMBLED, WheatBread.class, 2 ); + return Boolean.FALSE; } /**