/* * Copyright (c) 2015 Cisco Systems, Inc. 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.openflowplugin.impl.services; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; import org.opendaylight.openflowplugin.api.openflow.device.TxFacade; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy; import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider; import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.EventsTimeCounter; import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractMultipartRequestOnTheFlyCallback<T extends OfHeader> extends AbstractMultipartRequestCallback<T> { private static final Logger LOG = LoggerFactory.getLogger(AbstractMultipartRequestOnTheFlyCallback.class); private final DeviceInfo deviceInfo; private boolean finished = false; private final EventIdentifier doneEventIdentifier; private final TxFacade txFacade; private final MultipartWriterProvider statisticsWriterProvider; public AbstractMultipartRequestOnTheFlyCallback(final RequestContext<List<T>> context, Class<?> requestType, final DeviceContext deviceContext, final EventIdentifier eventIdentifier, final MultipartWriterProvider statisticsWriterProvider) { super(context, requestType, deviceContext, eventIdentifier); deviceInfo = deviceContext.getDeviceInfo(); doneEventIdentifier = new EventIdentifier(getMultipartType().name(), deviceContext.getDeviceInfo().getNodeId().toString()); txFacade = deviceContext; this.statisticsWriterProvider = statisticsWriterProvider; } @Override @SuppressWarnings("unchecked") public void onSuccess(final OfHeader result) { if (Objects.isNull(result)) { LOG.info("OfHeader was null."); if (!finished) { endCollecting(); return; } } else if (finished) { LOG.debug("Unexpected multipart response received: xid={}, {}", result.getXid(), result.getImplementedInterface()); return; } if (!isMultipart(result)) { LOG.info("Unexpected response type received {}.", result.getClass()); setResult(RpcResultBuilder.<List<T>>failed().withError(RpcError.ErrorType.APPLICATION, String.format("Unexpected response type received %s.", result.getClass())).build()); endCollecting(); } else { final T resultCast = (T) result; Futures.transform(processStatistics(resultCast), (Function<Optional<? extends MultipartReplyBody>, Void>) input -> { Optional.ofNullable(input).flatMap(i -> i).ifPresent(reply -> { try { statisticsWriterProvider .lookup(getMultipartType()) .ifPresent(writer -> writer.write(reply, false)); } catch (final Exception ex) { LOG.warn("Stats processing of type {} for node {} failed during write-to-tx step", getMultipartType(), deviceInfo.getLOGValue(), ex); } }); if (!isReqMore(resultCast)) { endCollecting(); onFinishedCollecting(); } return null; }); } } /** * Get tx facade * @return tx facade */ protected TxFacade getTxFacade() { return txFacade; } /** * Ends collecting of multipart data */ private void endCollecting() { EventsTimeCounter.markEnd(doneEventIdentifier); EventsTimeCounter.markEnd(getEventIdentifier()); spyMessage(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_TRANSLATE_OUT_SUCCESS); txFacade.submitTransaction(); setResult(RpcResultBuilder.success(Collections.<T>emptyList()).build()); finished = true; } /** * Process statistics. * * @param result result */ protected abstract ListenableFuture<Optional<? extends MultipartReplyBody>> processStatistics(final T result); /** * Get multipart type * @return multipart type */ protected abstract MultipartType getMultipartType(); /** * On finished collection event */ protected abstract void onFinishedCollecting(); }