/* * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowjava.protocol.impl.core.connection; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import org.opendaylight.yangtools.yang.common.RpcError; 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 org.slf4j.LoggerFactory; /** * This class holds all the context we need for sending a single message down the tube. * A MessageHolder (used in queue) and the actual listener. It is not a thing of beauty, * but it keeps us from allocating unnecessary objects in the egress path. */ abstract class AbstractRpcListener<T> implements GenericFutureListener<Future<Void>>, ChannelOutboundQueue.MessageHolder<Object> { private static final Logger LOG = LoggerFactory.getLogger(AbstractRpcListener.class); private static final String APPLICATION_TAG = "OPENFLOW_LIBRARY"; private static final String TAG = "OPENFLOW"; private final SettableFuture<RpcResult<T>> result = SettableFuture.create(); private final String failureInfo; private Object message; /** * Create RcpError object * @param info * @param severity - error severity * @param message * @param cause - details of reason * @return */ static RpcError buildRpcError(final String info, final String message, final Throwable cause) { return RpcResultBuilder.newError(ErrorType.RPC, TAG, message, APPLICATION_TAG, info, cause); } AbstractRpcListener(final Object message, final String failureInfo) { this.failureInfo = Preconditions.checkNotNull(failureInfo); this.message = Preconditions.checkNotNull(message); } public final ListenableFuture<RpcResult<T>> getResult() { return result; } @Override public final void operationComplete(final Future<Void> future) { if (!future.isSuccess()) { LOG.debug("operation failed"); failedRpc(future.cause()); } else { LOG.debug("operation complete"); operationSuccessful(); } } @Override public final Object takeMessage() { final Object ret = message; Preconditions.checkState(ret != null, "Message has already been taken"); message = null; return ret; } @Override public final GenericFutureListener<Future<Void>> takeListener() { return this; } protected abstract void operationSuccessful(); protected final void failedRpc(final Throwable cause) { final RpcError rpcError = buildRpcError(failureInfo, "check switch connection", cause); result.set(RpcResultBuilder.<T>failed().withRpcError(rpcError).build()); } protected final void successfulRpc(final T value) { result.set(RpcResultBuilder.success(value).build()); } }