Skip to content
Snippets Groups Projects
Commit e7bd453f authored by Saurav Das's avatar Saurav Das
Browse files

Implementing the rest of the debugCounters API

parent c7164bad
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.List;
......@@ -39,7 +40,7 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService {
/**
* Global debug-counter storage across all threads. These are
* updated from the local per thread counters by the update FIXME method.
* updated from the local per thread counters by the flush counters method.
*/
protected ConcurrentHashMap<String, AtomicLong> debugCounters =
new ConcurrentHashMap<String, AtomicLong>();
......@@ -82,11 +83,22 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService {
new ConcurrentHashMap<String, List<CounterInfo>>();
/**
* fast cache for counter names that are currently active
* fast global cache for counter names that are currently active
*/
Set<String> currentCounters = Collections.newSetFromMap(
new ConcurrentHashMap<String,Boolean>());
/**
* Thread local cache for counter names that are currently active.
*/
protected final ThreadLocal<Set<String>> threadlocalCurrentCounters =
new ThreadLocal<Set<String>>() {
@Override
protected Set<String> initialValue() {
return new HashSet<String>();
}
};
//*******************************
// IDebugCounterService
//*******************************
......@@ -118,31 +130,27 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService {
a.add(new CounterInfo(moduleCounterName, counterDescription, counterType));
// create counter in global map
debugCounters.put(moduleCounterName, new AtomicLong());
// create counter in local thread map
Map<String, MutableLong> thismap = this.threadlocalCounters.get();
MutableLong ml = thismap.get(moduleCounterName);
if (ml == null) {
thismap.put(moduleCounterName, new MutableLong());
}
// finally add to cache if it is meant to be always counted
// and add to counter name cache if it is meant to be always counted
if (counterType == CounterType.ALWAYS_COUNT) {
currentCounters.add(moduleCounterName);
debugCounters.put(moduleCounterName, new AtomicLong());
}
return true;
}
@Override
public void updateCounter(String moduleCounterName) {
if (currentCounters.contains(moduleCounterName)) {
Map<String, MutableLong> thismap = this.threadlocalCounters.get();
MutableLong ml = thismap.get(moduleCounterName);
if (ml == null) {
Map<String, MutableLong> thismap = this.threadlocalCounters.get();
MutableLong ml = thismap.get(moduleCounterName);
if (ml == null) {
// check locally to see if this counter should be created or not
Set<String> thisset = this.threadlocalCurrentCounters.get();
if (thisset.contains(moduleCounterName)) {
ml = new MutableLong();
ml.increment();
thismap.put(moduleCounterName, ml);
}
} else {
ml.increment();
}
}
......@@ -154,58 +162,143 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService {
MutableLong curval = thismap.get(key);
long delta = curval.get();
if (delta > 0) {
debugCounters.get(key).addAndGet(delta);
curval.set(0);
AtomicLong ctr = debugCounters.get(key);
if (ctr == null) {
// The global counter does not exist possibly because it has been
// disabled. It should thus be removed from the thread-local
// map (the counter) and set (the counter name). Removing it
// from the threadlocal set ensures that the counter will not be
// recreated (see updateCounter)
Set<String> thisset = this.threadlocalCurrentCounters.get();
thisset.remove(key);
thismap.remove(key);
} else {
ctr.addAndGet(delta);
curval.set(0);
}
}
}
// At this point it is also possible that the threadlocal map/set does not
// include a counter that has been enabled and is present in the global
// current counter store. If so we need to sync such state so that the
// thread local counter can be created (in the updateCounter method)
Set<String> thisset = this.threadlocalCurrentCounters.get();
if (thisset.size() != currentCounters.size()) {
thisset.addAll(currentCounters);
}
//printAllCounters();
}
@Override
public void resetCounter(String moduleCounterName) {
// TODO Auto-generated method stub
if (debugCounters.containsKey(moduleCounterName)) {
debugCounters.get(moduleCounterName).set(0);
}
}
@Override
public void resetAllCounters() {
// TODO Auto-generated method stub
for (AtomicLong v : debugCounters.values()) {
v.set(0);
}
}
@Override
public void resetAllModuleCounters(String moduleName) {
// TODO Auto-generated method stub
List<CounterInfo> cil = moduleCounters.get(moduleName);
if (cil != null) {
for (CounterInfo ci : cil) {
if (debugCounters.containsKey(ci.moduleCounterName)) {
debugCounters.get(ci.moduleCounterName).set(0);
}
}
} else {
if (log.isDebugEnabled())
log.debug("No module found with name {}", moduleName);
}
}
@Override
public void enableCtrOnDemand(String moduleCounterName) {
// TODO Auto-generated method stub
currentCounters.add(moduleCounterName);
debugCounters.putIfAbsent(moduleCounterName, new AtomicLong());
}
@Override
public void disableCtrOnDemand(String moduleCounterName) {
// TODO Auto-generated method stub
String[] temp = moduleCounterName.split("-");
if (temp.length < 2) {
log.error("moduleCounterName {} not recognized", moduleCounterName);
return;
}
String moduleName = temp[0];
List<CounterInfo> cil = moduleCounters.get(moduleName);
for (CounterInfo ci : cil) {
if (ci.moduleCounterName.equals(moduleCounterName) &&
ci.ctype == CounterType.COUNT_ON_DEMAND) {
currentCounters.remove(moduleCounterName);
debugCounters.remove(moduleCounterName);
return;
}
}
}
@Override
public DebugCounterInfo getCounterValue(String moduleCounterName) {
// TODO Auto-generated method stub
if (!debugCounters.containsKey(moduleCounterName)) return null;
long counterValue = debugCounters.get(moduleCounterName).longValue();
String[] temp = moduleCounterName.split("-");
if (temp.length < 2) {
log.error("moduleCounterName {} not recognized", moduleCounterName);
return null;
}
String moduleName = temp[0];
List<CounterInfo> cil = moduleCounters.get(moduleName);
for (CounterInfo ci : cil) {
if (ci.moduleCounterName.equals(moduleCounterName)) {
DebugCounterInfo dci = new DebugCounterInfo();
dci.counterinfo = ci;
dci.counterValue = counterValue;
return dci;
}
}
return null;
}
@Override
public List<DebugCounterInfo> getAllCounterValues() {
// TODO Auto-generated method stub
return null;
List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
for (List<CounterInfo> cil : moduleCounters.values()) {
for (CounterInfo ci : cil) {
AtomicLong ctr = debugCounters.get(ci.moduleCounterName);
if (ctr != null) {
DebugCounterInfo dci = new DebugCounterInfo();
dci.counterinfo = ci;
dci.counterValue = ctr.longValue();
dcilist.add(dci);
}
}
}
return dcilist;
}
@Override
public List<DebugCounterInfo> getModuleCounterValues() {
// TODO Auto-generated method stub
return null;
public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
if (moduleCounters.containsKey(moduleName)) {
List<CounterInfo> cil = moduleCounters.get(moduleName);
for (CounterInfo ci : cil) {
AtomicLong ctr = debugCounters.get(ci.moduleCounterName);
if (ctr != null) {
DebugCounterInfo dci = new DebugCounterInfo();
dci.counterinfo = ci;
dci.counterValue = ctr.longValue();
dcilist.add(dci);
}
}
}
return dcilist;
}
......@@ -246,19 +339,17 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService {
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init(FloodlightModuleContext context) throws FloodlightModuleException {
// TODO Auto-generated method stub
}
@Override
public void startUp(FloodlightModuleContext context) {
// TODO Auto-generated method stub
}
}
......@@ -7,7 +7,8 @@ import java.util.List;
public interface IDebugCounterService extends IFloodlightService {
/**
* Different counter types.
* Different counter types. Counters that are meant to be counted on demand
* need to be separately enabled/disabled.
*/
public enum CounterType {
ALWAYS_COUNT,
......@@ -28,6 +29,7 @@ public interface IDebugCounterService extends IFloodlightService {
* @param moduleCounterName the counter name which MUST be have the following
* syntax: <module name>-<counter name>
* eg.: linkdiscovery-incoming
* There should be only a single '-' in the name
* @param counterDescription a descriptive string that gives more information
* of what the counter is measuring. For example,
* "Measures the number of incoming packets seen by
......@@ -43,34 +45,85 @@ public interface IDebugCounterService extends IFloodlightService {
CounterType counterType);
/**
* Increments the counter by 1.
* Increments the counter by 1, if the counter is meant to be always counted,
* or if the counter has been enabled for counting.
* @param moduleCounterName the registered counter name.
*/
public void updateCounter(String moduleCounterName);
/**
* Update the global counter map with values from the thread local maps
* Update the global counter map with values from the thread local maps. This
* method is not intended for use by any module. It's typical usage is from
* floodlight core. As far as the modules are concerned, this should happen
* automatically for their counters.
*/
public void flushCounters();
/**
*
* @param moduleCounterName
* Resets the value of the counter to zero if it is currently enabled. Note
* that with live traffic, it is not necessary that the counter will display
* zero with a get call as it may get updated between the reset and get calls.
* @param moduleCounterName the registered counter name.
*/
public void resetCounter(String moduleCounterName);
/**
* Resets the values of all counters that are currently enabled to zero.
*/
public void resetAllCounters();
/**
* Resets the values of all counters that are currently active and belong
* to a module with the given 'moduleName'. The moduleName MUST be the
* part of the moduleCounterName with which the counters were registered.
* eg. if 'linkdiscovery-incoming' and 'linkdiscovery-lldpeol' are two counters
* the module name is 'linkdiscovery'
* @param moduleName
*/
public void resetAllModuleCounters(String moduleName);
/**
* This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
* enable counting on the counter. Note that this step is necessary to start
* counting for these counter types - merely registering the counter is not
* enough (as is the case for CounterType.ALWAYS_COUNT). Note that newly
* enabled counter starts from an initial value of zero.
*
* @param moduleCounterName the registered counter name.
*/
public void enableCtrOnDemand(String moduleCounterName);
/**
* This method applies only to CounterType.ALWAYS_COUNT. It is used to disable
* counting on this counter. Note that disabling a counter results in a loss
* of the counter value. When re-enabled the counter will restart from zero.
*
* @param moduleCounterName the registered counter name.
*/
public void disableCtrOnDemand(String moduleCounterName);
/**
* Get counter value and associated information for a specific counter
*
* @param moduleCounterName
* @return DebugCounterInfo or null if the counter could not be found
*/
public DebugCounterInfo getCounterValue(String moduleCounterName);
/**
* Get counter values and associated information for all counters
*
* @return the list of values/info or an empty list
*/
public List<DebugCounterInfo> getAllCounterValues();
public List<DebugCounterInfo> getModuleCounterValues();
/**
* Get counter values and associated information for all counters associated
* with a module.
*
* @param moduleName
* @return the list of values/info or an empty list
*/
public List<DebugCounterInfo> getModuleCounterValues(String moduleName);
}
......@@ -15,28 +15,24 @@ public class NullDebugCounter implements IFloodlightModule, IDebugCounterService
public boolean registerCounter(String moduleCounterName,
String counterDescription,
CounterType counterType) {
// TODO Auto-generated method stub
return false;
}
@Override
public Collection<Class<? extends IFloodlightService>>
getModuleServices() {
// TODO Auto-generated method stub
return null;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService>
getServiceImpls() {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<Class<? extends IFloodlightService>>
getModuleDependencies() {
// TODO Auto-generated method stub
return null;
}
......@@ -45,73 +41,61 @@ public class NullDebugCounter implements IFloodlightModule, IDebugCounterService
void
init(FloodlightModuleContext context)
throws FloodlightModuleException {
// TODO Auto-generated method stub
}
@Override
public void startUp(FloodlightModuleContext context) {
// TODO Auto-generated method stub
}
@Override
public void updateCounter(String moduleCounterName) {
// TODO Auto-generated method stub
}
@Override
public void flushCounters() {
// TODO Auto-generated method stub
}
@Override
public void resetCounter(String moduleCounterName) {
// TODO Auto-generated method stub
}
@Override
public void resetAllCounters() {
// TODO Auto-generated method stub
}
@Override
public void resetAllModuleCounters(String moduleName) {
// TODO Auto-generated method stub
}
@Override
public void enableCtrOnDemand(String moduleCounterName) {
// TODO Auto-generated method stub
}
@Override
public void disableCtrOnDemand(String moduleCounterName) {
// TODO Auto-generated method stub
}
@Override
public DebugCounterInfo getCounterValue(String moduleCounterName) {
// TODO Auto-generated method stub
return null;
}
@Override
public List<DebugCounterInfo> getAllCounterValues() {
// TODO Auto-generated method stub
return null;
}
@Override
public List<DebugCounterInfo> getModuleCounterValues() {
// TODO Auto-generated method stub
public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
return null;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment