/**
* Copyright (c) 2013 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.openflow.md.queue;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.statistics.MessageSpy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* OfHeader to DataObject implementation
*/
public class TicketProcessorFactoryImpl implements TicketProcessorFactory<OfHeader, DataObject> {
private static final Logger LOG = LoggerFactory
.getLogger(TicketProcessorFactoryImpl.class);
protected Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping;
protected MessageSpy<DataContainer> spy;
protected TicketFinisher<DataObject> ticketFinisher;
/**
* @param translatorMapping the translatorMapping to set
*/
@Override
public void setTranslatorMapping(
Map<TranslatorKey, Collection<IMDMessageTranslator<OfHeader, List<DataObject>>>> translatorMapping) {
this.translatorMapping = ImmutableMap.copyOf(translatorMapping);
}
/**
* @param spy the spy to set
*/
@Override
public void setSpy(MessageSpy<DataContainer> spy) {
this.spy = spy;
}
/**
* @param ticketFinisher the finisher to set
*/
@Override
public void setTicketFinisher(TicketFinisher<DataObject> ticketFinisher) {
this.ticketFinisher = ticketFinisher;
}
/**
* @param ticket ticket
* @return runnable ticket processor
*/
@Override
public Runnable createProcessor(final Ticket<OfHeader, DataObject> ticket) {
Runnable ticketProcessor = new Runnable() {
@Override
public void run() {
LOG.debug("message received, type: {}", ticket.getMessage().getImplementedInterface().getSimpleName());
List<DataObject> translate;
try {
translate = translate(ticket);
ticket.getResult().set(translate);
ticket.setDirectResult(translate);
// spying on result
if (spy != null) {
spy.spyIn(ticket.getMessage());
for (DataObject outMessage : translate) {
spy.spyOut(outMessage);
}
}
} catch (Exception e) {
LOG.warn("translation problem: {}", e.getMessage());
ticket.getResult().setException(e);
}
LOG.debug("message processing done (type: {}, ticket: {})",
ticket.getMessage().getImplementedInterface().getSimpleName(),
System.identityHashCode(ticket));
}
};
return ticketProcessor;
}
/**
* @param ticket ticket
* @return runnable ticket processor
*/
@Override
public Runnable createSyncProcessor(final Ticket<OfHeader, DataObject> ticket) {
Runnable ticketProcessor = new Runnable() {
@Override
public void run() {
List<DataObject> translate;
try {
translate = translate(ticket);
// spying on result
if (spy != null) {
spy.spyIn(ticket.getMessage());
for (DataObject outMessage : translate) {
spy.spyOut(outMessage);
}
}
ticketFinisher.firePopNotification(translate);
} catch (Exception e) {
LOG.error("translation problem: {}", e.getMessage());
ticket.getResult().setException(e);
}
}
};
return ticketProcessor;
}
/**
* @param ticket ticket
*
*/
@Override
public List<DataObject> translate(Ticket<OfHeader, DataObject> ticket) {
List<DataObject> result = new ArrayList<>();
OfHeader message = ticket.getMessage();
Class<? extends DataContainer> messageType = ticket.getMessage().getImplementedInterface();
ConnectionConductor conductor = ticket.getConductor();
Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> translators = null;
LOG.trace("translating ticket: {}, ticket: {}", messageType.getSimpleName(), System.identityHashCode(ticket));
Short version = message.getVersion();
if (version == null) {
throw new IllegalArgumentException("version is NULL");
}
TranslatorKey tKey = new TranslatorKey(version, messageType.getName());
translators = translatorMapping.get(tKey);
LOG.debug("translatorKey: {} + {}", version, messageType.getName());
if (translators != null) {
for (IMDMessageTranslator<OfHeader, List<DataObject>> translator : translators) {
SwitchConnectionDistinguisher cookie = null;
// Pass cookie only for PACKT_OfHeader
if (messageType.equals("PacketInMessage.class")) {
cookie = conductor.getAuxiliaryKey();
}
long start = System.nanoTime();
List<DataObject> translatorOutput = translator.translate(cookie, conductor.getSessionContext(), message);
long end = System.nanoTime();
LOG.trace("translator: {} elapsed time {} ns",translator,end-start);
if(translatorOutput != null && !translatorOutput.isEmpty()) {
result.addAll(translatorOutput);
}
}
} else {
LOG.warn("No translators for this message Type: {}", messageType);
}
return result;
}
}