/*
* 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.applications.frm.impl;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.Futures;
import java.util.Collections;
import java.util.concurrent.Future;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
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.table.service.rev131026.UpdateTableInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.OriginalTableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.table.update.UpdatedTableBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TableForwarder extends AbstractListeningCommiter<TableFeatures> {
private static final Logger LOG = LoggerFactory.getLogger(TableForwarder.class);
private ListenerRegistration<TableForwarder> listenerRegistration;
public TableForwarder(final ForwardingRulesManager manager, final DataBroker db) {
super(manager, TableFeatures.class);
Preconditions.checkNotNull(db, "DataBroker can not be null!");
final DataTreeIdentifier<TableFeatures> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath());
try {
SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(ForwardingRulesManagerImpl.STARTUP_LOOP_TICK,
ForwardingRulesManagerImpl.STARTUP_LOOP_MAX_RETRIES);
listenerRegistration = looper.loopUntilNoException(() -> db.registerDataTreeChangeListener(treeId, TableForwarder.this));
} catch (final Exception e) {
LOG.warn("FRM Table DataTreeChangeListener registration fail!");
LOG.debug("FRM Table DataTreeChangeListener registration fail ..", e);
throw new IllegalStateException("TableForwarder startup fail! System needs restart.", e);
}
}
@Override
public void close() {
if (listenerRegistration != null) {
try {
listenerRegistration.close();
} catch (Exception e) {
LOG.warn("Error by stop FRM TableChangeListener: {}", e.getMessage());
LOG.debug("Error by stop FRM TableChangeListener..", e);
}
listenerRegistration = null;
}
}
@Override
protected InstanceIdentifier<TableFeatures> getWildCardPath() {
return InstanceIdentifier.create(Nodes.class).child(Node.class)
.augmentation(FlowCapableNode.class).child(TableFeatures.class);
}
@Override
public void remove(final InstanceIdentifier<TableFeatures> identifier, final TableFeatures removeDataObj,
final InstanceIdentifier<FlowCapableNode> nodeIdent) {
// DO Nothing
}
@Override
public void update(final InstanceIdentifier<TableFeatures> identifier,
final TableFeatures original, final TableFeatures update,
final InstanceIdentifier<FlowCapableNode> nodeIdent) {
LOG.debug("Received the Table Update request [Tbl id, node Id, original, upd" +
" " + identifier + " " + nodeIdent + " " + original + " " + update);
final TableFeatures originalTableFeatures = original;
TableFeatures updatedTableFeatures;
if (null == update) {
updatedTableFeatures = original;
}
else {
updatedTableFeatures = update;
}
final UpdateTableInputBuilder builder = new UpdateTableInputBuilder();
builder.setNode(new NodeRef(nodeIdent.firstIdentifierOf(Node.class)));
// TODO: reconsider model - this particular field is not used in service implementation
builder.setTableRef(new TableRef(identifier));
builder.setTransactionUri(new Uri(provider.getNewTransactionId()));
builder.setUpdatedTable(new UpdatedTableBuilder().setTableFeatures(
Collections.singletonList(updatedTableFeatures)).build());
builder.setOriginalTable(new OriginalTableBuilder().setTableFeatures(
Collections.singletonList(originalTableFeatures)).build());
LOG.debug("Invoking SalTableService ");
if (this.provider.getSalTableService() != null)
LOG.debug(" Handle to SalTableServices" + this.provider.getSalTableService());
this.provider.getSalTableService().updateTable(builder.build());
}
@Override
public Future<? extends RpcResult<?>> add(
final InstanceIdentifier<TableFeatures> identifier,
final TableFeatures addDataObj,
final InstanceIdentifier<FlowCapableNode> nodeIdent) {
return Futures.immediateFuture(null);
}
@Override
public void createStaleMarkEntity(InstanceIdentifier<TableFeatures> identifier, TableFeatures del,
InstanceIdentifier<FlowCapableNode> nodeIdent) {
LOG.debug("NO-OP");
}
@Override
public Future<? extends RpcResult<?>> removeWithResult(InstanceIdentifier<TableFeatures> identifier,
TableFeatures del, InstanceIdentifier<FlowCapableNode> nodeIdent) {
return null;
}
}