package com.netifera.platform.host.processes;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import com.netifera.platform.api.log.ILogger;
public class LinuxProcessManager implements IProcessManager {
private ILogger logger;
private static final String managerName = "Process Manager [Linux]";
private final String procPath;
public LinuxProcessManager(ILogger logger) {
this.logger = logger;
File f = new File("/proc");
if(f.isDirectory()) {
procPath = "/proc/";
return;
}
f = new File("/peludo/osfs/proc");
if(f.isDirectory()) {
procPath = "/peludo/osfs/proc/";
} else {
procPath = null;
}
}
private String readLine(String fileName) {
try {
InputStream in = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
try {
return br.readLine();
} catch (IOException exception) {
logger.error("I/O Error", exception);
} finally {
try {
br.close();
} catch (IOException e) {
logger.debug("I/O Error", e);
}
try {
in.close();
} catch (IOException e) {
logger.debug("I/O Error", e);
}
}
} catch (IOException e) {
logger.error("I/O Error", e);
}
return null;
}
private Process getProcess(int pid) {
String name = "?";
int state = 0;
int ppid = 0;
int uid = 0;
String commandLine = "?";
long size = 0;
String stat = readLine(procPath+pid+"/stat");
if (stat != null) {
String[] statArray = stat.split(" ");
name = statArray[1];
String stateString = statArray[2];
if (stateString.equals("R"))
state = Process.RUNNING;
else if (stateString.equals("S"))
state = Process.SLEEPING;
else if (stateString.equals("Z"))
state = Process.ZOMBIE;
ppid = Integer.parseInt(statArray[3]);
size = Long.parseLong(statArray[22]); // FIXME could overflow, this field is %lu
// 13 utime
// 22 vsize
// 23 rss
}
InputStream in = null;
try {
in = new FileInputStream(procPath+pid+"/status");
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
try {
String line;
if ((line = br.readLine()) == null) {
logger.error("can not parse /proc/"+pid+"/status");
return null;
}
name = line.substring(line.indexOf('\t')+1);
if ((line = br.readLine()) == null) {
logger.error("can not parse /proc/"+pid+"/status");
return null;
}
br.readLine(); // skip State
br.readLine(); // skip Tgid
br.readLine(); // skip pid
if ((line = br.readLine()) == null) {
logger.error("can not parse /proc/"+pid+"/status");
return null;
}
// ppid = Integer.parseInt(line.split("\\s")[1]);
br.readLine(); // skip tracer pid
if ((line = br.readLine()) == null) {
logger.error("can not parse /proc/"+pid+"/status");
return null;
}
uid = Integer.parseInt(line.split("\\s")[1]);
} catch (IOException exception) {
logger.error("I/O Error", exception);
} finally {
try {
br.close();
} catch (IOException e) {
logger.debug("I/O Error", e);
}
try {
in.close();
} catch (IOException e) {
logger.debug("I/O Error", e);
}
}
commandLine = readLine(procPath+pid+"/cmdline");
/*
* memory /proc/statm
* memory map /proc/maps
* cwd /proc/cwd
*
*/
return new Process(this, name, state, pid, ppid, uid, commandLine, size);
} catch (FileNotFoundException e) {
logger.error("Process "+pid+" not found");
return null;
}
}
public Process[] getProcessList() {
List<Process> processList = new ArrayList<Process>();
File proc = new File(procPath);
if(!proc.exists()) {
return new Process[0];
}
for (String pid: proc.list())
if (pid.matches("\\d+")) {
Process process = getProcess(Integer.parseInt(pid));
if (process != null)
processList.add(process);
}
return processList.toArray(new Process[processList.size()]);
}
public boolean kill(int pid, int signal) {
try {
java.lang.Process killpid = Runtime.getRuntime().exec(new String[] {"kill","-"+signal, ""+pid});
try {
killpid.waitFor();
return true;
} catch (InterruptedException exception) {
logger.error("Interrupted", exception);
} finally {
killpid.getInputStream().close();
killpid.getErrorStream().close();
killpid.getOutputStream().close();
killpid.destroy();
}
} catch (IOException exception) {
logger.error("I/O Error", exception);
}
return false;
}
public boolean kill(int pid) {
return kill(pid, 9);
}
@Override
public String toString() {
return managerName;
}
}