From 1a42469471d2c0b25bf02341a2fb85f8e2324a4c Mon Sep 17 00:00:00 2001 From: Jian Li Date: Wed, 3 Feb 2016 16:21:18 -0800 Subject: [PATCH] Refactor SystemInfo, and store SystemInfo into singleton instance - Implement Bill Pugh singleton for ControlMetricsFactory and SystemInfo class Change-Id: Ia97538d9f1be9ea900b0e87371bf50877eaf6483 --- .../org/onosproject/cpman/SystemInfo.java | 94 +++++++++++++ .../cpman/impl/ControlMetricsFactory.java | 82 +++++------ .../cpman/impl/ControlMetricsSystemSpec.java | 132 ------------------ .../cpman/impl/DefaultSystemInfo.java | 95 +++++++++++++ .../cpman/impl/SystemInfoFactory.java | 74 ++++++++++ .../ControlMetricsCollectorWebResource.java | 26 ++-- ...stemSpecsPost.json => SystemInfoPost.json} | 0 .../ControlMetricsCollectorResourceTest.java | 12 +- ...m-spec-post.json => system-info-post.json} | 0 9 files changed, 321 insertions(+), 194 deletions(-) create mode 100644 apps/cpman/api/src/main/java/org/onosproject/cpman/SystemInfo.java delete mode 100644 apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsSystemSpec.java create mode 100644 apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultSystemInfo.java create mode 100644 apps/cpman/app/src/main/java/org/onosproject/cpman/impl/SystemInfoFactory.java rename apps/cpman/app/src/main/resources/definitions/{SystemSpecsPost.json => SystemInfoPost.json} (100%) rename apps/cpman/app/src/test/resources/org/onosproject/cpman/rest/{system-spec-post.json => system-info-post.json} (100%) diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/SystemInfo.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/SystemInfo.java new file mode 100644 index 0000000000..d8820f38ca --- /dev/null +++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/SystemInfo.java @@ -0,0 +1,94 @@ +/* + * 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; + +/** + * System information interface. + */ +public interface SystemInfo { + + /** + * Returns number of CPU cores. + * + * @return number of CPU cores + */ + int coreCount(); + + /** + * Returns number of CPUs. + * + * @return number of CPUs + */ + int cpuCount(); + + /** + * Returns CPU speed in MHz. + * + * @return CPU speed + */ + int cpuSpeed(); + + /** + * Returns the total amount of memory in Mega Bytes. + * + * @return memory size + */ + int totalMemory(); + + /** + * A builder of SystemInfo. + */ + interface Builder { + + /** + * Sets number of CPU cores. + * + * @param numOfCores number of CPU cores + * @return Builder object + */ + Builder numOfCores(int numOfCores); + + /** + * Sets number of CPUs. + * @param numOfCpus number of CPUs + * @return Builder object + */ + Builder numOfCpus(int numOfCpus); + + /** + * Sets CPU speed. + * + * @param cpuSpeedMhz CPU speed in Mhz + * @return Builder object + */ + Builder cpuSpeed(int cpuSpeedMhz); + + /** + * Sets total amount of memory. + * + * @param totalMemoryMbytes memory size in Mega Bytes + * @return Builder object + */ + Builder totalMemory(int totalMemoryMbytes); + + /** + * Builds a SystemInfo object. + * + * @return SystemInfo object + */ + SystemInfo build(); + } +} diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsFactory.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsFactory.java index 4fcf04ff5d..0d50884582 100644 --- a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsFactory.java +++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsFactory.java @@ -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,48 +64,23 @@ public final class ControlMetricsFactory { private Set 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); - } + 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; } } - return uniqueInstance; - } - - /** - * Sets system specification. - * - * @param cmss ControlMetricsSystemSpec object - */ - public void setSystemSpec(ControlMetricsSystemSpec cmss) { - if (this.cmss == null) { - this.cmss = cmss; - } } /** @@ -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 diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsSystemSpec.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsSystemSpec.java deleted file mode 100644 index a80f43c9ac..0000000000 --- a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlMetricsSystemSpec.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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; - -/** - * Control metrics class for storing system specification. - */ -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; - } - - /** - * Returns number of CPU cores. - * - * @return number of CPU cores - */ - public int numOfCores() { - return this.numOfCores; - } - - /** - * Returns number of CPUs. - * - * @return number of CPUs - */ - public int numOfCpus() { - return this.numOfCpus; - } - - /** - * Returns CPU speed in MHz. - * - * @return CPU speed - */ - public int cpuSpeed() { - return this.cpuSpeed; - } - - /** - * Returns the total amount of memory. - * - * @return memory size - */ - public long totalMemory() { - return this.totalMemory; - } - - /** - * ControlMetricsSystemSpec builder class. - */ - public static final class Builder { - private int numOfCores; - private int numOfCpus; - private int cpuSpeed; // in MHz - private long totalMemory; // in bytes - - /** - * Sets number of CPU cores. - * - * @param numOfCores number of CPU cores - * @return Builder object - */ - public Builder numOfCores(int numOfCores) { - this.numOfCores = numOfCores; - return this; - } - - /** - * Sets number of CPUs. - * @param numOfCpus number of CPUs - * @return Builder object - */ - public Builder numOfCpus(int numOfCpus) { - this.numOfCpus = numOfCpus; - return this; - } - - /** - * Sets CPU speed. - * - * @param cpuSpeed CPU speed - * @return Builder object - */ - public Builder cpuSpeed(int cpuSpeed) { - this.cpuSpeed = cpuSpeed; - return this; - } - - /** - * Sets total amount of memory. - * - * @param totalMemory memory size - * @return Builder object - */ - public Builder totalMemory(long totalMemory) { - this.totalMemory = totalMemory; - return this; - } - - /** - * Builds a ControlMetricsSystemSpec object. - * - * @return ControlMetricsSystemSpec object - */ - public ControlMetricsSystemSpec build() { - return new ControlMetricsSystemSpec(numOfCores, numOfCpus, cpuSpeed, totalMemory); - } - } -} diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultSystemInfo.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultSystemInfo.java new file mode 100644 index 0000000000..e4a301b03a --- /dev/null +++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultSystemInfo.java @@ -0,0 +1,95 @@ +/* + * 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); + } + } +} diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/SystemInfoFactory.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/SystemInfoFactory.java new file mode 100644 index 0000000000..78f076d007 --- /dev/null +++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/SystemInfoFactory.java @@ -0,0 +1,74 @@ +/* + * 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(); + } +} diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsCollectorWebResource.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsCollectorWebResource.java index ecb57641bb..777b89f654 100644 --- a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsCollectorWebResource.java +++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/ControlMetricsCollectorWebResource.java @@ -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); } diff --git a/apps/cpman/app/src/main/resources/definitions/SystemSpecsPost.json b/apps/cpman/app/src/main/resources/definitions/SystemInfoPost.json similarity index 100% rename from apps/cpman/app/src/main/resources/definitions/SystemSpecsPost.json rename to apps/cpman/app/src/main/resources/definitions/SystemInfoPost.json diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java index 6fd877044b..ac84e1da0b 100644 --- a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java +++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java @@ -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) { diff --git a/apps/cpman/app/src/test/resources/org/onosproject/cpman/rest/system-spec-post.json b/apps/cpman/app/src/test/resources/org/onosproject/cpman/rest/system-info-post.json similarity index 100% rename from apps/cpman/app/src/test/resources/org/onosproject/cpman/rest/system-spec-post.json rename to apps/cpman/app/src/test/resources/org/onosproject/cpman/rest/system-info-post.json