disk io works using cache - also pid cache cleanup and pid cache dump

This commit is contained in:
nira11 2013-09-15 12:00:23 +00:00
parent f2ba707d9f
commit 07b221a253
20 changed files with 409 additions and 43 deletions

View File

@ -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',
@ -641,9 +643,37 @@ use vars qw(%classes %cmds);
{ {
name => 'bytes_total', type => 'Long', name => 'bytes_total', type => 'Long',
desc => 'Bytes Total', desc => 'Bytes Total',
plat => 'LW' 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',

View File

@ -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.
@ -661,6 +663,34 @@ public class Sigar implements SigarProxy {
return getProcDiskIO(convertPid(pid)); 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.
*/ */

View File

@ -110,6 +110,12 @@ public interface SigarProxy {
public ProcDiskIO getProcDiskIO(String 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;

View File

@ -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();
}
}

View File

@ -103,6 +103,11 @@ public class ProcInfo extends SigarCommandBase {
try { try {
println("diskio=" + sigar.getProcDiskIO(pid)); println("diskio=" + sigar.getProcDiskIO(pid));
} catch (SigarException e) {} } 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 {

View File

@ -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));

View File

@ -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());
}
} }

View File

@ -44,4 +44,6 @@ public interface SigarProcessMBean {
public Double getCpuUsage(); public Double getCpuUsage();
public Long getOpenFd(); public Long getOpenFd();
public Double getBytesReadWriteTotal();
} }

View File

@ -293,7 +293,7 @@ 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 { typedef struct {
sigar_uint64_t sigar_uint64_t
bytes_read, bytes_read,
bytes_written, bytes_written,
bytes_total; bytes_total;
@ -302,6 +302,37 @@ typedef struct {
SIGAR_DECLARE(int) sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, SIGAR_DECLARE(int) sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io); 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;

View File

@ -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

View File

@ -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);

View File

@ -754,8 +754,8 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
return SIGAR_OK; return SIGAR_OK;
} }
int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *cumulative_proc_disk_io)
{ {
int status = sigar_getprocs(sigar, pid); int status = sigar_getprocs(sigar, pid);
struct procsinfo64 *pinfo = sigar->pinfo; struct procsinfo64 *pinfo = sigar->pinfo;
@ -763,13 +763,11 @@ int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL; cumulative_proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL; cumulative_proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_total = pinfo->pi_ioch; cumulative_proc_disk_io->bytes_total = pinfo->pi_ioch;
return SIGAR_OK; return SIGAR_OK;
} }

View File

@ -1241,8 +1241,8 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
return SIGAR_OK; return SIGAR_OK;
} }
int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
{ {
return SIGAR_ENOTIMPL; return SIGAR_ENOTIMPL;
} }

View File

@ -307,8 +307,8 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
return SIGAR_OK; return SIGAR_OK;
} }
int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
{ {
int status = sigar_pstat_getproc(sigar, pid); int status = sigar_pstat_getproc(sigar, pid);
@ -317,9 +317,9 @@ int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
if (status != SIGAR_OK) { if (status != SIGAR_OK) {
return status; return status;
} }
proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL; proc_cumulative_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL; proc_cumulative_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_total = pinfo->pst_ioch; proc_cumulative_disk_io->bytes_total = pinfo->pst_ioch;
return SIGAR_OK; return SIGAR_OK;

View File

@ -778,10 +778,10 @@ SIGAR_INLINE sigar_uint64_t get_named_proc_token(char *buffer,
return sigar_strtoul(ptr); return sigar_strtoul(ptr);
} }
int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
{ {
char buffer[BUFSIZ], *ptr=buffer; char buffer[BUFSIZ];
int status = SIGAR_PROC_FILE2STR(buffer, pid, "/io"); int status = SIGAR_PROC_FILE2STR(buffer, pid, "/io");
@ -789,9 +789,9 @@ int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
return status; return status;
} }
proc_disk_io->bytes_read = get_named_proc_token(buffer, "\nread_bytes"); proc_cumulative_disk_io->bytes_read = get_named_proc_token(buffer, "\nread_bytes");
proc_disk_io->bytes_written = get_named_proc_token(buffer, "\nwrite_bytes"); proc_cumulative_disk_io->bytes_written = get_named_proc_token(buffer, "\nwrite_bytes");
proc_disk_io->bytes_total = proc_disk_io->bytes_read + proc_disk_io->bytes_written; proc_cumulative_disk_io->bytes_total = proc_cumulative_disk_io->bytes_read + proc_cumulative_disk_io->bytes_written;
return SIGAR_OK; return SIGAR_OK;
} }

View File

@ -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,17 +719,17 @@ int sigar_proc_mem_get(sigar_t *sigar, sigar_pid_t pid,
return SIGAR_OK; return SIGAR_OK;
} }
int sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid, int sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
{ {
prusage_t usage; prusage_t usage;
int status; int status;
if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) { if ((status = sigar_proc_usage_get(sigar, &usage, pid)) != SIGAR_OK) {
return status; return status;
} }
proc_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL; proc_cumulative_disk_io->bytes_read = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL; proc_cumulative_disk_io->bytes_written = SIGAR_FIELD_NOTIMPL;
proc_disk_io->bytes_total = usage.pr_ioch; proc_cumulative_disk_io->bytes_total = usage.pr_ioch;
return SIGAR_OK; return SIGAR_OK;
} }

View File

@ -1214,8 +1214,8 @@ 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_disk_io_get(sigar_t *sigar, sigar_pid_t pid, SIGAR_DECLARE(int) sigar_proc_cumulative_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
sigar_proc_disk_io_t *proc_disk_io) sigar_proc_cumulative_disk_io_t *proc_cumulative_disk_io)
{ {
int status = get_proc_info(sigar, pid); int status = get_proc_info(sigar, pid);
sigar_win32_pinfo_t *pinfo = &sigar->pinfo; sigar_win32_pinfo_t *pinfo = &sigar->pinfo;
@ -1224,9 +1224,9 @@ SIGAR_DECLARE(int) sigar_proc_disk_io_get(sigar_t *sigar, sigar_pid_t pid,
return status; return status;
} }
proc_disk_io->bytes_read = pinfo->bytes_read; proc_cumulative_disk_io->bytes_read = pinfo->bytes_read;
proc_disk_io->bytes_written = pinfo->bytes_written; proc_cumulative_disk_io->bytes_written = pinfo->bytes_written;
proc_disk_io->bytes_total = proc_disk_io->bytes_read + proc_disk_io->bytes_written; proc_cumulative_disk_io->bytes_total = proc_cumulative_disk_io->bytes_read + proc_cumulative_disk_io->bytes_written;
return SIGAR_OK; return SIGAR_OK;
} }

View File

@ -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,104 @@ 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) {
if ( current_value == SIGAR_FIELD_NOTIMPL ) {
return SIGAR_FIELD_NOTIMPL;
}
double io_diff = (( current_value - prev_value)/(double)time_diff)*SIGAR_MSEC;
sigar_uint64_t 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;
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);
}
int 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)

View File

@ -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,16 +43,27 @@ 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,73 @@ 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) {
if (table->cleanup_period_millis == SIGAR_FIELD_NOTIMPL) {
/* no cleanup for this cache) */
}
sigar_uint64_t 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 */
int i;
sigar_cache_entry_t **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) {
ptr = entry->next;
sigar_uint64_t period_with_no_access = current_time - entry->last_access_time;
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 +191,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 +217,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;
} }

View File

@ -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 }
}; };