Merge pull request #33 from nettag/master
disk io per process, and a few bug fixes
This commit is contained in:
commit
189843858e
|
@ -43,6 +43,7 @@ my %has_name_arg = map { $_, 1 } qw(FileSystemUsage DiskUsage
|
||||||
FileAttrs DirStat DirUsage
|
FileAttrs DirStat DirUsage
|
||||||
NetInterfaceConfig NetInterfaceStat);
|
NetInterfaceConfig NetInterfaceStat);
|
||||||
|
|
||||||
|
|
||||||
my %proc_no_arg = map { $_, 1 } qw(stat);
|
my %proc_no_arg = map { $_, 1 } qw(stat);
|
||||||
|
|
||||||
my %get_not_impl = map { $_, 1 } qw(net_address net_route net_connection net_stat cpu_perc
|
my %get_not_impl = map { $_, 1 } qw(net_address net_route net_connection net_stat cpu_perc
|
||||||
|
@ -527,6 +528,7 @@ use vars qw(%classes %cmds);
|
||||||
plat => '*'
|
plat => '*'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
ProcMem => [
|
ProcMem => [
|
||||||
{
|
{
|
||||||
name => 'size', type => 'Long',
|
name => 'size', type => 'Long',
|
||||||
|
@ -627,6 +629,51 @@ use vars qw(%classes %cmds);
|
||||||
plat => '*'
|
plat => '*'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
ProcDiskIO => [
|
||||||
|
{
|
||||||
|
name => 'bytes_read', type => 'Long',
|
||||||
|
desc => 'Bytes Read',
|
||||||
|
plat => 'LW'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'bytes_written', type => 'Long',
|
||||||
|
desc => 'Bytes Written',
|
||||||
|
plat => 'LW'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'bytes_total', type => 'Long',
|
||||||
|
desc => 'Bytes Total',
|
||||||
|
plat => 'LWAHS'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
ProcCumulativeDiskIO => [
|
||||||
|
{
|
||||||
|
name => 'bytes_read', type => 'Long',
|
||||||
|
desc => 'Bytes Read from Start',
|
||||||
|
plat => 'LW'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'bytes_written', type => 'Long',
|
||||||
|
desc => 'Bytes Written from Start',
|
||||||
|
plat => 'LW'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'bytes_total', type => 'Long',
|
||||||
|
desc => 'Bytes Total from Start',
|
||||||
|
plat => 'LWAHS'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
DumpPidCache => [
|
||||||
|
{
|
||||||
|
name => 'dummy', type => 'Long',
|
||||||
|
desc => 'Dummy',
|
||||||
|
plat => 'LWAHS'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
ProcState => [
|
ProcState => [
|
||||||
{
|
{
|
||||||
name => 'state', type => 'Char',
|
name => 'state', type => 'Char',
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.hyperic.jni;
|
package org.hyperic.jni;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
@ -315,7 +316,16 @@ public class ArchLoader {
|
||||||
if ((file != null) &&
|
if ((file != null) &&
|
||||||
((file = file.getParentFile()) != null))
|
((file = file.getParentFile()) != null))
|
||||||
{
|
{
|
||||||
String dir = URLDecoder.decode(file.toString());
|
String dir;
|
||||||
|
try {
|
||||||
|
// Passing UTF-8 according to the recommendation in the URLDecoder.decode JavaDoc.
|
||||||
|
dir = URLDecoder.decode(file.toString(), "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
String msg = "Unsupported encoding in file name: " + file.toString();
|
||||||
|
ArchLoaderException archLoaderException = new ArchLoaderException(msg);
|
||||||
|
archLoaderException.initCause(e);
|
||||||
|
throw archLoaderException;
|
||||||
|
}
|
||||||
if (findNativeLibrary(dir, libName)) {
|
if (findNativeLibrary(dir, libName)) {
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,71 +295,55 @@ public class FileInfo extends FileAttrs implements java.io.Serializable {
|
||||||
ArrayList changes = new ArrayList();
|
ArrayList changes = new ArrayList();
|
||||||
|
|
||||||
if (this.getMtime() != info.getMtime()) {
|
if (this.getMtime() != info.getMtime()) {
|
||||||
changes.add(new Diff("Mtime",
|
changes.add(new Diff("Mtime", formatDate(info.getMtime()),
|
||||||
formatDate(info.getMtime()),
|
|
||||||
formatDate(this.getMtime())));
|
formatDate(this.getMtime())));
|
||||||
}
|
} else if (this.getCtime() != info.getCtime()) {
|
||||||
else if (this.getCtime() != info.getCtime()) {
|
changes.add(new Diff("Ctime", formatDate(info.getCtime()),
|
||||||
changes.add(new Diff("Ctime",
|
|
||||||
formatDate(info.getCtime()),
|
|
||||||
formatDate(this.getCtime())));
|
formatDate(this.getCtime())));
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
//no point in checking the rest if all times are the same.
|
|
||||||
//or should we include atime in the diff?
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getPermissions() != info.getPermissions()) {
|
if (this.getPermissions() != info.getPermissions()) {
|
||||||
changes.add(new Diff("Perms",
|
changes.add(new Diff("Perms", info.getPermissionsString(), this
|
||||||
info.getPermissionsString(),
|
.getPermissionsString()));
|
||||||
this.getPermissionsString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getType() != info.getType()) {
|
if (this.getType() != info.getType()) {
|
||||||
changes.add(new Diff("Type",
|
changes.add(new Diff("Type", info.getTypeString(), this
|
||||||
info.getTypeString(),
|
.getTypeString()));
|
||||||
this.getTypeString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getUid() != info.getUid()) {
|
if (this.getUid() != info.getUid()) {
|
||||||
changes.add(new Diff("Uid",
|
changes.add(new Diff("Uid", info.getUid(), this.getUid()));
|
||||||
info.getUid(),
|
|
||||||
this.getUid()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getGid() != info.getGid()) {
|
if (this.getGid() != info.getGid()) {
|
||||||
changes.add(new Diff("Gid",
|
changes.add(new Diff("Gid", info.getGid(), this.getGid()));
|
||||||
info.getGid(),
|
|
||||||
this.getGid()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getSize() != info.getSize()) {
|
if (this.getSize() != info.getSize()) {
|
||||||
changes.add(new Diff("Size",
|
changes.add(new Diff("Size", info.getSize(), this.getSize()));
|
||||||
info.getSize(),
|
|
||||||
this.getSize()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OperatingSystem.IS_WIN32) {
|
if (!OperatingSystem.IS_WIN32) {
|
||||||
if (this.getInode() != info.getInode()) {
|
if (this.getInode() != info.getInode()) {
|
||||||
changes.add(new Diff("Inode",
|
changes.add(new Diff("Inode", info.getInode(), this.getInode()));
|
||||||
info.getInode(),
|
|
||||||
this.getInode()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getDevice() != info.getDevice()) {
|
if (this.getDevice() != info.getDevice()) {
|
||||||
changes.add(new Diff("Device",
|
changes.add(new Diff("Device", info.getDevice(), this
|
||||||
info.getDevice(),
|
.getDevice()));
|
||||||
this.getDevice()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getNlink() != info.getNlink()) {
|
if (this.getNlink() != info.getNlink()) {
|
||||||
changes.add(new Diff("Nlink",
|
changes.add(new Diff("Nlink", info.getNlink(), this.getNlink()));
|
||||||
info.getNlink(),
|
|
||||||
this.getNlink()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if changes were not detected then return empty String */
|
||||||
|
if (changes.isEmpty()){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
StringBuffer sb = format(changes);
|
StringBuffer sb = format(changes);
|
||||||
if (this.dirStatEnabled) {
|
if (this.dirStatEnabled) {
|
||||||
sb.append(diff(info.stat));
|
sb.append(diff(info.stat));
|
||||||
|
@ -389,7 +373,9 @@ public class FileInfo extends FileAttrs implements java.io.Serializable {
|
||||||
|
|
||||||
stat();
|
stat();
|
||||||
|
|
||||||
return this.mtime != oldInfo.mtime;
|
boolean isModified = isModified(this.oldInfo);
|
||||||
|
|
||||||
|
return isModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean changed()
|
public boolean changed()
|
||||||
|
@ -455,4 +441,49 @@ public class FileInfo extends FileAttrs implements java.io.Serializable {
|
||||||
|
|
||||||
return fetchInfo(sigar, name, false);
|
return fetchInfo(sigar, name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isModified(FileInfo info){
|
||||||
|
/* Check modified time */
|
||||||
|
if (this.getMtime() != info.getMtime()) {
|
||||||
|
return true;
|
||||||
|
} else if (this.getCtime() != info.getCtime()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getPermissions() != info.getPermissions()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getType() != info.getType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getUid() != info.getUid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getGid() != info.getGid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getSize() != info.getSize()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OperatingSystem.IS_WIN32) {
|
||||||
|
if (this.getInode() != info.getInode()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getDevice() != info.getDevice()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getNlink() != info.getNlink()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ public class Sigar implements SigarProxy {
|
||||||
private static String loadError = null;
|
private static String loadError = null;
|
||||||
|
|
||||||
public static final long FIELD_NOTIMPL = -1;
|
public static final long FIELD_NOTIMPL = -1;
|
||||||
|
public static final int PID_PROC_CPU_CACHE = 1;
|
||||||
|
public static final int PID_PROC_IO_CACHE = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Sigar java version.
|
* The Sigar java version.
|
||||||
|
@ -638,6 +640,57 @@ public class Sigar implements SigarProxy {
|
||||||
Integer.parseInt(port));
|
Integer.parseInt(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get process disk IO info.
|
||||||
|
* @param pid THe process id.
|
||||||
|
* @exception SigarException on failure.
|
||||||
|
*/
|
||||||
|
public ProcDiskIO getProcDiskIO(long pid) throws SigarException {
|
||||||
|
try {
|
||||||
|
return ProcDiskIO.fetch(this, pid);
|
||||||
|
} catch (UnsatisfiedLinkError linkErrorException) {
|
||||||
|
// We want to handle exceptions gracefully even if the linked
|
||||||
|
// shared library is older and isn't compiled with the ProcDiskIO APIs.
|
||||||
|
// The downside of this is that we throw SigarNotImplemented exception
|
||||||
|
// also when the shared library can't be loaded.
|
||||||
|
SigarException sigarException = new SigarNotImplementedException();
|
||||||
|
sigarException.initCause(linkErrorException);
|
||||||
|
throw sigarException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcDiskIO getProcDiskIO(String pid) throws SigarException {
|
||||||
|
return getProcDiskIO(convertPid(pid));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get process cumulative disk IO info.
|
||||||
|
* @param pid THe process id.
|
||||||
|
* @exception SigarException on failure.
|
||||||
|
*/
|
||||||
|
public ProcCumulativeDiskIO getProcCumulativeDiskIO(long pid) throws SigarException {
|
||||||
|
try {
|
||||||
|
return ProcCumulativeDiskIO.fetch(this, pid);
|
||||||
|
} catch (UnsatisfiedLinkError linkErrorException) {
|
||||||
|
// We want to handle exceptions gracefully even if the linked
|
||||||
|
// shared library is older and isn't compiled with the ProcDiskIO APIs.
|
||||||
|
// The downside of this is that we throw SigarNotImplemented exception
|
||||||
|
// also when the shared library can't be loaded.
|
||||||
|
SigarException sigarException = new SigarNotImplementedException();
|
||||||
|
sigarException.initCause(linkErrorException);
|
||||||
|
throw sigarException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcCumulativeDiskIO getProcCumulativeDiskIO(String pid) throws SigarException {
|
||||||
|
return getProcCumulativeDiskIO(convertPid(pid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DumpPidCache dumpPidCache() throws SigarException {
|
||||||
|
return DumpPidCache.fetch(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cumulative cpu time for the calling thread.
|
* Get the cumulative cpu time for the calling thread.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -106,6 +106,16 @@ public interface SigarProxy {
|
||||||
|
|
||||||
public long getProcPort(String protocol, String port) throws SigarException;
|
public long getProcPort(String protocol, String port) throws SigarException;
|
||||||
|
|
||||||
|
public ProcDiskIO getProcDiskIO(long pid) throws SigarException;
|
||||||
|
|
||||||
|
public ProcDiskIO getProcDiskIO(String pid) throws SigarException;
|
||||||
|
|
||||||
|
public ProcCumulativeDiskIO getProcCumulativeDiskIO(long pid) throws SigarException;
|
||||||
|
|
||||||
|
public ProcCumulativeDiskIO getProcCumulativeDiskIO(String pid) throws SigarException;
|
||||||
|
|
||||||
|
public DumpPidCache dumpPidCache() throws SigarException;
|
||||||
|
|
||||||
public FileSystem[] getFileSystemList() throws SigarException;
|
public FileSystem[] getFileSystemList() throws SigarException;
|
||||||
|
|
||||||
public FileSystemMap getFileSystemMap() throws SigarException;
|
public FileSystemMap getFileSystemMap() throws SigarException;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2007 Hyperic, Inc.
|
||||||
|
*
|
||||||
|
* 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.hyperic.sigar.cmd;
|
||||||
|
|
||||||
|
import org.hyperic.sigar.SigarException;
|
||||||
|
import org.hyperic.sigar.SigarPermissionDeniedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display all pid cache information.
|
||||||
|
*/
|
||||||
|
public class PidCacheInfo extends SigarCommandBase {
|
||||||
|
|
||||||
|
|
||||||
|
public PidCacheInfo(Shell shell) {
|
||||||
|
super(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PidCacheInfo() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean validateArgs(String[] args) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsageShort() {
|
||||||
|
return "Display cache info for CPU cache and for IO cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPidCompleter() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void output(String[] args) throws SigarException {
|
||||||
|
sigar.dumpPidCache();
|
||||||
|
}
|
||||||
|
}
|
|
@ -100,6 +100,14 @@ public class ProcInfo extends SigarCommandBase {
|
||||||
try {
|
try {
|
||||||
println("credname=" + sigar.getProcCredName(pid));
|
println("credname=" + sigar.getProcCredName(pid));
|
||||||
} catch (SigarException e) {}
|
} catch (SigarException e) {}
|
||||||
|
try {
|
||||||
|
println("diskio=" + sigar.getProcDiskIO(pid));
|
||||||
|
} catch (SigarException e) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
println("cumulative diskio=" + sigar.getProcCumulativeDiskIO(pid));
|
||||||
|
} catch (SigarException e) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
|
@ -103,6 +103,8 @@ public class Shell extends ShellBase {
|
||||||
registerCommandHandler("time", new Time(this));
|
registerCommandHandler("time", new Time(this));
|
||||||
registerCommandHandler("ulimit", new Ulimit(this));
|
registerCommandHandler("ulimit", new Ulimit(this));
|
||||||
registerCommandHandler("who", new Who(this));
|
registerCommandHandler("who", new Who(this));
|
||||||
|
registerCommandHandler("pid_cache_info", new PidCacheInfo(this));
|
||||||
|
|
||||||
if (SigarLoader.IS_WIN32) {
|
if (SigarLoader.IS_WIN32) {
|
||||||
registerCommandHandler("service", new Win32Service(this));
|
registerCommandHandler("service", new Win32Service(this));
|
||||||
registerCommandHandler("fversion", new FileVersionInfo(this));
|
registerCommandHandler("fversion", new FileVersionInfo(this));
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.hyperic.sigar.ProcCpu;
|
||||||
import org.hyperic.sigar.ProcFd;
|
import org.hyperic.sigar.ProcFd;
|
||||||
import org.hyperic.sigar.ProcMem;
|
import org.hyperic.sigar.ProcMem;
|
||||||
import org.hyperic.sigar.ProcUtil;
|
import org.hyperic.sigar.ProcUtil;
|
||||||
|
import org.hyperic.sigar.ProcDiskIO;
|
||||||
import org.hyperic.sigar.Sigar;
|
import org.hyperic.sigar.Sigar;
|
||||||
import org.hyperic.sigar.SigarException;
|
import org.hyperic.sigar.SigarException;
|
||||||
import org.hyperic.sigar.SigarProxy;
|
import org.hyperic.sigar.SigarProxy;
|
||||||
|
@ -76,6 +77,16 @@ public class SigarProcess implements SigarProcessMBean {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private synchronized ProcDiskIO getDiskIO() {
|
||||||
|
try {
|
||||||
|
return this.sigar.getProcDiskIO(getPid());
|
||||||
|
} catch (SigarException e) {
|
||||||
|
throw unexpectedError("DiskIO", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private synchronized ProcFd getFd() throws SigarException {
|
private synchronized ProcFd getFd() throws SigarException {
|
||||||
return this.sigar.getProcFd(getPid());
|
return this.sigar.getProcFd(getPid());
|
||||||
}
|
}
|
||||||
|
@ -153,4 +164,9 @@ public class SigarProcess implements SigarProcessMBean {
|
||||||
return NOTIMPL;
|
return NOTIMPL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Double getBytesReadWriteTotal() {
|
||||||
|
return new Double(getDiskIO().getBytesTotal());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,6 @@ public interface SigarProcessMBean {
|
||||||
public Double getCpuUsage();
|
public Double getCpuUsage();
|
||||||
|
|
||||||
public Long getOpenFd();
|
public Long getOpenFd();
|
||||||
|
|
||||||
|
public Double getBytesReadWriteTotal();
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,11 +133,11 @@ public class TestFileInfo extends SigarTestCase {
|
||||||
tmp.deleteOnExit();
|
tmp.deleteOnExit();
|
||||||
traceln("TMP=" + file);
|
traceln("TMP=" + file);
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
//stat() mtime is in seconds, this happens to quick to detect change.
|
//stat() mtime is in seconds, this happens to quick to detect change.
|
||||||
Thread.sleep(1000 * 1);
|
//Thread.sleep(1000 * 1);
|
||||||
} catch (InterruptedException e) {
|
// } catch (InterruptedException e) {
|
||||||
}
|
// }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileInfo info = sigar.getFileInfo(file);
|
FileInfo info = sigar.getFileInfo(file);
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.hyperic.sigar.test;
|
||||||
|
|
||||||
|
import org.hyperic.sigar.ProcDiskIO;
|
||||||
|
import org.hyperic.sigar.Sigar;
|
||||||
|
import org.hyperic.sigar.SigarException;
|
||||||
|
|
||||||
|
public class TestProcDiskIO extends SigarTestCase {
|
||||||
|
|
||||||
|
public TestProcDiskIO(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void traceDiskIO(Sigar sigar, long pid) throws Exception {
|
||||||
|
ProcDiskIO procDiskIO;
|
||||||
|
|
||||||
|
try {
|
||||||
|
procDiskIO = sigar.getProcDiskIO(pid);
|
||||||
|
} catch (SigarException e) {
|
||||||
|
traceln("pid " + pid + ": " + e.getMessage());
|
||||||
|
// throw e;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long bytesRead = procDiskIO.getBytesRead();
|
||||||
|
long bytesWritten = procDiskIO.getBytesWritten();
|
||||||
|
long bytesTotal = procDiskIO.getBytesTotal();
|
||||||
|
|
||||||
|
traceln("Pid=" + pid);
|
||||||
|
traceln("Bytes Read=" + Sigar.formatSize(bytesRead));
|
||||||
|
traceln("Bytes Written=" + Sigar.formatSize(bytesWritten));
|
||||||
|
traceln("Bytes Total=" + Sigar.formatSize(bytesTotal));
|
||||||
|
|
||||||
|
if (bytesRead != -1 && bytesWritten != -1 && bytesTotal != -1) {
|
||||||
|
assertTrue("Bytes total should equal bytesRead + bytesWritten",
|
||||||
|
(bytesTotal == bytesRead + bytesWritten));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreate() throws Exception {
|
||||||
|
Sigar sigar = getSigar();
|
||||||
|
|
||||||
|
boolean caughtException = false;
|
||||||
|
try {
|
||||||
|
sigar.getProcDiskIO(getInvalidPid());
|
||||||
|
} catch (SigarException e) {
|
||||||
|
caughtException = true;
|
||||||
|
}
|
||||||
|
assertTrue("Test on invalid PID should have thrown an exception.", caughtException);
|
||||||
|
|
||||||
|
long[] pids = sigar.getProcList();
|
||||||
|
for (int i=0; i<pids.length; i++) {
|
||||||
|
traceDiskIO(sigar, pids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -292,6 +292,47 @@ typedef struct {
|
||||||
SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
sigar_proc_mem_t *procmem);
|
sigar_proc_mem_t *procmem);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sigar_uint64_t
|
||||||
|
bytes_read,
|
||||||
|
bytes_written,
|
||||||
|
bytes_total;
|
||||||
|
} sigar_proc_disk_io_t;
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_disk_io_t *proc_disk_io);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sigar_uint64_t
|
||||||
|
bytes_read,
|
||||||
|
bytes_written,
|
||||||
|
bytes_total;
|
||||||
|
sigar_uint64_t last_time;
|
||||||
|
sigar_uint64_t
|
||||||
|
bytes_read_diff,
|
||||||
|
bytes_written_diff,
|
||||||
|
bytes_total_diff;
|
||||||
|
} sigar_cached_proc_disk_io_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sigar_uint64_t
|
||||||
|
bytes_read,
|
||||||
|
bytes_written,
|
||||||
|
bytes_total;
|
||||||
|
} sigar_proc_cumulative_disk_io_t;
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sigar_uint64_t dummy;
|
||||||
|
}sigar_dump_pid_cache_t;
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_dump_pid_cache_get(sigar_t *sigar, sigar_dump_pid_cache_t *info);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sigar_uid_t uid;
|
sigar_uid_t uid;
|
||||||
sigar_gid_t gid;
|
sigar_gid_t gid;
|
||||||
|
|
|
@ -68,7 +68,8 @@
|
||||||
sigar_cache_t *proc_cpu; \
|
sigar_cache_t *proc_cpu; \
|
||||||
sigar_cache_t *net_listen; \
|
sigar_cache_t *net_listen; \
|
||||||
sigar_cache_t *net_services_tcp; \
|
sigar_cache_t *net_services_tcp; \
|
||||||
sigar_cache_t *net_services_udp
|
sigar_cache_t *net_services_udp;\
|
||||||
|
sigar_cache_t *proc_io
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
# define SIGAR_INLINE __inline
|
# define SIGAR_INLINE __inline
|
||||||
|
@ -398,11 +399,15 @@ int sigar_get_iftype(const char *name, int *type, int *inst);
|
||||||
#define SIGAR_NIC_SIT "IPv6-in-IPv4"
|
#define SIGAR_NIC_SIT "IPv6-in-IPv4"
|
||||||
#define SIGAR_NIC_IRDA "IrLAP"
|
#define SIGAR_NIC_IRDA "IrLAP"
|
||||||
#define SIGAR_NIC_EC "Econet"
|
#define SIGAR_NIC_EC "Econet"
|
||||||
|
#define PID_CACHE_CLEANUP_PERIOD 1000*60*10 /* 10 minutes */
|
||||||
|
#define PID_CACHE_ENTRY_EXPIRE_PERIOD 1000*60*20 /* 20 minutes */
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PROC_PID_CPU_CACHE 1
|
||||||
|
#define PROC_PID_IO_CACHE 2
|
||||||
|
|
||||||
#define SIGAR_HOSTENT_LEN 1024
|
#define SIGAR_HOSTENT_LEN 1024
|
||||||
#if defined(_AIX)
|
#if defined(_AIX)
|
||||||
#define SIGAR_HAS_HOSTENT_DATA
|
#define SIGAR_HAS_HOSTENT_DATA
|
||||||
|
|
|
@ -170,15 +170,21 @@ struct sigar_cache_entry_t {
|
||||||
sigar_cache_entry_t *next;
|
sigar_cache_entry_t *next;
|
||||||
sigar_uint64_t id;
|
sigar_uint64_t id;
|
||||||
void *value;
|
void *value;
|
||||||
|
sigar_uint64_t last_access_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sigar_cache_entry_t **entries;
|
sigar_cache_entry_t **entries;
|
||||||
unsigned int count, size;
|
unsigned int count, size;
|
||||||
void (*free_value)(void *ptr);
|
void (*free_value)(void *ptr);
|
||||||
|
sigar_uint64_t entry_expire_period;
|
||||||
|
sigar_uint64_t cleanup_period_millis;
|
||||||
|
sigar_uint64_t last_cleanup_time;
|
||||||
} sigar_cache_t;
|
} sigar_cache_t;
|
||||||
|
|
||||||
sigar_cache_t *sigar_cache_new(int size);
|
sigar_cache_t *sigar_cache_new(int size);
|
||||||
|
sigar_cache_t *sigar_expired_cache_new(int size, sigar_uint64_t cleanup_period_millis, sigar_uint64_t entry_expire_period);
|
||||||
|
void sigar_cache_dump(sigar_cache_t *table);
|
||||||
|
|
||||||
sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
|
sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
|
||||||
sigar_uint64_t key);
|
sigar_uint64_t key);
|
||||||
|
|
|
@ -754,6 +754,23 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *cumulative_proc_disk_io)
|
||||||
|
{
|
||||||
|
int status = sigar_getprocs(sigar, pid);
|
||||||
|
struct procsinfo64 *pinfo = sigar->pinfo;
|
||||||
|
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
cumulative_proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
|
||||||
|
cumulative_proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
|
||||||
|
cumulative_proc_disk_io->bytes_total = pinfo->pi_ioch;
|
||||||
|
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
sigar_proc_cred_t *proccred)
|
sigar_proc_cred_t *proccred)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1241,6 +1241,13 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
|
||||||
|
{
|
||||||
|
return SIGAR_ENOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
sigar_proc_cred_t *proccred)
|
sigar_proc_cred_t *proccred)
|
||||||
{
|
{
|
||||||
|
|
|
@ -307,6 +307,25 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
|
||||||
|
{
|
||||||
|
|
||||||
|
int status = sigar_pstat_getproc(sigar, pid);
|
||||||
|
struct pst_status *pinfo = sigar->pinfo;
|
||||||
|
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
proc_cumulative_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
|
||||||
|
proc_cumulative_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
|
||||||
|
proc_cumulative_disk_io->bytes_total = pinfo->pst_ioch;
|
||||||
|
|
||||||
|
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
sigar_proc_cred_t *proccred)
|
sigar_proc_cred_t *proccred)
|
||||||
{
|
{
|
||||||
|
|
|
@ -768,6 +768,34 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIGAR_INLINE sigar_uint64_t get_named_proc_token(char *buffer,
|
||||||
|
char *token) {
|
||||||
|
char *ptr = strstr(buffer, token);
|
||||||
|
if (!ptr) {
|
||||||
|
return SIGAR_FIELD_NOTIMPL;
|
||||||
|
}
|
||||||
|
ptr = sigar_skip_token(ptr);
|
||||||
|
return sigar_strtoul(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
|
||||||
|
{
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
|
||||||
|
int status = SIGAR_PROC_FILE2STR(buffer, pid, "/io");
|
||||||
|
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_cumulative_disk_io->bytes_read = get_named_proc_token(buffer, "\nread_bytes");
|
||||||
|
proc_cumulative_disk_io->bytes_written = get_named_proc_token(buffer, "\nwrite_bytes");
|
||||||
|
proc_cumulative_disk_io->bytes_total = proc_cumulative_disk_io->bytes_read + proc_cumulative_disk_io->bytes_written;
|
||||||
|
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#define NO_ID_MSG "[proc_cred] /proc/%lu" PROC_PSTATUS " missing "
|
#define NO_ID_MSG "[proc_cred] /proc/%lu" PROC_PSTATUS " missing "
|
||||||
|
|
||||||
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
|
|
@ -407,7 +407,7 @@ int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu)
|
||||||
cpu->idle += xcpu->idle;
|
cpu->idle += xcpu->idle;
|
||||||
cpu->nice += xcpu->nice;
|
cpu->nice += xcpu->nice;
|
||||||
cpu->wait += xcpu->wait;
|
cpu->wait += xcpu->wait;
|
||||||
cpu->total = xcpu->total;
|
cpu->total += xcpu->total;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
|
@ -719,6 +719,21 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
|
||||||
|
{
|
||||||
|
prusage_t usage;
|
||||||
|
int status;
|
||||||
|
if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
proc_cumulative_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
|
||||||
|
proc_cumulative_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
|
||||||
|
proc_cumulative_disk_io->bytes_total = usage.pr_ioch;
|
||||||
|
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
int sigar_proc_cred_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
sigar_proc_cred_t *proccred)
|
sigar_proc_cred_t *proccred)
|
||||||
{
|
{
|
||||||
|
|
|
@ -345,6 +345,8 @@ typedef struct {
|
||||||
sigar_uint64_t handles;
|
sigar_uint64_t handles;
|
||||||
sigar_uint64_t threads;
|
sigar_uint64_t threads;
|
||||||
sigar_uint64_t page_faults;
|
sigar_uint64_t page_faults;
|
||||||
|
sigar_uint64_t bytes_read;
|
||||||
|
sigar_uint64_t bytes_written;
|
||||||
} sigar_win32_pinfo_t;
|
} sigar_win32_pinfo_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -62,6 +62,8 @@ typedef enum {
|
||||||
#define PERF_TITLE_PPID 1410
|
#define PERF_TITLE_PPID 1410
|
||||||
#define PERF_TITLE_PRIORITY 682
|
#define PERF_TITLE_PRIORITY 682
|
||||||
#define PERF_TITLE_START_TIME 684
|
#define PERF_TITLE_START_TIME 684
|
||||||
|
#define PERF_TITLE_IO_READ_BYTES_SEC 1420
|
||||||
|
#define PERF_TITLE_IO_WRITE_BYTES_SEC 1422
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PERF_IX_CPUTIME,
|
PERF_IX_CPUTIME,
|
||||||
|
@ -74,6 +76,8 @@ typedef enum {
|
||||||
PERF_IX_PPID,
|
PERF_IX_PPID,
|
||||||
PERF_IX_PRIORITY,
|
PERF_IX_PRIORITY,
|
||||||
PERF_IX_START_TIME,
|
PERF_IX_START_TIME,
|
||||||
|
PERF_IX_IO_READ_BYTES_SEC,
|
||||||
|
PERF_IX_IO_WRITE_BYTES_SEC,
|
||||||
PERF_IX_MAX
|
PERF_IX_MAX
|
||||||
} perf_proc_offsets_t;
|
} perf_proc_offsets_t;
|
||||||
|
|
||||||
|
@ -1210,6 +1214,23 @@ SIGAR_DECLARE(int) sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
|
||||||
|
{
|
||||||
|
int status = get_proc_info(sigar, pid);
|
||||||
|
sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
|
||||||
|
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_cumulative_disk_io->bytes_read = pinfo->bytes_read;
|
||||||
|
proc_cumulative_disk_io->bytes_written = pinfo->bytes_written;
|
||||||
|
proc_cumulative_disk_io->bytes_total = proc_cumulative_disk_io->bytes_read + proc_cumulative_disk_io->bytes_written;
|
||||||
|
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#define TOKEN_DAC (STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY)
|
#define TOKEN_DAC (STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY)
|
||||||
|
|
||||||
SIGAR_DECLARE(int)
|
SIGAR_DECLARE(int)
|
||||||
|
@ -1441,6 +1462,12 @@ static int get_proc_info(sigar_t *sigar, sigar_pid_t pid)
|
||||||
case PERF_TITLE_START_TIME:
|
case PERF_TITLE_START_TIME:
|
||||||
perf_offsets[PERF_IX_START_TIME] = offset;
|
perf_offsets[PERF_IX_START_TIME] = offset;
|
||||||
break;
|
break;
|
||||||
|
case PERF_TITLE_IO_READ_BYTES_SEC:
|
||||||
|
perf_offsets[PERF_IX_IO_READ_BYTES_SEC] = offset;
|
||||||
|
break;
|
||||||
|
case PERF_TITLE_IO_WRITE_BYTES_SEC:
|
||||||
|
perf_offsets[PERF_IX_IO_WRITE_BYTES_SEC] = offset;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1466,6 +1493,8 @@ static int get_proc_info(sigar_t *sigar, sigar_pid_t pid)
|
||||||
pinfo->handles = PERF_VAL(PERF_IX_HANDLE_CNT);
|
pinfo->handles = PERF_VAL(PERF_IX_HANDLE_CNT);
|
||||||
pinfo->threads = PERF_VAL(PERF_IX_THREAD_CNT);
|
pinfo->threads = PERF_VAL(PERF_IX_THREAD_CNT);
|
||||||
pinfo->page_faults = PERF_VAL(PERF_IX_PAGE_FAULTS);
|
pinfo->page_faults = PERF_VAL(PERF_IX_PAGE_FAULTS);
|
||||||
|
pinfo->bytes_read = PERF_VAL(PERF_IX_IO_READ_BYTES_SEC);
|
||||||
|
pinfo->bytes_written = PERF_VAL(PERF_IX_IO_WRITE_BYTES_SEC);
|
||||||
|
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
@ -3693,6 +3722,7 @@ int sigar_who_list_get_win32(sigar_t *sigar,
|
||||||
#define SIGAR_ARCH "x86"
|
#define SIGAR_ARCH "x86"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int sigar_os_sys_info_get(sigar_t *sigar,
|
int sigar_os_sys_info_get(sigar_t *sigar,
|
||||||
sigar_sys_info_t *sysinfo)
|
sigar_sys_info_t *sysinfo)
|
||||||
{
|
{
|
||||||
|
@ -3741,10 +3771,24 @@ int sigar_os_sys_info_get(sigar_t *sigar,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// not nt work station
|
||||||
|
if (version.dwMinorVersion == 0 || version.dwMinorVersion ==1) {
|
||||||
vendor_name = "Windows 2008";
|
vendor_name = "Windows 2008";
|
||||||
vendor_version = "2008";
|
vendor_version = "2008";
|
||||||
code_name = "Longhorn Server";
|
code_name = "Longhorn Server";
|
||||||
}
|
}
|
||||||
|
else if (version.dwMinorVersion == 2) {
|
||||||
|
vendor_name = "Windows 2012";
|
||||||
|
vendor_version = "2012";
|
||||||
|
code_name = "Windows Server 8";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// defaults
|
||||||
|
vendor_name = "Windows Unknown";
|
||||||
|
vendor_version = "2012";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SIGAR_SSTRCPY(sysinfo->name, "Win32");
|
SIGAR_SSTRCPY(sysinfo->name, "Win32");
|
||||||
|
|
108
src/sigar.c
108
src/sigar.c
|
@ -64,6 +64,7 @@ SIGAR_DECLARE(int) sigar_open(sigar_t **sigar)
|
||||||
(*sigar)->net_listen = NULL;
|
(*sigar)->net_listen = NULL;
|
||||||
(*sigar)->net_services_tcp = NULL;
|
(*sigar)->net_services_tcp = NULL;
|
||||||
(*sigar)->net_services_udp = NULL;
|
(*sigar)->net_services_udp = NULL;
|
||||||
|
(*sigar)->proc_io = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -96,6 +97,11 @@ SIGAR_DECLARE(int) sigar_close(sigar_t *sigar)
|
||||||
if (sigar->net_services_udp) {
|
if (sigar->net_services_udp) {
|
||||||
sigar_cache_destroy(sigar->net_services_udp);
|
sigar_cache_destroy(sigar->net_services_udp);
|
||||||
}
|
}
|
||||||
|
if (sigar->proc_io) {
|
||||||
|
sigar_cache_destroy(sigar->proc_io);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return sigar_os_close(sigar);
|
return sigar_os_close(sigar);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +129,7 @@ SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (!sigar->proc_cpu) {
|
if (!sigar->proc_cpu) {
|
||||||
sigar->proc_cpu = sigar_cache_new(128);
|
sigar->proc_cpu = sigar_expired_cache_new(128, PID_CACHE_CLEANUP_PERIOD, PID_CACHE_ENTRY_EXPIRE_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = sigar_cache_get(sigar->proc_cpu, pid);
|
entry = sigar_cache_get(sigar->proc_cpu, pid);
|
||||||
|
@ -172,6 +178,106 @@ SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
|
||||||
return SIGAR_OK;
|
return SIGAR_OK;
|
||||||
}
|
}
|
||||||
|
void copy_cached_disk_io_into_disk_io( sigar_cached_proc_disk_io_t *cached, sigar_proc_disk_io_t *proc_disk_io) {
|
||||||
|
proc_disk_io->bytes_read = cached->bytes_read_diff;
|
||||||
|
proc_disk_io->bytes_written = cached->bytes_written_diff;
|
||||||
|
proc_disk_io->bytes_total = cached->bytes_total_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigar_uint64_t get_io_diff(sigar_uint64_t current_value, sigar_uint64_t prev_value, sigar_uint64_t time_diff) {
|
||||||
|
double io_diff;
|
||||||
|
sigar_uint64_t int_io_diff;
|
||||||
|
if ( current_value == SIGAR_FIELD_NOTIMPL ) {
|
||||||
|
return SIGAR_FIELD_NOTIMPL;
|
||||||
|
}
|
||||||
|
io_diff = (( current_value - prev_value)/(double)time_diff)*SIGAR_MSEC;
|
||||||
|
int_io_diff = (sigar_uint64_t)io_diff;
|
||||||
|
if (int_io_diff >=0) {
|
||||||
|
return int_io_diff;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculate_io_diff(sigar_proc_cumulative_disk_io_t * proc_disk_io, sigar_cached_proc_disk_io_t *cached, sigar_uint64_t time_diff, int is_first_time) {
|
||||||
|
/*calculate avg diff /read/write/total per second*/
|
||||||
|
if (!is_first_time) {
|
||||||
|
cached->bytes_written_diff = get_io_diff(proc_disk_io->bytes_written, cached->bytes_written, time_diff);
|
||||||
|
cached->bytes_read_diff = get_io_diff(proc_disk_io->bytes_read, cached->bytes_read, time_diff);
|
||||||
|
cached->bytes_total_diff = get_io_diff(proc_disk_io->bytes_total, cached->bytes_total, time_diff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cached->bytes_total_diff = cached->bytes_read_diff = cached->bytes_written_diff = 0.0;
|
||||||
|
}
|
||||||
|
// now put in cache the current cumulative values
|
||||||
|
cached->bytes_written = proc_disk_io->bytes_written;
|
||||||
|
cached->bytes_read = proc_disk_io->bytes_read;
|
||||||
|
cached->bytes_total = proc_disk_io->bytes_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
|
||||||
|
sigar_proc_disk_io_t *proc_disk_io)
|
||||||
|
{
|
||||||
|
sigar_cache_entry_t *entry;
|
||||||
|
sigar_cached_proc_disk_io_t *prev;
|
||||||
|
sigar_proc_cumulative_disk_io_t cumulative_proc_disk_io;
|
||||||
|
sigar_uint64_t time_now = sigar_time_now_millis();
|
||||||
|
sigar_uint64_t time_diff;
|
||||||
|
int status, is_first_time;
|
||||||
|
|
||||||
|
if (!sigar->proc_io) {
|
||||||
|
sigar->proc_io = sigar_expired_cache_new(128, PID_CACHE_CLEANUP_PERIOD, PID_CACHE_ENTRY_EXPIRE_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = sigar_cache_get(sigar->proc_io, pid);
|
||||||
|
if (entry->value) {
|
||||||
|
prev = (sigar_cached_proc_disk_io_t *)entry->value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev = entry->value = malloc(sizeof(*prev));
|
||||||
|
SIGAR_ZERO(prev);
|
||||||
|
}
|
||||||
|
is_first_time = (prev->last_time == 0);
|
||||||
|
time_diff = time_now - prev->last_time;
|
||||||
|
|
||||||
|
if (time_diff < 1000) {
|
||||||
|
/* we were just called within < 1 second ago. */
|
||||||
|
copy_cached_disk_io_into_disk_io(prev, proc_disk_io);
|
||||||
|
if (time_diff < 0) {
|
||||||
|
// something is wrong at least from now on the time will be ok
|
||||||
|
prev->last_time = time_now;
|
||||||
|
}
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
prev->last_time = time_now;
|
||||||
|
|
||||||
|
|
||||||
|
status =
|
||||||
|
sigar_proc_cumulative_disk_io_get(sigar, pid,
|
||||||
|
&cumulative_proc_disk_io);
|
||||||
|
|
||||||
|
if (status != SIGAR_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
calculate_io_diff(&cumulative_proc_disk_io, prev, time_diff, is_first_time);
|
||||||
|
copy_cached_disk_io_into_disk_io(prev, proc_disk_io);
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_cache_info(sigar_cache_t * cache, char * name){
|
||||||
|
if (cache == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("******** %s *********\n", name);
|
||||||
|
sigar_cache_dump(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
SIGAR_DECLARE(int) sigar_dump_pid_cache_get(sigar_t *sigar, sigar_dump_pid_cache_t *info) {
|
||||||
|
|
||||||
|
get_cache_info(sigar->proc_cpu, "proc cpu cache");
|
||||||
|
get_cache_info(sigar->proc_io, "proc io cache");
|
||||||
|
return SIGAR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar,
|
SIGAR_DECLARE(int) sigar_proc_stat_get(sigar_t *sigar,
|
||||||
sigar_proc_stat_t *procstat)
|
sigar_proc_stat_t *procstat)
|
||||||
|
|
|
@ -35,7 +35,7 @@ static void free_value(void *ptr)
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sigar_cache_t *sigar_cache_new(int size)
|
sigar_cache_t *sigar_expired_cache_new(int size, sigar_uint64_t cleanup_period_millis, sigar_uint64_t entry_expire_period)
|
||||||
{
|
{
|
||||||
sigar_cache_t *table = malloc(sizeof(*table));
|
sigar_cache_t *table = malloc(sizeof(*table));
|
||||||
table->count = 0;
|
table->count = 0;
|
||||||
|
@ -43,15 +43,26 @@ sigar_cache_t *sigar_cache_new(int size)
|
||||||
table->entries = malloc(ENTRIES_SIZE(size));
|
table->entries = malloc(ENTRIES_SIZE(size));
|
||||||
memset(table->entries, '\0', ENTRIES_SIZE(size));
|
memset(table->entries, '\0', ENTRIES_SIZE(size));
|
||||||
table->free_value = free_value;
|
table->free_value = free_value;
|
||||||
|
table->cleanup_period_millis = cleanup_period_millis;
|
||||||
|
table->last_cleanup_time = sigar_time_now_millis();
|
||||||
|
table->entry_expire_period = entry_expire_period;
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CACHE
|
sigar_cache_t *sigar_cache_new(int size)
|
||||||
|
{
|
||||||
|
return sigar_expired_cache_new(size, SIGAR_FIELD_NOTIMPL, SIGAR_FIELD_NOTIMPL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*#ifdef DEBUG_CACHE*/
|
||||||
/* see how well entries are distributed */
|
/* see how well entries are distributed */
|
||||||
static void sigar_cache_dump(sigar_cache_t *table)
|
void sigar_cache_dump(sigar_cache_t *table)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
sigar_cache_entry_t **entries = table->entries;
|
sigar_cache_entry_t **entries = table->entries;
|
||||||
|
printf("table size %lu\n", (long)table->size);
|
||||||
|
printf("table count %lu\n", (long)table->count);
|
||||||
|
|
||||||
for (i=0; i<table->size; i++) {
|
for (i=0; i<table->size; i++) {
|
||||||
sigar_cache_entry_t *entry = *entries++;
|
sigar_cache_entry_t *entry = *entries++;
|
||||||
|
@ -68,12 +79,12 @@ static void sigar_cache_dump(sigar_cache_t *table)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
#endif
|
/*#endif*/
|
||||||
|
|
||||||
static void sigar_cache_rehash(sigar_cache_t *table)
|
static void sigar_cache_rehash(sigar_cache_t *table)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int new_size = table->size * 2 + 1;
|
unsigned int new_size = table->count * 2 + 1;
|
||||||
sigar_cache_entry_t **entries = table->entries;
|
sigar_cache_entry_t **entries = table->entries;
|
||||||
sigar_cache_entry_t **new_entries =
|
sigar_cache_entry_t **new_entries =
|
||||||
malloc(ENTRIES_SIZE(new_size));
|
malloc(ENTRIES_SIZE(new_size));
|
||||||
|
@ -101,16 +112,76 @@ static void sigar_cache_rehash(sigar_cache_t *table)
|
||||||
#define SIGAR_CACHE_IX(t, k) \
|
#define SIGAR_CACHE_IX(t, k) \
|
||||||
t->entries + (k % t->size)
|
t->entries + (k % t->size)
|
||||||
|
|
||||||
|
void sigar_perform_cleanup_if_necessary(sigar_cache_t *table) {
|
||||||
|
sigar_uint64_t current_time;
|
||||||
|
int i;
|
||||||
|
sigar_cache_entry_t **entries;
|
||||||
|
if (table->cleanup_period_millis == SIGAR_FIELD_NOTIMPL) {
|
||||||
|
/* no cleanup for this cache) */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current_time = sigar_time_now_millis();
|
||||||
|
if ((current_time - table->last_cleanup_time) < table->cleanup_period_millis) {
|
||||||
|
/* not enough time has passed since last cleanup */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* performing cleanup */
|
||||||
|
entries = table->entries;
|
||||||
|
|
||||||
|
table->last_cleanup_time = current_time;
|
||||||
|
|
||||||
|
for (i=0; i<table->size; i++) {
|
||||||
|
sigar_cache_entry_t *entry, *ptr, *entry_prev=NULL, **entry_in_table;
|
||||||
|
entry_in_table = entries;
|
||||||
|
entry = *entries++;
|
||||||
|
|
||||||
|
while (entry) {
|
||||||
|
sigar_uint64_t period_with_no_access = current_time - entry->last_access_time;
|
||||||
|
ptr = entry->next;
|
||||||
|
if (table->entry_expire_period < period_with_no_access) {
|
||||||
|
/* no one acess this entry for too long - we can delete it */
|
||||||
|
if (entry->value) {
|
||||||
|
table->free_value(entry->value);
|
||||||
|
}
|
||||||
|
free(entry);
|
||||||
|
table->count--;
|
||||||
|
if (entry_prev != NULL) {
|
||||||
|
entry_prev->next = ptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* removing first entry - head of list should point to next entry */
|
||||||
|
*entry_in_table = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* entry not expired - advance entry_prev to current entry*/
|
||||||
|
entry_prev = entry;
|
||||||
|
}
|
||||||
|
entry = ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (table->count < (table->size/4)) {
|
||||||
|
/* hash table (the array size) too big for the amount of values it contains perform rehash */
|
||||||
|
sigar_cache_rehash(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table,
|
sigar_cache_entry_t *sigar_cache_find(sigar_cache_t *table,
|
||||||
sigar_uint64_t key)
|
sigar_uint64_t key)
|
||||||
{
|
{
|
||||||
sigar_cache_entry_t *entry, **ptr;
|
sigar_cache_entry_t *entry, **ptr;
|
||||||
|
sigar_perform_cleanup_if_necessary(table);
|
||||||
|
|
||||||
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
||||||
entry;
|
entry;
|
||||||
ptr = &entry->next, entry = *ptr)
|
ptr = &entry->next, entry = *ptr)
|
||||||
{
|
{
|
||||||
if (entry->id == key) {
|
if (entry->id == key) {
|
||||||
|
entry->last_access_time = sigar_time_now_millis();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,17 +194,19 @@ sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
|
||||||
sigar_uint64_t key)
|
sigar_uint64_t key)
|
||||||
{
|
{
|
||||||
sigar_cache_entry_t *entry, **ptr;
|
sigar_cache_entry_t *entry, **ptr;
|
||||||
|
sigar_perform_cleanup_if_necessary(table);
|
||||||
|
|
||||||
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
||||||
entry;
|
entry;
|
||||||
ptr = &entry->next, entry = *ptr)
|
ptr = &entry->next, entry = *ptr)
|
||||||
{
|
{
|
||||||
if (entry->id == key) {
|
if (entry->id == key) {
|
||||||
|
entry->last_access_time = sigar_time_now_millis();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table->count++ > table->size) {
|
if (++table->count > table->size) {
|
||||||
sigar_cache_rehash(table);
|
sigar_cache_rehash(table);
|
||||||
|
|
||||||
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
for (ptr = SIGAR_CACHE_IX(table, key), entry = *ptr;
|
||||||
|
@ -147,6 +220,7 @@ sigar_cache_entry_t *sigar_cache_get(sigar_cache_t *table,
|
||||||
entry->id = key;
|
entry->id = key;
|
||||||
entry->value = NULL;
|
entry->value = NULL;
|
||||||
entry->next = NULL;
|
entry->next = NULL;
|
||||||
|
entry->last_access_time = sigar_time_now_millis();
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1338,6 +1338,14 @@ static ptql_lookup_t PTQL_Cpu[] = {
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ptql_lookup_t PTQL_Disk_IO[] = {
|
||||||
|
{ "BytesRead", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_read, UI64) },
|
||||||
|
{ "BytesWritten", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_written, UI64) },
|
||||||
|
{ "BytesTotal", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_total, UI64) },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static ptql_lookup_t PTQL_CredName[] = {
|
static ptql_lookup_t PTQL_CredName[] = {
|
||||||
{ "User", PTQL_LOOKUP_ENTRY(proc_cred_name, user, STR) },
|
{ "User", PTQL_LOOKUP_ENTRY(proc_cred_name, user, STR) },
|
||||||
{ "Group", PTQL_LOOKUP_ENTRY(proc_cred_name, group, STR) },
|
{ "Group", PTQL_LOOKUP_ENTRY(proc_cred_name, group, STR) },
|
||||||
|
@ -1424,6 +1432,7 @@ static ptql_entry_t ptql_map[] = {
|
||||||
{ "Port", PTQL_Port },
|
{ "Port", PTQL_Port },
|
||||||
{ "Pid", PTQL_Pid },
|
{ "Pid", PTQL_Pid },
|
||||||
{ "Service", PTQL_Service },
|
{ "Service", PTQL_Service },
|
||||||
|
{ "Disk_IO", PTQL_Disk_IO },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue