blob: 989d2c1c1b2cd5f1ad2d26cf83e4db3815891a07 [file] [log] [blame]
package net.onrc.onos.core.registry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.restserver.IRestApiService;
import net.onrc.onos.core.registry.web.RegistryWebRoutable;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of a registry that doesn't rely on any external registry
* service. This is designed to be used only in single-node setups (e.g. for
* development). All registry data is stored in local memory.
*
* @author jono
*/
public class StandaloneRegistry implements IFloodlightModule,
IControllerRegistryService {
private static final Logger log = LoggerFactory.getLogger(StandaloneRegistry.class);
protected IRestApiService restApi;
protected String registeredControllerId = null;
protected Map<String, ControlChangeCallback> switchCallbacks;
//
// Unique ID generation state
//
private static AtomicLong nextUniqueId = new AtomicLong(0);
@Override
public void requestControl(long dpid, ControlChangeCallback cb)
throws RegistryException {
if (registeredControllerId == null) {
throw new RuntimeException(
"Must register a controller before calling requestControl");
}
switchCallbacks.put(HexString.toHexString(dpid), cb);
log.debug("Control granted for {}", HexString.toHexString(dpid));
//Immediately grant request for control
if (cb != null) {
cb.controlChanged(dpid, true);
}
}
@Override
public void releaseControl(long dpid) {
ControlChangeCallback cb = switchCallbacks.remove(HexString.toHexString(dpid));
log.debug("Control released for {}", HexString.toHexString(dpid));
if (cb != null) {
cb.controlChanged(dpid, false);
}
}
@Override
public boolean hasControl(long dpid) {
return switchCallbacks.containsKey(HexString.toHexString(dpid));
}
@Override
public boolean isClusterLeader() {
return true;
}
@Override
public String getControllerId() {
return registeredControllerId;
}
@Override
public void registerController(String controllerId)
throws RegistryException {
if (registeredControllerId != null) {
throw new RegistryException(
"Controller already registered with id " + registeredControllerId);
}
registeredControllerId = controllerId;
}
@Override
public Collection<String> getAllControllers() throws RegistryException {
List<String> l = new ArrayList<String>();
l.add(registeredControllerId);
return l;
}
@Override
public String getControllerForSwitch(long dpid) throws RegistryException {
return (switchCallbacks.get(HexString.toHexString(dpid)) != null) ? registeredControllerId : null;
}
@Override
public Map<String, List<ControllerRegistryEntry>> getAllSwitches() {
Map<String, List<ControllerRegistryEntry>> switches =
new HashMap<String, List<ControllerRegistryEntry>>();
for (String strSwitch : switchCallbacks.keySet()) {
log.debug("Switch _{}", strSwitch);
List<ControllerRegistryEntry> list = new ArrayList<ControllerRegistryEntry>();
list.add(new ControllerRegistryEntry(registeredControllerId, 0));
switches.put(strSwitch, list);
}
return switches;
}
@Override
public Collection<Long> getSwitchesControlledByController(
String controllerId) {
throw new RuntimeException("Not yet implemented");
}
private long blockTop = 0L;
private static final long BLOCK_SIZE = 0x1000000L;
/**
* Returns a block of IDs which are unique and unused.
* Range of IDs is fixed size and is assigned incrementally as this method called.
*/
@Override
public synchronized IdBlock allocateUniqueIdBlock() {
long blockHead = blockTop;
long blockTail = blockTop + BLOCK_SIZE;
IdBlock block = new IdBlock(blockHead, blockTail - 1, BLOCK_SIZE);
blockTop = blockTail;
return block;
}
/**
* Get a globally unique ID.
*
* @return a globally unique ID.
*/
@Override
public long getNextUniqueId() {
return nextUniqueId.incrementAndGet();
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IControllerRegistryService.class);
return l;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Map<Class<? extends IFloodlightService>, IFloodlightService> m =
new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
m.put(IControllerRegistryService.class, this);
return m;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IFloodlightProviderService.class);
l.add(IRestApiService.class);
return l;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
restApi = context.getServiceImpl(IRestApiService.class);
switchCallbacks = new HashMap<String, ControlChangeCallback>();
}
@Override
public void startUp(FloodlightModuleContext context) {
restApi.addRestletRoutable(new RegistryWebRoutable());
}
@Override
public IdBlock allocateUniqueIdBlock(long range) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}