/*
* 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.groupbasedpolicy.statistics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.groupbasedpolicy.api.StatisticsManager;
import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
import org.opendaylight.groupbasedpolicy.util.IidFactory;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.StatRecords;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.StatRecordsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.EpToEpStatistic;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.EpToEpStatisticBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.EpToEpStatisticKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.EpEpgToEpEpgStatistic;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.EpEpgToEpEpgStatisticBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.EpEpgToEpEpgStatisticKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.ep.epg.to.ep.epg.statistic.MatchedRuleStatistic;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.ep.epg.to.ep.epg.statistic.MatchedRuleStatisticBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.rev151215.statistic.records.stat.records.ep.to.ep.statistic.ep.epg.to.ep.epg.statistic.MatchedRuleStatisticKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.RecordId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.StatisticsStore;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.StatisticsStoreBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.dst.ep.fields.DstEndpointBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.source.ep.fields.SrcEndpointBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecord;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecordBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.StatisticRecordKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.statistic.record.Statistic;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.statistic.record.StatisticBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.statistics.store.rev151215.statistics.store.statistic.record.StatisticKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
public class StatisticsManagerImpl implements StatisticsManager, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
private static long recordKey = 0;
private DataBroker dataBroker;
public StatisticsManagerImpl(DataBroker broker) {
this.dataBroker = broker;
inicializeStatistics();
}
private void inicializeStatistics() {
InstanceIdentifier<StatisticsStore> statsIID = InstanceIdentifier.builder(StatisticsStore.class).build();
WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
LOG.debug("Initalizing statistics");
wtx.put(LogicalDatastoreType.OPERATIONAL, statsIID, new StatisticsStoreBuilder().build());
wtx.submit();
}
@Override
public boolean writeStat(StatRecords record) {
WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
for (EpToEpStatistic epStats : record.getEpToEpStatistic()) {
SrcEndpointBuilder srcBuilder = new SrcEndpointBuilder();
DstEndpointBuilder dstBuilder = new DstEndpointBuilder();
srcBuilder.setMacAddress(epStats.getSrcMacAddress())
.setL2Context(epStats.getSrcL2c())
.setTenant(epStats.getSrcTenant());
dstBuilder.setMacAddress(epStats.getDstMacAddress())
.setL2Context(epStats.getDstL2c())
.setTenant(epStats.getDstTenant());
for (EpEpgToEpEpgStatistic epgStats : epStats.getEpEpgToEpEpgStatistic()) {
StatisticRecordKey key = new StatisticRecordKey(new RecordId(recordKey++));
StatisticRecord statRecord;
srcBuilder.setEndpointGroup(epgStats.getSrcEpg());
dstBuilder.setEndpointGroup(epgStats.getDstEpg());
List<Statistic> statisticList = new ArrayList<>();
for (MatchedRuleStatistic ruleStats : epgStats.getMatchedRuleStatistic()) {
Statistic statistic = new StatisticBuilder()
.setKey(new StatisticKey(ruleStats.getContract(),
ruleStats.getMatchedRule(), ruleStats.getSubject()))
.setContract(ruleStats.getContract())
.setSubject(ruleStats.getSubject())
.setRule(ruleStats.getMatchedRule())
.setAction(ruleStats.getAction())
.setClassifier(ruleStats.getClassifier())
.setByteCount(ruleStats.getByteCount())
.setPacketCount(ruleStats.getPacketCount())
.build();
statisticList.add(statistic);
}
statRecord = new StatisticRecordBuilder().setKey(key)
.setRecordId(new RecordId(recordKey))
.setTimestamp(epStats.getTimestamp())
.setSrcEndpoint(srcBuilder.build())
.setDstEndpoint(dstBuilder.build())
.setStatistic(statisticList)
.build();
InstanceIdentifier<StatisticRecord> statIID = IidFactory.statisticRecordIid(key);
LOG.debug("Writing statistics to datastore: {}", statRecord);
wtx.put(LogicalDatastoreType.OPERATIONAL, statIID, statRecord, true);
}
}
return DataStoreHelper.submitToDs(wtx);
}
@Override
public StatRecords readStats() {
InstanceIdentifier<StatisticsStore> statsIID = InstanceIdentifier.builder(StatisticsStore.class).build();
ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction();
LOG.debug("Reading statistics");
Optional<StatisticsStore> storeOpt = Optional.absent();
try {
storeOpt = rtx.read(LogicalDatastoreType.OPERATIONAL, statsIID).get();
} catch (InterruptedException | ExecutionException e) {
LOG.error("Exception thrown on reading from Datastore: {}", e.getMessage());
return null;
}
if (storeOpt.isPresent()) {
StatisticsStore store = storeOpt.get();
Map<EpToEpStatisticKey, EpToEpStatisticBuilder> map = new HashMap<>();
for (StatisticRecord storeStat : store.getStatisticRecord()) {
MacAddress srcMac = storeStat.getSrcEndpoint().getMacAddress();
MacAddress dstMac = storeStat.getDstEndpoint().getMacAddress();
L2BridgeDomainId srcL2C = storeStat.getSrcEndpoint().getL2Context();
L2BridgeDomainId dstL2C = storeStat.getDstEndpoint().getL2Context();
TenantId srcTenant = storeStat.getSrcEndpoint().getTenant();
TenantId dstTenant = storeStat.getDstEndpoint().getTenant();
EpToEpStatisticKey epKey = new EpToEpStatisticKey(dstL2C, dstMac, srcL2C, srcMac);
EpEpgToEpEpgStatisticKey epgKey = new EpEpgToEpEpgStatisticKey(
storeStat.getDstEndpoint().getEndpointGroup(), storeStat.getSrcEndpoint().getEndpointGroup());
EpToEpStatisticBuilder epStat = map.get(epKey);
if (epStat == null) {
// eptoep combination doesnt exist
epStat = new EpToEpStatisticBuilder();
epStat.setKey(epKey)
.setSrcMacAddress(srcMac)
.setSrcL2c(srcL2C)
.setSrcTenant(storeStat.getSrcEndpoint().getTenant())
.setDstMacAddress(dstMac)
.setDstL2c(dstL2C)
.setDstTenant(storeStat.getDstEndpoint().getTenant());
}
List<MatchedRuleStatistic> ruleStatList = new ArrayList<>();
for(Statistic statistic : storeStat.getStatistic())
{
MatchedRuleStatisticBuilder statBuilder = new MatchedRuleStatisticBuilder()
.setKey(new MatchedRuleStatisticKey(statistic.getContract()
,statistic.getRule()
,statistic.getSubject()))
.setContract(statistic.getContract())
.setSubject(statistic.getSubject())
.setMatchedRule(statistic.getRule())
.setAction(statistic.getAction())
.setClassifier(statistic.getClassifier())
.setByteCount(statistic.getByteCount())
.setPacketCount(statistic.getPacketCount());
ruleStatList.add(statBuilder.build());
}
EpEpgToEpEpgStatisticBuilder epgtoepgBuilder = new EpEpgToEpEpgStatisticBuilder();
epgtoepgBuilder.setKey(epgKey)
.setSrcEpg(storeStat.getSrcEndpoint().getEndpointGroup())
.setDstEpg(storeStat.getDstEndpoint().getEndpointGroup())
.setMatchedRuleStatistic(ruleStatList);
epStat.setEpEpgToEpEpgStatistic(
addIfNotExists(epgtoepgBuilder, epStat.getEpEpgToEpEpgStatistic()));
map.put(epKey, epStat);
}
List<EpToEpStatistic> epList = new ArrayList<>();
for (EpToEpStatisticBuilder statBuilder : map.values()) {
epList.add(statBuilder.build());
}
StatRecordsBuilder statStore = new StatRecordsBuilder();
statStore.setEpToEpStatistic(epList);
return statStore.build();
}
LOG.debug("Statistics store empty");
return null;
}
private List<EpEpgToEpEpgStatistic> addIfNotExists(EpEpgToEpEpgStatisticBuilder stat,
List<EpEpgToEpEpgStatistic> list) {
if ( list == null ) {
list = new ArrayList<>();
} else {
Iterator<EpEpgToEpEpgStatistic> iterator = list.iterator();
while (iterator.hasNext()) {
EpEpgToEpEpgStatistic epgStat = iterator.next();
if (stat.getKey().equals(epgStat.getKey())) {
List<MatchedRuleStatistic> newMatches = new ArrayList<>();
Iterator<MatchedRuleStatistic> iteratorNew = stat.getMatchedRuleStatistic().iterator();
while(iteratorNew.hasNext()) {
MatchedRuleStatistic newStat = iteratorNew.next();
Iterator<MatchedRuleStatistic> iteratorOld = epgStat.getMatchedRuleStatistic().iterator();
boolean matched = false;
while(iteratorOld.hasNext()) {
MatchedRuleStatistic oldStat = iteratorOld.next();
if(oldStat.getKey().equals(newStat.getKey())) {
MatchedRuleStatistic newRuleStat = new MatchedRuleStatisticBuilder(oldStat)
.setByteCount(sumNullableValues(oldStat.getByteCount(), newStat.getByteCount()))
.setPacketCount(sumNullableValues(oldStat.getPacketCount(), newStat.getPacketCount()))
.build();
newMatches.add(newRuleStat);
matched = true;
} else {
newMatches.add(oldStat);
}
}
if (!matched) {
newMatches.add(newStat);
}
}
stat.setMatchedRuleStatistic(newMatches);
iterator.remove();
break;
}
}
}
list.add(stat.build());
return list;
}
public Long sumNullableValues (Long... x ) {
long result = 0;
for (Long num : x) {
if (num != null) {
result += num;
}
}
return result;
}
@Override
public void close() {
// TODO Auto-generated method stub
}
}