MAPREDUCE-3583. Change pid to String and stime to BigInteger in order to handle integers larger than Long.MAX_VALUE. Contributed by Zhihong Yu

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1245828 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tsz-wo Sze 2012-02-18 01:12:18 +00:00
parent ff33b38734
commit b4c8567e1b
4 changed files with 134 additions and 113 deletions

View File

@ -124,6 +124,9 @@ Release 0.23.2 - UNRELEASED
urls when mutiple jobs are submitted from same client jvm. (Eric Payne via urls when mutiple jobs are submitted from same client jvm. (Eric Payne via
sseth) sseth)
MAPREDUCE-3583. Change pid to String and stime to BigInteger in order to
avoid NumberFormatException caused by overflow. (Zhihong Yu via szetszwo)
Release 0.23.1 - 2012-02-08 Release 0.23.1 - 2012-02-08
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -91,12 +92,14 @@ public class ProcfsBasedProcessTree extends ProcessTree {
// to a test directory. // to a test directory.
private String procfsDir; private String procfsDir;
private Integer pid = -1; static private String deadPid = "-1";
private String pid = deadPid;
static private Pattern numberPattern = Pattern.compile("[1-9][0-9]*");
private Long cpuTime = 0L; private Long cpuTime = 0L;
private boolean setsidUsed = false; private boolean setsidUsed = false;
private long sleeptimeBeforeSigkill = DEFAULT_SLEEPTIME_BEFORE_SIGKILL; private long sleeptimeBeforeSigkill = DEFAULT_SLEEPTIME_BEFORE_SIGKILL;
private Map<Integer, ProcessInfo> processTree = new HashMap<Integer, ProcessInfo>(); private Map<String, ProcessInfo> processTree = new HashMap<String, ProcessInfo>();
public ProcfsBasedProcessTree(String pid) { public ProcfsBasedProcessTree(String pid) {
this(pid, false, DEFAULT_SLEEPTIME_BEFORE_SIGKILL); this(pid, false, DEFAULT_SLEEPTIME_BEFORE_SIGKILL);
@ -166,19 +169,19 @@ public class ProcfsBasedProcessTree extends ProcessTree {
* @return the process-tree with latest state. * @return the process-tree with latest state.
*/ */
public ProcfsBasedProcessTree getProcessTree() { public ProcfsBasedProcessTree getProcessTree() {
if (pid != -1) { if (!pid.equals(deadPid)) {
// Get the list of processes // Get the list of processes
List<Integer> processList = getProcessList(); List<String> processList = getProcessList();
Map<Integer, ProcessInfo> allProcessInfo = new HashMap<Integer, ProcessInfo>(); Map<String, ProcessInfo> allProcessInfo = new HashMap<String, ProcessInfo>();
// cache the processTree to get the age for processes // cache the processTree to get the age for processes
Map<Integer, ProcessInfo> oldProcs = Map<String, ProcessInfo> oldProcs =
new HashMap<Integer, ProcessInfo>(processTree); new HashMap<String, ProcessInfo>(processTree);
processTree.clear(); processTree.clear();
ProcessInfo me = null; ProcessInfo me = null;
for (Integer proc : processList) { for (String proc : processList) {
// Get information for each process // Get information for each process
ProcessInfo pInfo = new ProcessInfo(proc); ProcessInfo pInfo = new ProcessInfo(proc);
if (constructProcessInfo(pInfo, procfsDir) != null) { if (constructProcessInfo(pInfo, procfsDir) != null) {
@ -195,9 +198,9 @@ public class ProcfsBasedProcessTree extends ProcessTree {
} }
// Add each process to its parent. // Add each process to its parent.
for (Map.Entry<Integer, ProcessInfo> entry : allProcessInfo.entrySet()) { for (Map.Entry<String, ProcessInfo> entry : allProcessInfo.entrySet()) {
Integer pID = entry.getKey(); String pID = entry.getKey();
if (pID != 1) { if (!pID.equals("1")) {
ProcessInfo pInfo = entry.getValue(); ProcessInfo pInfo = entry.getValue();
ProcessInfo parentPInfo = allProcessInfo.get(pInfo.getPpid()); ProcessInfo parentPInfo = allProcessInfo.get(pInfo.getPpid());
if (parentPInfo != null) { if (parentPInfo != null) {
@ -218,7 +221,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
} }
// update age values and compute the number of jiffies since last update // update age values and compute the number of jiffies since last update
for (Map.Entry<Integer, ProcessInfo> procs : processTree.entrySet()) { for (Map.Entry<String, ProcessInfo> procs : processTree.entrySet()) {
ProcessInfo oldInfo = oldProcs.get(procs.getKey()); ProcessInfo oldInfo = oldProcs.get(procs.getKey());
if (procs.getValue() != null) { if (procs.getValue() != null) {
procs.getValue().updateJiffy(oldInfo); procs.getValue().updateJiffy(oldInfo);
@ -242,10 +245,10 @@ public class ProcfsBasedProcessTree extends ProcessTree {
* @return true if the root-process is alive, false otherwise. * @return true if the root-process is alive, false otherwise.
*/ */
public boolean isAlive() { public boolean isAlive() {
if (pid == -1) { if (pid.equals(deadPid)) {
return false; return false;
} else { } else {
return isAlive(pid.toString()); return isAlive(pid);
} }
} }
@ -256,8 +259,8 @@ public class ProcfsBasedProcessTree extends ProcessTree {
* alive, false otherwise. * alive, false otherwise.
*/ */
public boolean isAnyProcessInTreeAlive() { public boolean isAnyProcessInTreeAlive() {
for (Integer pId : processTree.keySet()) { for (String pId : processTree.keySet()) {
if (isAlive(pId.toString())) { if (isAlive(pId)) {
return true; return true;
} }
} }
@ -269,9 +272,8 @@ public class ProcfsBasedProcessTree extends ProcessTree {
* @param procfsDir Procfs root dir * @param procfsDir Procfs root dir
*/ */
static boolean checkPidPgrpidForMatch(String pidStr, String procfsDir) { static boolean checkPidPgrpidForMatch(String pidStr, String procfsDir) {
Integer pId = Integer.parseInt(pidStr);
// Get information for this process // Get information for this process
ProcessInfo pInfo = new ProcessInfo(pId); ProcessInfo pInfo = new ProcessInfo(pidStr);
pInfo = constructProcessInfo(pInfo, procfsDir); pInfo = constructProcessInfo(pInfo, procfsDir);
if (pInfo == null) { if (pInfo == null) {
// process group leader may have finished execution, but we still need to // process group leader may have finished execution, but we still need to
@ -279,14 +281,15 @@ public class ProcfsBasedProcessTree extends ProcessTree {
return true; return true;
} }
String pgrpId = pInfo.getPgrpId().toString();
//make sure that pId and its pgrpId match //make sure that pId and its pgrpId match
if (!pInfo.getPgrpId().equals(pId)) { if (!pgrpId.equals(pidStr)) {
LOG.warn("Unexpected: Process with PID " + pId + LOG.warn("Unexpected: Process with PID " + pidStr +
" is not a process group leader."); " is not a process group leader. pgrpId is: " + pInfo.getPgrpId());
return false; return false;
} }
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug(pId + " is a process group leader, as expected."); LOG.debug(pidStr + " is a process group leader, as expected.");
} }
return true; return true;
} }
@ -324,7 +327,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
*/ */
public void destroy(boolean inBackground) { public void destroy(boolean inBackground) {
LOG.debug("Killing ProcfsBasedProcessTree of " + pid); LOG.debug("Killing ProcfsBasedProcessTree of " + pid);
if (pid == -1) { if (pid.equals(deadPid)) {
return; return;
} }
if (isAlive(pid.toString())) { if (isAlive(pid.toString())) {
@ -347,7 +350,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
} }
private static final String PROCESSTREE_DUMP_FORMAT = private static final String PROCESSTREE_DUMP_FORMAT =
"\t|- %d %d %d %d %s %d %d %d %d %s\n"; "\t|- %s %s %d %d %s %d %d %d %d %s\n";
/** /**
* Get a dump of the process-tree. * Get a dump of the process-tree.
@ -458,34 +461,27 @@ public class ProcfsBasedProcessTree extends ProcessTree {
return cpuTime; return cpuTime;
} }
private static Integer getValidPID(String pid) { private static String getValidPID(String pid) {
Integer retPid = -1; if (pid == null) return deadPid;
try { Matcher m = numberPattern.matcher(pid);
retPid = Integer.parseInt(pid); if (m.matches()) return pid;
if (retPid <= 0) { return deadPid;
retPid = -1;
}
} catch (NumberFormatException nfe) {
retPid = -1;
}
return retPid;
} }
/** /**
* Get the list of all processes in the system. * Get the list of all processes in the system.
*/ */
private List<Integer> getProcessList() { private List<String> getProcessList() {
String[] processDirs = (new File(procfsDir)).list(); String[] processDirs = (new File(procfsDir)).list();
List<Integer> processList = new ArrayList<Integer>(); List<String> processList = new ArrayList<String>();
for (String dir : processDirs) { for (String dir : processDirs) {
Matcher m = numberPattern.matcher(dir);
if (!m.matches()) continue;
try { try {
int pd = Integer.parseInt(dir);
if ((new File(procfsDir, dir)).isDirectory()) { if ((new File(procfsDir, dir)).isDirectory()) {
processList.add(Integer.valueOf(pd)); processList.add(dir);
} }
} catch (NumberFormatException n) {
// skip this directory
} catch (SecurityException s) { } catch (SecurityException s) {
// skip this process // skip this process
} }
@ -511,7 +507,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
BufferedReader in = null; BufferedReader in = null;
FileReader fReader = null; FileReader fReader = null;
try { try {
File pidDir = new File(procfsDir, String.valueOf(pinfo.getPid())); File pidDir = new File(procfsDir, pinfo.getPid());
fReader = new FileReader(new File(pidDir, PROCFS_STAT_FILE)); fReader = new FileReader(new File(pidDir, PROCFS_STAT_FILE));
in = new BufferedReader(fReader); in = new BufferedReader(fReader);
} catch (FileNotFoundException f) { } catch (FileNotFoundException f) {
@ -528,9 +524,9 @@ public class ProcfsBasedProcessTree extends ProcessTree {
boolean mat = m.find(); boolean mat = m.find();
if (mat) { if (mat) {
// Set (name) (ppid) (pgrpId) (session) (utime) (stime) (vsize) (rss) // Set (name) (ppid) (pgrpId) (session) (utime) (stime) (vsize) (rss)
pinfo.updateProcessInfo(m.group(2), Integer.parseInt(m.group(3)), pinfo.updateProcessInfo(m.group(2), m.group(3),
Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)), Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)),
Long.parseLong(m.group(7)), Long.parseLong(m.group(8)), Long.parseLong(m.group(7)), new BigInteger(m.group(8)),
Long.parseLong(m.group(10)), Long.parseLong(m.group(11))); Long.parseLong(m.group(10)), Long.parseLong(m.group(11)));
} else { } else {
LOG.warn("Unexpected: procfs stat file is not in the expected format" LOG.warn("Unexpected: procfs stat file is not in the expected format"
@ -562,7 +558,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
*/ */
public String toString() { public String toString() {
StringBuffer pTree = new StringBuffer("[ "); StringBuffer pTree = new StringBuffer("[ ");
for (Integer p : processTree.keySet()) { for (String p : processTree.keySet()) {
pTree.append(p); pTree.append(p);
pTree.append(" "); pTree.append(" ");
} }
@ -575,15 +571,16 @@ public class ProcfsBasedProcessTree extends ProcessTree {
* *
*/ */
private static class ProcessInfo { private static class ProcessInfo {
private Integer pid; // process-id private String pid; // process-id
private String name; // command name private String name; // command name
private Integer pgrpId; // process group-id private Integer pgrpId; // process group-id
private Integer ppid; // parent process-id private String ppid; // parent process-id
private Integer sessionId; // session-id private Integer sessionId; // session-id
private Long vmem; // virtual memory usage private Long vmem; // virtual memory usage
private Long rssmemPage; // rss memory usage in # of pages private Long rssmemPage; // rss memory usage in # of pages
private Long utime = 0L; // # of jiffies in user mode private Long utime = 0L; // # of jiffies in user mode
private Long stime = 0L; // # of jiffies in kernel mode private final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
private BigInteger stime = new BigInteger("0"); // # of jiffies in kernel mode
// how many times has this process been seen alive // how many times has this process been seen alive
private int age; private int age;
@ -595,13 +592,13 @@ public class ProcfsBasedProcessTree extends ProcessTree {
private List<ProcessInfo> children = new ArrayList<ProcessInfo>(); // list of children private List<ProcessInfo> children = new ArrayList<ProcessInfo>(); // list of children
public ProcessInfo(int pid) { public ProcessInfo(String pid) {
this.pid = Integer.valueOf(pid); this.pid = pid;
// seeing this the first time. // seeing this the first time.
this.age = 1; this.age = 1;
} }
public Integer getPid() { public String getPid() {
return pid; return pid;
} }
@ -613,7 +610,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
return pgrpId; return pgrpId;
} }
public Integer getPpid() { public String getPpid() {
return ppid; return ppid;
} }
@ -629,7 +626,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
return utime; return utime;
} }
public Long getStime() { public BigInteger getStime() {
return stime; return stime;
} }
@ -652,8 +649,8 @@ public class ProcfsBasedProcessTree extends ProcessTree {
return false; return false;
} }
public void updateProcessInfo(String name, Integer ppid, Integer pgrpId, public void updateProcessInfo(String name, String ppid, Integer pgrpId,
Integer sessionId, Long utime, Long stime, Long vmem, Long rssmem) { Integer sessionId, Long utime, BigInteger stime, Long vmem, Long rssmem) {
this.name = name; this.name = name;
this.ppid = ppid; this.ppid = ppid;
this.pgrpId = pgrpId; this.pgrpId = pgrpId;
@ -665,8 +662,19 @@ public class ProcfsBasedProcessTree extends ProcessTree {
} }
public void updateJiffy(ProcessInfo oldInfo) { public void updateJiffy(ProcessInfo oldInfo) {
this.dtime = (oldInfo == null ? this.utime + this.stime if (oldInfo == null) {
: (this.utime + this.stime) - (oldInfo.utime + oldInfo.stime)); BigInteger sum = this.stime.add(BigInteger.valueOf(this.utime));
if (sum.compareTo(MAX_LONG) > 0) {
this.dtime = 0L;
LOG.warn("Sum of stime (" + this.stime + ") and utime (" + this.utime
+ ") is greater than " + Long.MAX_VALUE);
} else {
this.dtime = sum.longValue();
}
return;
}
this.dtime = (this.utime - oldInfo.utime +
this.stime.subtract(oldInfo.stime).longValue());
} }
public void updateAge(ProcessInfo oldInfo) { public void updateAge(ProcessInfo oldInfo) {
@ -690,7 +698,7 @@ public class ProcfsBasedProcessTree extends ProcessTree {
FileReader fReader = null; FileReader fReader = null;
try { try {
fReader = fReader =
new FileReader(new File(new File(procfsDir, pid.toString()), new FileReader(new File(new File(procfsDir, pid),
PROCFS_CMDLINE_FILE)); PROCFS_CMDLINE_FILE));
} catch (FileNotFoundException f) { } catch (FileNotFoundException f) {
// The process vanished in the interim! // The process vanished in the interim!

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -91,12 +92,14 @@ public class ProcfsBasedProcessTree {
// to a test directory. // to a test directory.
private String procfsDir; private String procfsDir;
protected final Integer pid; static private String deadPid = "-1";
private String pid = deadPid;
static private Pattern numberPattern = Pattern.compile("[1-9][0-9]*");
private Long cpuTime = 0L; private Long cpuTime = 0L;
private boolean setsidUsed = false; private boolean setsidUsed = false;
protected Map<Integer, ProcessInfo> processTree = protected Map<String, ProcessInfo> processTree =
new HashMap<Integer, ProcessInfo>(); new HashMap<String, ProcessInfo>();
public ProcfsBasedProcessTree(String pid) { public ProcfsBasedProcessTree(String pid) {
this(pid, false); this(pid, false);
@ -150,19 +153,19 @@ public class ProcfsBasedProcessTree {
* @return the process-tree with latest state. * @return the process-tree with latest state.
*/ */
public ProcfsBasedProcessTree getProcessTree() { public ProcfsBasedProcessTree getProcessTree() {
if (pid != -1) { if (!pid.equals(deadPid)) {
// Get the list of processes // Get the list of processes
List<Integer> processList = getProcessList(); List<String> processList = getProcessList();
Map<Integer, ProcessInfo> allProcessInfo = new HashMap<Integer, ProcessInfo>(); Map<String, ProcessInfo> allProcessInfo = new HashMap<String, ProcessInfo>();
// cache the processTree to get the age for processes // cache the processTree to get the age for processes
Map<Integer, ProcessInfo> oldProcs = Map<String, ProcessInfo> oldProcs =
new HashMap<Integer, ProcessInfo>(processTree); new HashMap<String, ProcessInfo>(processTree);
processTree.clear(); processTree.clear();
ProcessInfo me = null; ProcessInfo me = null;
for (Integer proc : processList) { for (String proc : processList) {
// Get information for each process // Get information for each process
ProcessInfo pInfo = new ProcessInfo(proc); ProcessInfo pInfo = new ProcessInfo(proc);
if (constructProcessInfo(pInfo, procfsDir) != null) { if (constructProcessInfo(pInfo, procfsDir) != null) {
@ -179,9 +182,9 @@ public class ProcfsBasedProcessTree {
} }
// Add each process to its parent. // Add each process to its parent.
for (Map.Entry<Integer, ProcessInfo> entry : allProcessInfo.entrySet()) { for (Map.Entry<String, ProcessInfo> entry : allProcessInfo.entrySet()) {
Integer pID = entry.getKey(); String pID = entry.getKey();
if (pID != 1) { if (!pID.equals("1")) {
ProcessInfo pInfo = entry.getValue(); ProcessInfo pInfo = entry.getValue();
ProcessInfo parentPInfo = allProcessInfo.get(pInfo.getPpid()); ProcessInfo parentPInfo = allProcessInfo.get(pInfo.getPpid());
if (parentPInfo != null) { if (parentPInfo != null) {
@ -202,7 +205,7 @@ public class ProcfsBasedProcessTree {
} }
// update age values and compute the number of jiffies since last update // update age values and compute the number of jiffies since last update
for (Map.Entry<Integer, ProcessInfo> procs : processTree.entrySet()) { for (Map.Entry<String, ProcessInfo> procs : processTree.entrySet()) {
ProcessInfo oldInfo = oldProcs.get(procs.getKey()); ProcessInfo oldInfo = oldProcs.get(procs.getKey());
if (procs.getValue() != null) { if (procs.getValue() != null) {
procs.getValue().updateJiffy(oldInfo); procs.getValue().updateJiffy(oldInfo);
@ -227,20 +230,22 @@ public class ProcfsBasedProcessTree {
return checkPidPgrpidForMatch(pid, PROCFS); return checkPidPgrpidForMatch(pid, PROCFS);
} }
public static boolean checkPidPgrpidForMatch(int _pid, String procfs) { public static boolean checkPidPgrpidForMatch(String _pid, String procfs) {
// Get information for this process // Get information for this process
ProcessInfo pInfo = new ProcessInfo(_pid); ProcessInfo pInfo = new ProcessInfo(_pid);
pInfo = constructProcessInfo(pInfo, procfs); pInfo = constructProcessInfo(pInfo, procfs);
// null if process group leader finished execution; issue no warning // null if process group leader finished execution; issue no warning
// make sure that pid and its pgrpId match // make sure that pid and its pgrpId match
return pInfo == null || pInfo.getPgrpId().equals(_pid); if (pInfo == null) return true;
String pgrpId = pInfo.getPgrpId().toString();
return pgrpId.equals(_pid);
} }
private static final String PROCESSTREE_DUMP_FORMAT = private static final String PROCESSTREE_DUMP_FORMAT =
"\t|- %d %d %d %d %s %d %d %d %d %s\n"; "\t|- %s %s %d %d %s %d %d %d %d %s\n";
public List<Integer> getCurrentProcessIDs() { public List<String> getCurrentProcessIDs() {
List<Integer> currentPIDs = new ArrayList<Integer>(); List<String> currentPIDs = new ArrayList<String>();
currentPIDs.addAll(processTree.keySet()); currentPIDs.addAll(processTree.keySet());
return currentPIDs; return currentPIDs;
} }
@ -354,34 +359,27 @@ public class ProcfsBasedProcessTree {
return cpuTime; return cpuTime;
} }
private static Integer getValidPID(String pid) { private static String getValidPID(String pid) {
Integer retPid = -1; if (pid == null) return deadPid;
try { Matcher m = numberPattern.matcher(pid);
retPid = Integer.parseInt(pid); if (m.matches()) return pid;
if (retPid <= 0) { return deadPid;
retPid = -1;
}
} catch (NumberFormatException nfe) {
retPid = -1;
}
return retPid;
} }
/** /**
* Get the list of all processes in the system. * Get the list of all processes in the system.
*/ */
private List<Integer> getProcessList() { private List<String> getProcessList() {
String[] processDirs = (new File(procfsDir)).list(); String[] processDirs = (new File(procfsDir)).list();
List<Integer> processList = new ArrayList<Integer>(); List<String> processList = new ArrayList<String>();
for (String dir : processDirs) { for (String dir : processDirs) {
Matcher m = numberPattern.matcher(dir);
if (!m.matches()) continue;
try { try {
int pd = Integer.parseInt(dir);
if ((new File(procfsDir, dir)).isDirectory()) { if ((new File(procfsDir, dir)).isDirectory()) {
processList.add(Integer.valueOf(pd)); processList.add(dir);
} }
} catch (NumberFormatException n) {
// skip this directory
} catch (SecurityException s) { } catch (SecurityException s) {
// skip this process // skip this process
} }
@ -407,7 +405,7 @@ public class ProcfsBasedProcessTree {
BufferedReader in = null; BufferedReader in = null;
FileReader fReader = null; FileReader fReader = null;
try { try {
File pidDir = new File(procfsDir, String.valueOf(pinfo.getPid())); File pidDir = new File(procfsDir, pinfo.getPid());
fReader = new FileReader(new File(pidDir, PROCFS_STAT_FILE)); fReader = new FileReader(new File(pidDir, PROCFS_STAT_FILE));
in = new BufferedReader(fReader); in = new BufferedReader(fReader);
} catch (FileNotFoundException f) { } catch (FileNotFoundException f) {
@ -424,9 +422,9 @@ public class ProcfsBasedProcessTree {
boolean mat = m.find(); boolean mat = m.find();
if (mat) { if (mat) {
// Set (name) (ppid) (pgrpId) (session) (utime) (stime) (vsize) (rss) // Set (name) (ppid) (pgrpId) (session) (utime) (stime) (vsize) (rss)
pinfo.updateProcessInfo(m.group(2), Integer.parseInt(m.group(3)), pinfo.updateProcessInfo(m.group(2), m.group(3),
Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)), Integer.parseInt(m.group(4)), Integer.parseInt(m.group(5)),
Long.parseLong(m.group(7)), Long.parseLong(m.group(8)), Long.parseLong(m.group(7)), new BigInteger(m.group(8)),
Long.parseLong(m.group(10)), Long.parseLong(m.group(11))); Long.parseLong(m.group(10)), Long.parseLong(m.group(11)));
} else { } else {
LOG.warn("Unexpected: procfs stat file is not in the expected format" LOG.warn("Unexpected: procfs stat file is not in the expected format"
@ -458,7 +456,7 @@ public class ProcfsBasedProcessTree {
*/ */
public String toString() { public String toString() {
StringBuffer pTree = new StringBuffer("[ "); StringBuffer pTree = new StringBuffer("[ ");
for (Integer p : processTree.keySet()) { for (String p : processTree.keySet()) {
pTree.append(p); pTree.append(p);
pTree.append(" "); pTree.append(" ");
} }
@ -471,15 +469,16 @@ public class ProcfsBasedProcessTree {
* *
*/ */
private static class ProcessInfo { private static class ProcessInfo {
private Integer pid; // process-id private String pid; // process-id
private String name; // command name private String name; // command name
private Integer pgrpId; // process group-id private Integer pgrpId; // process group-id
private Integer ppid; // parent process-id private String ppid; // parent process-id
private Integer sessionId; // session-id private Integer sessionId; // session-id
private Long vmem; // virtual memory usage private Long vmem; // virtual memory usage
private Long rssmemPage; // rss memory usage in # of pages private Long rssmemPage; // rss memory usage in # of pages
private Long utime = 0L; // # of jiffies in user mode private Long utime = 0L; // # of jiffies in user mode
private Long stime = 0L; // # of jiffies in kernel mode private final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
private BigInteger stime = new BigInteger("0"); // # of jiffies in kernel mode
// how many times has this process been seen alive // how many times has this process been seen alive
private int age; private int age;
@ -491,13 +490,13 @@ public class ProcfsBasedProcessTree {
private List<ProcessInfo> children = new ArrayList<ProcessInfo>(); // list of children private List<ProcessInfo> children = new ArrayList<ProcessInfo>(); // list of children
public ProcessInfo(int pid) { public ProcessInfo(String pid) {
this.pid = Integer.valueOf(pid); this.pid = pid;
// seeing this the first time. // seeing this the first time.
this.age = 1; this.age = 1;
} }
public Integer getPid() { public String getPid() {
return pid; return pid;
} }
@ -509,7 +508,7 @@ public class ProcfsBasedProcessTree {
return pgrpId; return pgrpId;
} }
public Integer getPpid() { public String getPpid() {
return ppid; return ppid;
} }
@ -525,7 +524,7 @@ public class ProcfsBasedProcessTree {
return utime; return utime;
} }
public Long getStime() { public BigInteger getStime() {
return stime; return stime;
} }
@ -548,8 +547,8 @@ public class ProcfsBasedProcessTree {
return false; return false;
} }
public void updateProcessInfo(String name, Integer ppid, Integer pgrpId, public void updateProcessInfo(String name, String ppid, Integer pgrpId,
Integer sessionId, Long utime, Long stime, Long vmem, Long rssmem) { Integer sessionId, Long utime, BigInteger stime, Long vmem, Long rssmem) {
this.name = name; this.name = name;
this.ppid = ppid; this.ppid = ppid;
this.pgrpId = pgrpId; this.pgrpId = pgrpId;
@ -561,8 +560,19 @@ public class ProcfsBasedProcessTree {
} }
public void updateJiffy(ProcessInfo oldInfo) { public void updateJiffy(ProcessInfo oldInfo) {
this.dtime = (oldInfo == null ? this.utime + this.stime if (oldInfo == null) {
: (this.utime + this.stime) - (oldInfo.utime + oldInfo.stime)); BigInteger sum = this.stime.add(BigInteger.valueOf(this.utime));
if (sum.compareTo(MAX_LONG) > 0) {
this.dtime = 0L;
LOG.warn("Sum of stime (" + this.stime + ") and utime (" + this.utime
+ ") is greater than " + Long.MAX_VALUE);
} else {
this.dtime = sum.longValue();
}
return;
}
this.dtime = (this.utime - oldInfo.utime +
this.stime.subtract(oldInfo.stime).longValue());
} }
public void updateAge(ProcessInfo oldInfo) { public void updateAge(ProcessInfo oldInfo) {

View File

@ -527,7 +527,7 @@ public class TestProcfsBasedProcessTree {
// Let us not create stat file for pid 100. // Let us not create stat file for pid 100.
Assert.assertTrue(ProcfsBasedProcessTree.checkPidPgrpidForMatch( Assert.assertTrue(ProcfsBasedProcessTree.checkPidPgrpidForMatch(
Integer.valueOf(pid), procfsRootDir.getAbsolutePath())); pid, procfsRootDir.getAbsolutePath()));
} finally { } finally {
FileUtil.fullyDelete(procfsRootDir); FileUtil.fullyDelete(procfsRootDir);
} }
@ -662,8 +662,8 @@ public class TestProcfsBasedProcessTree {
*/ */
private static boolean isAnyProcessInTreeAlive( private static boolean isAnyProcessInTreeAlive(
ProcfsBasedProcessTree processTree) { ProcfsBasedProcessTree processTree) {
for (Integer pId : processTree.getCurrentProcessIDs()) { for (String pId : processTree.getCurrentProcessIDs()) {
if (isAlive(pId.toString())) { if (isAlive(pId)) {
return true; return true;
} }
} }