Skip to content

Commit

Permalink
Disk and Network method performance and thread safety (#1107)
Browse files Browse the repository at this point in the history
* Make FreeBsdDisks thread safe

* Refactor MacNetworks

* Performance tweaks

* Fix structure size calculation
  • Loading branch information
dbwiddis committed Feb 15, 2020
1 parent 0cee9ab commit 286543a
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 44 deletions.
28 changes: 22 additions & 6 deletions oshi-core/src/main/java/oshi/hardware/common/AbstractNetworks.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,44 @@ public abstract class AbstractNetworks implements Networks {
@Override
public NetworkIF[] getNetworks() {
List<NetworkIF> result = new ArrayList<>();

for (NetworkInterface netint : getNetworkInterfaces()) {
NetworkIF netIF = new NetworkIF();
netIF.setNetworkInterface(netint);
netIF.updateAttributes();
result.add(netIF);
}

return result.toArray(new NetworkIF[0]);
}

/**
* Returns network interfaces that are not Loopback, and have a hardware
* address.
*
* @return An array of network interfaces
*/
protected NetworkInterface[] getNetworkInterfaces() {
List<NetworkInterface> result = new ArrayList<>();
Enumeration<NetworkInterface> interfaces;

try {
interfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException ex) {
LOG.error("Socket exception when retrieving interfaces: {}", ex);
return new NetworkIF[0];
return new NetworkInterface[0];
}

for (NetworkInterface netint : Collections.list(interfaces)) {
try {
if (!netint.isLoopback() && netint.getHardwareAddress() != null) {
NetworkIF netIF = new NetworkIF();
netIF.setNetworkInterface(netint);
netIF.updateAttributes();
result.add(netIF);
result.add(netint);
}
} catch (SocketException ex) {
LOG.error("Socket exception when retrieving interface \"{}\": {}", netint.getName(), ex);
}
}

return result.toArray(new NetworkIF[0]);
return result.toArray(new NetworkInterface[0]);
}
}
87 changes: 57 additions & 30 deletions oshi-core/src/main/java/oshi/hardware/platform/mac/MacNetworks.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
*/
package oshi.hardware.platform.mac;

import static oshi.util.Memoizer.defaultExpiration;
import static oshi.util.Memoizer.memoize;

import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -57,56 +56,70 @@ public class MacNetworks extends AbstractNetworks {
private static final int NET_RT_IFLIST2 = 6;
private static final int RTM_IFINFO2 = 0x12;

private static final Supplier<Map<Integer, IFdata>> ifDataMap = memoize(MacNetworks::queryIFdata,
defaultExpiration());
@Override
public NetworkIF[] getNetworks() {
List<NetworkIF> result = new ArrayList<>();
Map<Integer, IFdata> ifDataMap = queryIFdata(-1);

for (NetworkInterface netint : getNetworkInterfaces()) {
NetworkIF netIF = new NetworkIF();
netIF.setNetworkInterface(netint);
updateNetworkStats(netIF, ifDataMap);
result.add(netIF);
}

return result.toArray(new NetworkIF[0]);
}

/**
* Map all network interfaces. Ported from source code of "netstat -ir". See
* http://opensource.apple.com/source/network_cmds/network_cmds-457/
* netstat.tproj/if.c
*
* @param index
* If nonnegative, returns results for only that index
* @return a map of {@link IFData} object indexed by the interface index,
* encapsulating the stats, or {@code null} if the query failed.
*/
private static Map<Integer, IFdata> queryIFdata() {
private static Map<Integer, IFdata> queryIFdata(int index) {
Map<Integer, IFdata> data = new HashMap<>();
// Get buffer of all interface information
int[] mib = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 };
IntByReference len = new IntByReference();
if (0 != SystemB.INSTANCE.sysctl(mib, 6, null, len, null, 0)) {
LOG.error("Didn't get buffer length for IFLIST2");
return null;
return data;
}
Pointer buf = new Memory(len.getValue());
Memory buf = new Memory(len.getValue());
if (0 != SystemB.INSTANCE.sysctl(mib, 6, buf, len, null, 0)) {
LOG.error("Didn't get buffer for IFLIST2");
return null;
return data;
}

// Iterate offset from buf's pointer up to limit of buf
int lim = len.getValue();
int next = 0;
while (next < lim) {
int lim = (int) (buf.size() - new IFmsgHdr().size());
int offset = 0;
while (offset < lim) {
// Get pointer to current native part of buf
Pointer p = new Pointer(Pointer.nativeValue(buf) + next);
Pointer p = buf.share(offset);
// Cast pointer to if_msghdr
IFmsgHdr ifm = new IFmsgHdr(p);
ifm.read();
// Advance next
next += ifm.ifm_msglen;
offset += ifm.ifm_msglen;
// Skip messages which are not the right format
if (ifm.ifm_type != RTM_IFINFO2) {
continue;
if (ifm.ifm_type == RTM_IFINFO2) {
// Cast pointer to if_msghdr2
IFmsgHdr2 if2m = new IFmsgHdr2(p);
if2m.read();
if (index < 0 || index == if2m.ifm_index) {
data.put((int) if2m.ifm_index,
new IFdata(if2m.ifm_data.ifi_opackets, if2m.ifm_data.ifi_ipackets, if2m.ifm_data.ifi_obytes,
if2m.ifm_data.ifi_ibytes, if2m.ifm_data.ifi_oerrors, if2m.ifm_data.ifi_ierrors,
if2m.ifm_data.ifi_collisions, if2m.ifm_data.ifi_iqdrops, if2m.ifm_data.ifi_baudrate,
System.currentTimeMillis()));
}
}
// Cast pointer to if_msghdr2
IFmsgHdr2 if2m = new IFmsgHdr2(p);
if2m.read();

data.put((int) if2m.ifm_index,
new IFdata(if2m.ifm_data.ifi_opackets, if2m.ifm_data.ifi_ipackets, if2m.ifm_data.ifi_obytes,
if2m.ifm_data.ifi_ibytes, if2m.ifm_data.ifi_oerrors, if2m.ifm_data.ifi_ierrors,
if2m.ifm_data.ifi_collisions, if2m.ifm_data.ifi_iqdrops, if2m.ifm_data.ifi_baudrate,
System.currentTimeMillis()));
}
return data;
}
Expand All @@ -119,10 +132,24 @@ private static Map<Integer, IFdata> queryIFdata() {
* The interface on which to update statistics
*/
public static boolean updateNetworkStats(NetworkIF netIF) {
Map<Integer, IFdata> data = ifDataMap.get();
IFdata ifData = data.getOrDefault(netIF.queryNetworkInterface().getIndex(), null);
// Update data
if (ifData != null) {
int index = netIF.queryNetworkInterface().getIndex();
return updateNetworkStats(netIF, queryIFdata(index));
}

/**
* Updates interface network statistics on the given interface. Statistics
* include packets and bytes sent and received, and interface speed.
*
* @param netIF
* The interface on which to update statistics
* @param data
* A map of network interface statistics with the index as the key
*/
private static boolean updateNetworkStats(NetworkIF netIF, Map<Integer, IFdata> data) {
int index = netIF.queryNetworkInterface().getIndex();
if (data.containsKey(index)) {
IFdata ifData = data.get(index);
// Update data
netIF.setBytesSent(ifData.oBytes);
netIF.setBytesRecv(ifData.iBytes);
netIF.setPacketsSent(ifData.oPackets);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ public class FreeBsdDisks implements Disks {

private static final Pattern MOUNT_PATTERN = Pattern.compile("/dev/(\\S+p\\d+) on (\\S+) .*");

// Create map indexed by device name to populate data from multiple commands
private static final Map<String, HWDiskStore> diskMap = new HashMap<>();
// Map of partitions to mount points
private static final Map<String, String> mountMap = new HashMap<>();

/**
* <p>
* updateDiskStats.
Expand Down Expand Up @@ -84,11 +79,10 @@ public static boolean updateDiskStats(HWDiskStore diskStore) {
return diskFound;
}

/** {@inheritDoc} */
@Override
public HWDiskStore[] getDisks() {
// Parse 'mount' to map partitions to mount point
mountMap.clear();
Map<String, String> mountMap = new HashMap<>();
for (String mnt : ExecutingCommand.runNative("mount")) {
Matcher m = MOUNT_PATTERN.matcher(mnt);
if (m.matches()) {
Expand All @@ -97,7 +91,8 @@ public HWDiskStore[] getDisks() {
}

// Get list of valid disks
diskMap.clear();
// Create map indexed by device name to populate data from multiple commands
Map<String, HWDiskStore> diskMap = new HashMap<>();
List<String> devices = Arrays.asList(ParseUtil.whitespaces.split(BsdSysctlUtil.sysctl("kern.disks", "")));

// Temporary list to hold partitions
Expand Down

0 comments on commit 286543a

Please sign in to comment.