Jian Li
Committed by Gerrit Code Review

Refactor SystemInfo, and store SystemInfo into singleton instance

- Implement Bill Pugh singleton for ControlMetricsFactory and
  SystemInfo class

Change-Id: Ia97538d9f1be9ea900b0e87371bf50877eaf6483
......@@ -13,69 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cpman.impl;
package org.onosproject.cpman;
/**
* Control metrics class for storing system specification.
* System information interface.
*/
public final class ControlMetricsSystemSpec {
private int numOfCores;
private int numOfCpus;
private int cpuSpeed; // in MHz
private long totalMemory; // in bytes
private ControlMetricsSystemSpec(int numOfCores, int numOfCpus,
int cpuSpeed, long totalMemory) {
this.numOfCores = numOfCores;
this.numOfCpus = numOfCpus;
this.cpuSpeed = cpuSpeed;
this.totalMemory = totalMemory;
}
public interface SystemInfo {
/**
* Returns number of CPU cores.
*
* @return number of CPU cores
*/
public int numOfCores() {
return this.numOfCores;
}
int coreCount();
/**
* Returns number of CPUs.
*
* @return number of CPUs
*/
public int numOfCpus() {
return this.numOfCpus;
}
int cpuCount();
/**
* Returns CPU speed in MHz.
*
* @return CPU speed
*/
public int cpuSpeed() {
return this.cpuSpeed;
}
int cpuSpeed();
/**
* Returns the total amount of memory.
* Returns the total amount of memory in Mega Bytes.
*
* @return memory size
*/
public long totalMemory() {
return this.totalMemory;
}
int totalMemory();
/**
* ControlMetricsSystemSpec builder class.
* A builder of SystemInfo.
*/
public static final class Builder {
private int numOfCores;
private int numOfCpus;
private int cpuSpeed; // in MHz
private long totalMemory; // in bytes
interface Builder {
/**
* Sets number of CPU cores.
......@@ -83,50 +59,36 @@ public final class ControlMetricsSystemSpec {
* @param numOfCores number of CPU cores
* @return Builder object
*/
public Builder numOfCores(int numOfCores) {
this.numOfCores = numOfCores;
return this;
}
Builder numOfCores(int numOfCores);
/**
* Sets number of CPUs.
* @param numOfCpus number of CPUs
* @return Builder object
*/
public Builder numOfCpus(int numOfCpus) {
this.numOfCpus = numOfCpus;
return this;
}
Builder numOfCpus(int numOfCpus);
/**
* Sets CPU speed.
*
* @param cpuSpeed CPU speed
* @param cpuSpeedMhz CPU speed in Mhz
* @return Builder object
*/
public Builder cpuSpeed(int cpuSpeed) {
this.cpuSpeed = cpuSpeed;
return this;
}
Builder cpuSpeed(int cpuSpeedMhz);
/**
* Sets total amount of memory.
*
* @param totalMemory memory size
* @param totalMemoryMbytes memory size in Mega Bytes
* @return Builder object
*/
public Builder totalMemory(long totalMemory) {
this.totalMemory = totalMemory;
return this;
}
Builder totalMemory(int totalMemoryMbytes);
/**
* Builds a ControlMetricsSystemSpec object.
* Builds a SystemInfo object.
*
* @return ControlMetricsSystemSpec object
* @return SystemInfo object
*/
public ControlMetricsSystemSpec build() {
return new ControlMetricsSystemSpec(numOfCores, numOfCpus, cpuSpeed, totalMemory);
}
SystemInfo build();
}
}
......
......@@ -32,13 +32,9 @@ import java.util.concurrent.ConcurrentHashMap;
* Singleton class to provide various control plane metrics to other components.
*/
public final class ControlMetricsFactory {
private static volatile ControlMetricsFactory uniqueInstance;
private MetricsService metricsService;
private boolean enableMonitor = false;
// define a ControlMetricsSystemSpec
private ControlMetricsSystemSpec cmss;
private Boolean isInitialized = false;
// define a set of MetricsAggregators
private MetricsAggregator cpuLoad;
......@@ -68,47 +64,22 @@ public final class ControlMetricsFactory {
private Set<String> nwInterfaces = Sets.newConcurrentHashSet();
/**
* Constructs a control metrics factory using the given metrics and device services.
*
* @param metricsService metric service reference
* @param deviceService device service reference
*/
private ControlMetricsFactory(MetricsService metricsService, DeviceService deviceService) {
this.metricsService = metricsService;
registerMetrics();
deviceService.getDevices().forEach(d->deviceIds.add(d.id()));
addAllControlMessageMetrics(deviceIds);
}
/**
* Obtains the unique instance of ControlMetricsFactory.
* Initializes the control metrics factory instance using the given
* metric service and device service. Makes sure that we only initialize
* control metrics factory instance once.
*
* @param metricsService metric service
* @param deviceService device service
* @return instance of ControlMetricsFactory
*/
public static ControlMetricsFactory getInstance(MetricsService metricsService,
DeviceService deviceService) {
if (uniqueInstance == null) {
synchronized (ControlMetricsFactory.class) {
if (uniqueInstance == null) {
uniqueInstance = new ControlMetricsFactory(metricsService, deviceService);
}
}
}
return uniqueInstance;
}
/**
* Sets system specification.
*
* @param cmss ControlMetricsSystemSpec object
*/
public void setSystemSpec(ControlMetricsSystemSpec cmss) {
if (this.cmss == null) {
this.cmss = cmss;
public void initialization(MetricsService metricsService, DeviceService deviceService) {
synchronized (isInitialized) {
if (!isInitialized) {
this.metricsService = metricsService;
registerMetrics();
deviceService.getDevices().forEach(d->deviceIds.add(d.id()));
addAllControlMessageMetrics(deviceIds);
isInitialized = true;
}
}
}
......@@ -119,17 +90,17 @@ public final class ControlMetricsFactory {
*/
public void addControlMessageMetricsByDeviceId(DeviceId deviceId) {
MetricsAggregator inbound = new MetricsAggregator(metricsService,
ControlMetricType.INBOUND_PACKET, Optional.of(deviceId));
ControlMetricType.INBOUND_PACKET, Optional.of(deviceId));
MetricsAggregator outbound = new MetricsAggregator(metricsService,
ControlMetricType.OUTBOUND_PACKET, Optional.of(deviceId));
ControlMetricType.OUTBOUND_PACKET, Optional.of(deviceId));
MetricsAggregator flowmod = new MetricsAggregator(metricsService,
ControlMetricType.FLOW_MOD_PACKET, Optional.of(deviceId));
ControlMetricType.FLOW_MOD_PACKET, Optional.of(deviceId));
MetricsAggregator flowrmv = new MetricsAggregator(metricsService,
ControlMetricType.FLOW_REMOVED_PACKET, Optional.of(deviceId));
ControlMetricType.FLOW_REMOVED_PACKET, Optional.of(deviceId));
MetricsAggregator request = new MetricsAggregator(metricsService,
ControlMetricType.REQUEST_PACKET, Optional.of(deviceId));
ControlMetricType.REQUEST_PACKET, Optional.of(deviceId));
MetricsAggregator reply = new MetricsAggregator(metricsService,
ControlMetricType.REPLY_PACKET, Optional.of(deviceId));
ControlMetricType.REPLY_PACKET, Optional.of(deviceId));
inboundPacket.putIfAbsent(deviceId, inbound);
outboundPacket.putIfAbsent(deviceId, outbound);
......@@ -148,7 +119,7 @@ public final class ControlMetricsFactory {
*/
public void addDiskMetricsByPartition(String partitionName) {
MetricsAggregator readBytes = new MetricsAggregator(metricsService,
ControlMetricType.DISK_READ_BYTES, partitionName);
ControlMetricType.DISK_READ_BYTES, partitionName);
MetricsAggregator writeBytes = new MetricsAggregator(metricsService,
ControlMetricType.DISK_WRITE_BYTES, partitionName);
......@@ -165,7 +136,7 @@ public final class ControlMetricsFactory {
*/
public void addNetworkMetricsByInterface(String interfaceName) {
MetricsAggregator incomingBytes = new MetricsAggregator(metricsService,
ControlMetricType.NW_INCOMING_BYTES, interfaceName);
ControlMetricType.NW_INCOMING_BYTES, interfaceName);
MetricsAggregator outgoingBytes = new MetricsAggregator(metricsService,
ControlMetricType.NW_OUTGOING_BYTES, interfaceName);
MetricsAggregator incomingPackets = new MetricsAggregator(metricsService,
......@@ -579,4 +550,17 @@ public final class ControlMetricsFactory {
public MetricsAggregator replyPacket(DeviceId deviceId) {
return replyPacket.get(deviceId);
}
/**
* Returns an instance of control metrics factory.
*
* @return instance of control metrics factory
*/
public static ControlMetricsFactory getInstance() {
return SingletonHelper.INSTANCE;
}
private static class SingletonHelper {
private static final ControlMetricsFactory INSTANCE = new ControlMetricsFactory();
}
}
\ No newline at end of file
......
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cpman.impl;
import org.onosproject.cpman.SystemInfo;
/**
* Implementation class of storing system specification.
*/
public final class DefaultSystemInfo implements SystemInfo {
private int numOfCores;
private int numOfCpus;
private int cpuSpeedMhz;
private int totalMemoryMbytes;
private DefaultSystemInfo(int numOfCores, int numOfCpus,
int cpuSpeedMhz, int totalMemoryMbytes) {
this.numOfCores = numOfCores;
this.numOfCpus = numOfCpus;
this.cpuSpeedMhz = cpuSpeedMhz;
this.totalMemoryMbytes = totalMemoryMbytes;
}
@Override
public int coreCount() {
return this.numOfCores;
}
@Override
public int cpuCount() {
return this.numOfCpus;
}
@Override
public int cpuSpeed() {
return this.cpuSpeedMhz;
}
@Override
public int totalMemory() {
return this.totalMemoryMbytes;
}
/**
* ControlMetricsSystemSpec builder class.
*/
public static final class Builder implements SystemInfo.Builder {
private int numOfCores;
private int numOfCpus;
private int cpuSpeedMHz;
private int totalMemoryBytes;
@Override
public SystemInfo.Builder numOfCores(int numOfCores) {
this.numOfCores = numOfCores;
return this;
}
@Override
public Builder numOfCpus(int numOfCpus) {
this.numOfCpus = numOfCpus;
return this;
}
@Override
public Builder cpuSpeed(int cpuSpeedMhz) {
this.cpuSpeedMHz = cpuSpeedMhz;
return this;
}
@Override
public Builder totalMemory(int totalMemoryBytes) {
this.totalMemoryBytes = totalMemoryBytes;
return this;
}
@Override
public DefaultSystemInfo build() {
return new DefaultSystemInfo(numOfCores, numOfCpus, cpuSpeedMHz, totalMemoryBytes);
}
}
}
/*
* Copyright 2016 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cpman.impl;
import org.onosproject.cpman.SystemInfo;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
/**
* A factory class which instantiates a system info object.
*/
public final class SystemInfoFactory {
private final Logger log = getLogger(getClass());
private SystemInfo systemInfo;
// non-instantiable (except for our Singleton)
private SystemInfoFactory() {
}
/**
* Returns system information.
*
* @return reference object of system info
*/
public SystemInfo getSystemInfo() {
synchronized (systemInfo) {
return this.systemInfo;
}
}
/**
* Set system information only if it is empty.
*
* @param systemInfo reference object of system info
*/
public void setSystemInfo(SystemInfo systemInfo) {
synchronized (systemInfo) {
if (this.systemInfo == null) {
this.systemInfo = systemInfo;
} else {
log.warn("System information has already been set");
}
}
}
/**
* Returns an instance of system info factory.
*
* @return instance of system info factory
*/
public static SystemInfoFactory getInstance() {
return SingletonHelper.INSTANCE;
}
private static class SingletonHelper {
private static final SystemInfoFactory INSTANCE = new SystemInfoFactory();
}
}
......@@ -22,7 +22,9 @@ import org.onosproject.cpman.ControlMetric;
import org.onosproject.cpman.ControlMetricType;
import org.onosproject.cpman.ControlPlaneMonitorService;
import org.onosproject.cpman.MetricValue;
import org.onosproject.cpman.impl.ControlMetricsSystemSpec;
import org.onosproject.cpman.SystemInfo;
import org.onosproject.cpman.impl.DefaultSystemInfo;
import org.onosproject.cpman.impl.SystemInfoFactory;
import org.onosproject.rest.AbstractWebResource;
import javax.ws.rs.Consumes;
......@@ -227,19 +229,19 @@ public class ControlMetricsCollectorWebResource extends AbstractWebResource {
}
/**
* Collects system specifications.
* The system specs include the various control metrics
* Collects system information.
* The system information includes the various control metrics
* which do not require aggregation.
*
* @param stream JSON stream
* @return 200 OK
* @onos.rsModel SystemSpecsPost
* @onos.rsModel SystemInfoPost
*/
@POST
@Path("system_specs")
@Path("system_info")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response systemSpecs(InputStream stream) {
public Response systemInfo(InputStream stream) {
ObjectNode root = mapper().createObjectNode();
try {
......@@ -249,15 +251,17 @@ public class ControlMetricsCollectorWebResource extends AbstractWebResource {
JsonNode cpuSpeed = jsonTree.get("cpuSpeed");
JsonNode totalMemory = jsonTree.get("totalMemory");
if (numOfCores != null && numOfCpus != null && cpuSpeed != null && totalMemory != null) {
ControlMetricsSystemSpec.Builder builder = new ControlMetricsSystemSpec.Builder();
ControlMetricsSystemSpec cmss = builder.numOfCores(numOfCores.asInt())
if (numOfCores != null && numOfCpus != null &&
cpuSpeed != null && totalMemory != null) {
SystemInfo systemInfo = new DefaultSystemInfo.Builder()
.numOfCores(numOfCores.asInt())
.numOfCpus(numOfCpus.asInt())
.cpuSpeed(cpuSpeed.asInt())
.totalMemory(totalMemory.asLong())
.totalMemory(totalMemory.asInt())
.build();
// TODO: need to implement spec store
// try to store the system info.
SystemInfoFactory.getInstance().setSystemInfo(systemInfo);
} else {
throw new IllegalArgumentException(INVALID_SYSTEM_SPECS);
}
......
......@@ -27,6 +27,8 @@ import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
import org.onosproject.cpman.ControlPlaneMonitorService;
import org.onosproject.cpman.SystemInfo;
import org.onosproject.cpman.impl.SystemInfoFactory;
import org.onosproject.net.DeviceId;
import javax.ws.rs.core.MediaType;
......@@ -123,8 +125,14 @@ public class ControlMetricsCollectorResourceTest extends JerseyTest {
}
@Test
public void testSystemSpecsPost() {
basePostTest("system-spec-post.json", PREFIX + "/system_specs");
public void testSystemInfoPost() {
basePostTest("system-info-post.json", PREFIX + "/system_info");
SystemInfo si = SystemInfoFactory.getInstance().getSystemInfo();
assertThat(si.cpuSpeed(), is(2048));
assertThat(si.coreCount(), is(6));
assertThat(si.cpuCount(), is(2));
assertThat(si.totalMemory(), is(4096));
}
private ClientResponse baseTest(String jsonFile, String path) {
......