diff options
11 files changed, 361 insertions, 341 deletions
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/ChannelTCP.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/ChannelTCP.java index d4918858f..20ac6cb87 100644 --- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/ChannelTCP.java +++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/core/ChannelTCP.java @@ -60,7 +60,7 @@ public class ChannelTCP extends StreamChannel { out = new BufferedOutputStream(socket.getOutputStream()); onSocketConnected(null); } - catch (final Exception x) { + catch (Exception x) { onSocketConnected(x); } } @@ -85,7 +85,10 @@ public class ChannelTCP extends StreamChannel { private void onSocketConnected(final Throwable x) { Protocol.invokeLater(new Runnable() { public void run() { - if (x != null) terminate(x); + if (x != null) { + terminate(x); + closed = true; + } if (closed) { try { if (socket != null) { diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/IProcesses.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/IProcesses.java index b8d530e82..bf9b49fc1 100644 --- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/IProcesses.java +++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/services/IProcesses.java @@ -199,6 +199,7 @@ public interface IProcesses extends IService { /** * Get list of signals that can be send to the process. + * @param context_id - process context ID or null. * @param done - call back interface called when operation is completed. * @return pending command handle, can be used to cancel the command. */ diff --git a/plugins/org.eclipse.tm.tcf.rse/META-INF/MANIFEST.MF b/plugins/org.eclipse.tm.tcf.rse/META-INF/MANIFEST.MF index 9a25d6f85..1c05bdb64 100644 --- a/plugins/org.eclipse.tm.tcf.rse/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.tm.tcf.rse/META-INF/MANIFEST.MF @@ -12,7 +12,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.rse.services, org.eclipse.ui.views, org.eclipse.rse.subsystems.files.core, - org.eclipse.rse.subsystems.processes.core + org.eclipse.rse.subsystems.processes.core, + org.eclipse.rse.processes.ui Import-package: org.eclipse.tm.tcf.core;version="0.2.0", org.eclipse.tm.tcf.protocol;version="0.2.0", org.eclipse.tm.tcf.services;version="0.2.0", diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/TCFConnectorService.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/TCFConnectorService.java index e272e1206..79c7ab469 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/TCFConnectorService.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/TCFConnectorService.java @@ -25,6 +25,7 @@ import org.eclipse.rse.core.subsystems.CommunicationsEvent; import org.eclipse.tm.tcf.core.AbstractPeer; import org.eclipse.tm.tcf.protocol.IChannel; import org.eclipse.tm.tcf.protocol.IPeer; +import org.eclipse.tm.tcf.protocol.IService; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IFileSystem; import org.eclipse.tm.tcf.services.ILocator; @@ -209,18 +210,19 @@ public class TCFConnectorService extends BasicConnectorService { if (channel.getState() == IChannel.STATE_OPEN) channel.close(); return false; } - - public ISysMonitor getSysMonitorService() { + + public <V extends IService> V getService(Class<V> service_interface) { if (channel == null || channel.getState() != IChannel.STATE_OPEN) throw new Error("Not connected"); //$NON-NLS-1$ - ISysMonitor m = channel.getRemoteService(ISysMonitor.class); - if (m == null) throw new Error("Remote peer does not support SysMonitor service"); //$NON-NLS-1$ + V m = channel.getRemoteService(service_interface); + if (m == null) throw new Error("Remote peer does not support " + service_interface.getName() + " service"); //$NON-NLS-1$ //$NON-NLS-2$ return m; } + public ISysMonitor getSysMonitorService() { + return getService(ISysMonitor.class); + } + public IFileSystem getFileSystemService() { - if (channel == null || channel.getState() != IChannel.STATE_OPEN) throw new Error("Not connected"); //$NON-NLS-1$ - IFileSystem m = channel.getRemoteService(IFileSystem.class); - if (m == null) throw new Error("Remote peer does not support FileSystem service"); //$NON-NLS-1$ - return m; + return getService(IFileSystem.class); } } diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileResource.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileResource.java index e1a5438d7..26801151d 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileResource.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileResource.java @@ -143,6 +143,5 @@ public class TCFFileResource extends AbstractResource implements IHostFile, IHos public void setPermissions(IHostFilePermissions permissions) { this.permissions = permissions; - } } diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileService.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileService.java index 1af8c5fe8..bdcdfe4d6 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileService.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/files/TCFFileService.java @@ -326,7 +326,7 @@ public class TCFFileService extends AbstractFileService { // the entry is a broken symbolic link } else if (e.attrs.isDirectory()) { - //dont filter folder names if getting both folders and files + // dont filter folder names if getting both folders and files if (wantFolders && (matcher==null || fileType==FILE_TYPE_FILES_AND_FOLDERS || matcher.matches(e.filename))) { results.add(new TCFFileResource(TCFFileService.this, path, e.filename, e.attrs, false)); @@ -368,8 +368,7 @@ public class TCFFileService extends AbstractFileService { final IFileHandle handle = new TCFRSETask<IFileHandle>() { public void run() { IFileSystem fs = connector.getFileSystemService(); - fs.open(path, IFileSystem.TCF_O_READ, null, - new IFileSystem.DoneOpen() { + fs.open(path, IFileSystem.TCF_O_READ, null, new IFileSystem.DoneOpen() { public void doneOpen(IToken token, FileSystemException error, IFileHandle handle) { if (error != null) error(error); else done(handle); @@ -387,8 +386,7 @@ public class TCFFileService extends AbstractFileService { final IFileHandle handle = new TCFRSETask<IFileHandle>() { public void run() { IFileSystem fs = connector.getFileSystemService(); - int flags = IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_CREAT - | IFileSystem.TCF_O_TRUNC; + int flags = IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_CREAT | IFileSystem.TCF_O_TRUNC; fs.open(path, flags, null, new IFileSystem.DoneOpen() { public void doneOpen(IToken token, FileSystemException error, IFileHandle handle) { if (error != null) error(error); diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessAdapter.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessAdapter.java index 2f519f271..0d4de7704 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessAdapter.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessAdapter.java @@ -36,7 +36,7 @@ public class TCFProcessAdapter implements IHostProcessToRemoteProcessAdapter { List<IRemoteProcess> list = new ArrayList<IRemoteProcess>(nodes.length); for (int idx = 0; idx < nodes.length; idx++) { TCFProcessResource node = (TCFProcessResource)nodes[idx]; - list.add(new TCFRemoteProcess(context, node)); + if (node != null) list.add(new TCFRemoteProcess(context, node)); } return list.toArray(new IRemoteProcess[list.size()]); } diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessResource.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessResource.java index 0304a139d..c9b595c98 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessResource.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessResource.java @@ -13,11 +13,12 @@ package org.eclipse.tm.internal.tcf.rse.processes; import java.math.BigInteger; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.eclipse.rse.core.subsystems.AbstractResource; import org.eclipse.rse.services.clientserver.IServiceConstants; @@ -28,60 +29,29 @@ import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.ISysMonitor; import org.eclipse.tm.tcf.services.ISysMonitor.SysMonitorContext; -public class TCFProcessResource extends AbstractResource implements - IHostProcess { +public class TCFProcessResource extends AbstractResource implements IHostProcess { - private final TCFProcessService rse_service; + public static final String PROP_PC_UTIME = "PCUTime"; //$NON-NLS-1$ + public static final String PROP_PC_STIME = "PCSTime"; //$NON-NLS-1$ + private final TCFProcessService rse_service; private final ISysMonitor tcf_service; - private final TCFProcessResource prev; - private final String id; private Throwable error; - private ISysMonitor.SysMonitorContext context; private final List<Runnable> children_wait_list = new ArrayList<Runnable>(); - + private final HashMap<String,TCFProcessResource> children = new HashMap<String,TCFProcessResource>(); private boolean children_loading; - private boolean children_loaded; - private Throwable children_error; - private boolean running_wait_list; - private long gid = -1; - - private String name; - - private long ppid = -1; - - private long pid = -1; - - private String state; - - private long tgid = -1; - - private long tracepid = -1; - - private long uid; - - private String username; - - private long vm_rss_kb; - - private long vm_size_kb; - - private String utime_pc; - - private String stime_pc; - private long timestamp; - private String[] propertyKeys = new String[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_COUNT+1]; + private final String[] propertyKeys = new String[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_COUNT]; { propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_INDEX_EXENAME] = ISysMonitor.PROP_FILE; propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_INDEX_GID] = ISysMonitor.PROP_GROUPNAME; @@ -94,18 +64,10 @@ public class TCFProcessResource extends AbstractResource implements propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_INDEX_USERNAME] = ISysMonitor.PROP_USERNAME; propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_INDEX_VMSIZE] = ISysMonitor.PROP_VSIZE; propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_INDEX_VMRSS] = ISysMonitor.PROP_RSS; - propertyKeys[ISystemProcessRemoteConstants.PROCESS_ATTRIBUTES_COUNT] = " "; //set the label //$NON-NLS-1$ } private Map<String, Object> properties = new HashMap<String, Object>(); - private static final NumberFormat percent_format; - - static { - percent_format = NumberFormat.getPercentInstance(); - percent_format.setMaximumFractionDigits(3); - } - TCFProcessResource(TCFProcessService rse_service, ISysMonitor service, TCFProcessResource prev, String id) { this.rse_service = rse_service; @@ -119,7 +81,7 @@ public class TCFProcessResource extends AbstractResource implements } public String getParentID() { - return (String) properties.get(ISysMonitor.PROP_PARENTID); + return (String)properties.get(ISysMonitor.PROP_PARENTID); } public TCFProcessService getService() { @@ -138,57 +100,69 @@ public class TCFProcessResource extends AbstractResource implements if (context != null) return true; tcf_service.getContext(id, new ISysMonitor.DoneGetContext() { - public void doneGetContext(IToken token, Exception error, - SysMonitorContext context) { + public void doneGetContext(IToken token, Exception error, SysMonitorContext context) { TCFProcessResource.this.error = error; TCFProcessResource.this.context = context; + timestamp = System.currentTimeMillis(); if (error != null) { - properties = new HashMap<String, Object>(); - gid = -1; - name = null; - ppid = -1; - pid = -1; - state = null; - tgid = -1; - tracepid = -1; - uid = 0; - username = null; - vm_rss_kb = 0; - vm_size_kb = 0; + properties = new HashMap<String,Object>(); } else { - properties = new HashMap<String, Object>(context - .getProperties()); - gid = context.getUGID(); - name = context.getFile(); - if (properties.containsKey(ISysMonitor.PROP_PPID)) { - ppid = context.getPPID(); - } - pid = context.getPID(); - state = context.getState(); - tgid = context.getTGID(); - if (properties.containsKey(ISysMonitor.PROP_TRACERPID)) { - tracepid = context.getTracerPID(); + properties = new HashMap<String,Object>(context.getProperties()); + if (prev != null && timestamp > prev.timestamp) { + setPCProperty(PROP_PC_UTIME, ISysMonitor.PROP_UTIME); + setPCProperty(PROP_PC_STIME, ISysMonitor.PROP_STIME); } - uid = context.getUID(); - username = context.getUserName(); - vm_rss_kb = context.getRSS(); - long page_bytes = context.getPSize(); - if (page_bytes <= 0 || vm_rss_kb < 0) { - vm_rss_kb = -1; - } - else { - vm_rss_kb = (vm_rss_kb * page_bytes + 1023) / 1024; - } - vm_size_kb = (context.getVSize() + 1023) / 1024; + // Conversions are necessary for sorting to work + toLong(ISysMonitor.PROP_PID); + toLong(ISysMonitor.PROP_PPID); + toLong(ISysMonitor.PROP_UTIME); + toLong(ISysMonitor.PROP_STIME); + toLong(ISysMonitor.PROP_CUTIME); + toLong(ISysMonitor.PROP_CSTIME); + toLong(ISysMonitor.PROP_STARTTIME); + toLong(ISysMonitor.PROP_ITREALVALUE); + toBigInteger(ISysMonitor.PROP_CODESTART); + toBigInteger(ISysMonitor.PROP_CODEEND); + toBigInteger(ISysMonitor.PROP_STACKSTART); + toBigInteger(ISysMonitor.PROP_WCHAN); } - timestamp = System.currentTimeMillis(); Protocol.invokeLater(done); } }); return false; } + + private void toLong(String name) { + Number n = (Number)properties.get(name); + if (n == null || n instanceof Long) return; + properties.put(name, Long.valueOf(n.longValue())); + } + + private void toBigInteger(String name) { + Number n = (Number)properties.get(name); + if (n == null || n instanceof BigInteger) return; + properties.put(name, new BigInteger(n.toString())); + } + + private void setPCProperty(String property, String name) { + Object x = prev.properties.get(name); + Object y = properties.get(name); + if (x instanceof Number && y instanceof Number) { + BigInteger nx = x instanceof BigInteger ? (BigInteger) x + : new BigInteger(x.toString()); + BigInteger ny = y instanceof BigInteger ? (BigInteger) y + : new BigInteger(y.toString()); + double d = ny.subtract(nx).doubleValue() + / (timestamp - prev.timestamp); + properties.put(property, d); + } + } + + public long getTimestamp() { + return timestamp; + } public Throwable getError() { assert Protocol.isDispatchThread(); @@ -213,51 +187,68 @@ public class TCFProcessResource extends AbstractResource implements } public long getGid() { - return gid; + Number n = (Number)properties.get(ISysMonitor.PROP_UGID); + if (n == null) return -1; + return n.longValue(); } public String getLabel() { - return Long.toString(getPid()) + " " + name; //$NON-NLS-1$ + return Long.toString(getPid()) + " " + getName(); //$NON-NLS-1$ } public String getName() { - return name; + return (String)properties.get(ISysMonitor.PROP_FILE); } public long getPPid() { - return ppid; + Number n = (Number)properties.get(ISysMonitor.PROP_PPID); + if (n == null) return -1; + return n.longValue(); } public long getPid() { - return pid; + Number n = (Number)properties.get(ISysMonitor.PROP_PID); + if (n == null) return -1; + return n.longValue(); } public String getState() { - return state; + return (String)properties.get(ISysMonitor.PROP_STATE); } public long getTgid() { - return tgid; + Number n = (Number)properties.get(ISysMonitor.PROP_TGID); + if (n == null) return -1; + return n.longValue(); } public long getTracerPid() { - return tracepid; + Number n = (Number)properties.get(ISysMonitor.PROP_TRACERPID); + if (n == null) return -1; + return n.longValue(); } public long getUid() { - return uid; + Number n = (Number)properties.get(ISysMonitor.PROP_UID); + if (n == null) return -1; + return n.longValue(); } public String getUsername() { - return username; + return (String)properties.get(ISysMonitor.PROP_USERNAME); } public long getVmRSSInKB() { - return vm_rss_kb; + Number rss = (Number)properties.get(ISysMonitor.PROP_RSS); + Number psz = (Number)properties.get(ISysMonitor.PROP_PSIZE); + if (rss == null || psz == null) return -1; + return (rss.longValue() * psz.longValue() + 1023) / 1024; } public long getVmSizeInKB() { - return vm_size_kb; + Number vsz = (Number)properties.get(ISysMonitor.PROP_VSIZE); + if (vsz == null) return -1; + return (vsz.longValue() + 1023) / 1024; } public boolean isRoot() { @@ -268,7 +259,7 @@ public class TCFProcessResource extends AbstractResource implements final String STATUS_DELIMITER = "|"; //$NON-NLS-1$ StringBuffer s = new StringBuffer(); s.append(getPid()).append(STATUS_DELIMITER); - s.append(name).append(STATUS_DELIMITER); + s.append(getName()).append(STATUS_DELIMITER); s.append(getState()).append(STATUS_DELIMITER); s.append(getTgid()).append(STATUS_DELIMITER); s.append(getPPid()).append(STATUS_DELIMITER); @@ -281,83 +272,99 @@ public class TCFProcessResource extends AbstractResource implements return s.toString(); } - public Map<String, Object> getProperties() { + public Map<String,Object> getProperties() { return properties; } - private String getTimePC(String name) { - if (prev == null) return null; - Object x = prev.properties.get(name); - Object y = properties.get(name); - if (x instanceof Number && y instanceof Number) { - BigInteger nx = x instanceof BigInteger ? (BigInteger) x - : new BigInteger(x.toString()); - BigInteger ny = y instanceof BigInteger ? (BigInteger) y - : new BigInteger(y.toString()); - double d = ny.subtract(nx).doubleValue() - / (timestamp - prev.timestamp); - return percent_format.format(d); + private void runChildrenWaitList() { + assert !children_loading; + assert children_loaded; + try { + running_wait_list = true; + for (Runnable r : children_wait_list) r.run(); + children_wait_list.clear(); + } + finally { + running_wait_list = false; } - return null; - } - - public String getUserTimePC() { - if (utime_pc != null) return utime_pc; - return utime_pc = getTimePC(ISysMonitor.PROP_UTIME); - } - - public String getSysTimePC() { - if (stime_pc != null) return stime_pc; - return stime_pc = getTimePC(ISysMonitor.PROP_STIME); - } - - public boolean getChildrenLoading() { - return children_loading; - } - - public void setChildrenLoading(boolean b) { - children_loading = b; - } - - public boolean getChildrenLoaded() { - return children_loaded; - } - - public void setChildrenLoaded(boolean b) { - children_loaded = b; } - + public Throwable getChildrenError() { return children_error; } - - public void setChildrenError(Throwable error) { - children_error = error; + + public void flushChildrenCache() { + Map<Long,TCFProcessResource> pid2res = rse_service.getProcessCache(); + for (TCFProcessResource r : children.values()) { + long pid = r.getPid(); + if (pid > 0 && getPid() != pid) pid2res.remove(r.getPid()); + } + children_loaded = false; + children_error = null; } - public void addChildrenWaitList(Runnable run) { + public boolean loadChildren(Runnable run) { + if (children_loaded) return true; assert !running_wait_list; - assert children_loading; - assert !children_loaded; children_wait_list.add(run); - } - - public void runChildrenWaitList() { - assert !children_loading; - assert children_loaded; + if (children_loading) return false; + children_loading = true; try { - running_wait_list = true; - for (Runnable r : children_wait_list) - r.run(); - children_wait_list.clear(); + final ISysMonitor m = rse_service.getTCFConnectorService().getSysMonitorService(); + m.getChildren(getID(), new ISysMonitor.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] ids) { + try { + if (error != null) { + loadProcessesDone(error, null); + } + else if (ids == null) { + loadProcessesDone(null, new TCFProcessResource[0]); + } + else { + final TCFProcessResource[] arr = new TCFProcessResource[ids.length]; + final Set<IHostProcess> pending = new HashSet<IHostProcess>(); + for (int i = 0; i < ids.length; i++) { + final TCFProcessResource r = new TCFProcessResource( + rse_service, m, children.get(ids[i]), ids[i]); + if (!r.validate(new Runnable() { + public void run() { + pending.remove(r); + if (pending.isEmpty()) loadProcessesDone(null, arr); + } + })) pending.add(r); + arr[i] = r; + } + if (pending.isEmpty()) loadProcessesDone(null, arr); + } + } + catch (Throwable x) { + loadProcessesDone(x, null); + } + } + }); + return false; } - finally { - running_wait_list = false; + catch (Throwable x) { + loadProcessesDone(x, null); + return true; } } - public void cancelChildrenLoading() { - // TODO: cancelChildrenLoading + private void loadProcessesDone(Throwable error, TCFProcessResource[] arr) { + assert children_loading; + children_loading = false; + children_loaded = true; + children.clear(); + if (arr != null && error == null) { + Map<Long,TCFProcessResource> pid2res = rse_service.getProcessCache(); + for (TCFProcessResource r : arr) { + long pid = r.getPid(); + if (pid > 0 && getPid() != pid) pid2res.put(pid, r); + if (r.getError() == null) children.put(r.getID(), r); + } + } + children_error = error; + runChildrenWaitList(); } @Override diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessService.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessService.java index dca42a95e..2b12b1abe 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessService.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFProcessService.java @@ -15,13 +15,11 @@ package org.eclipse.tm.internal.tcf.rse.processes; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.rse.core.model.IHost; @@ -29,6 +27,7 @@ import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.clientserver.processes.HostProcessFilterImpl; import org.eclipse.rse.services.clientserver.processes.IHostProcess; import org.eclipse.rse.services.clientserver.processes.IHostProcessFilter; +import org.eclipse.rse.services.clientserver.processes.ISystemProcessRemoteConstants; import org.eclipse.rse.services.processes.AbstractProcessService; import org.eclipse.rse.services.processes.IProcessService; import org.eclipse.tm.internal.tcf.rse.ITCFSubSystem; @@ -36,22 +35,26 @@ import org.eclipse.tm.internal.tcf.rse.TCFConnectorService; import org.eclipse.tm.internal.tcf.rse.TCFConnectorServiceManager; import org.eclipse.tm.internal.tcf.rse.TCFRSETask; import org.eclipse.tm.tcf.protocol.IToken; -import org.eclipse.tm.tcf.services.ISysMonitor; +import org.eclipse.tm.tcf.services.IProcesses; -public class TCFProcessService extends AbstractProcessService implements - IProcessService { +public class TCFProcessService extends AbstractProcessService implements IProcessService { private final TCFConnectorService connector; private final TCFProcessResource root; - private final Map<String,TCFProcessResource> id2res = new HashMap<String,TCFProcessResource>(); private final Map<Long,TCFProcessResource> pid2res = new HashMap<Long,TCFProcessResource>(); + private final Map<String,Long> signals = new HashMap<String,Long>(); + private final List<Runnable> get_signals_wait_list = new ArrayList<Runnable>(); public TCFProcessService(IHost host) { connector = (TCFConnectorService)TCFConnectorServiceManager .getInstance().getConnectorService(host, ITCFSubSystem.class); root = new TCFProcessResource(this, null, null, null); } + + public TCFConnectorService getTCFConnectorService() { + return connector; + } @Override public String getDescription() { @@ -65,35 +68,91 @@ public class TCFProcessService extends AbstractProcessService implements } @Override - public IHostProcess getParentProcess(long PID, IProgressMonitor monitor) - throws SystemMessageException { + public IHostProcess getParentProcess(long PID, IProgressMonitor monitor) throws SystemMessageException { return getProcess(getProcess(PID, monitor).getPPid(), monitor); } @Override - public IHostProcess getProcess(final long PID, IProgressMonitor monitor) - throws SystemMessageException { + public IHostProcess getProcess(final long PID, IProgressMonitor monitor) throws SystemMessageException { return new TCFRSETask<IHostProcess>() { public void run() { - if (!loadProcesses(this, root)) return; + if (!root.loadChildren(this)) return; if (root.getChildrenError() != null) { error(root.getChildrenError()); return; } - done(pid2res.get(Long.valueOf(PID))); + done(pid2res.get(PID)); } }.getS(monitor, "Get process properties"); //$NON-NLS-1$ } public String[] getSignalTypes() { - // TODO Auto-generated method stub - return null; + return new TCFRSETask<String[]>() { + public void run() { + if (signals.isEmpty()) { + if (get_signals_wait_list.contains(this)) { + done(signals.keySet().toArray(new String[signals.size()])); + } + else { + if (get_signals_wait_list.isEmpty()) { + connector.getService(IProcesses.class).getSignalList(null, new IProcesses.DoneGetSignalList() { + public void doneGetSignalList(IToken token, Exception error, Collection<Map<String,Object>> list) { + if (list != null) { + for (Map<String,Object> m : list) { + String name = (String)m.get(IProcesses.SIG_NAME); + Number code = (Number)m.get(IProcesses.SIG_CODE); + if (name != null && code != null) signals.put(name, code.longValue()); + } + } + for (Runnable r : get_signals_wait_list) r.run(); + get_signals_wait_list.clear(); + } + }); + } + get_signals_wait_list.add(this); + } + } + else { + done(signals.keySet().toArray(new String[signals.size()])); + } + } + }.getE(); } - public boolean kill(long PID, String signal, IProgressMonitor monitor) - throws SystemMessageException { - // TODO Auto-generated method stub - return false; + public boolean kill(final long PID, final String signal, IProgressMonitor monitor) throws SystemMessageException { + return new TCFRSETask<Boolean>() { + public void run() { + if (!root.loadChildren(this)) return; + if (root.getChildrenError() != null) { + error(root.getChildrenError()); + return; + } + TCFProcessResource prs = pid2res.get(PID); + if (prs == null) { + done(false); + return; + } + Long signo = signals.get(signal); + if (signal.equals(ISystemProcessRemoteConstants.PROCESS_SIGNAL_TYPE_DEFAULT)) { + if (signo == null) signo = signals.get("SIGTERM"); + if (signo == null) signo = signals.get("SIGKILL"); + } + if (signo == null) { + error(new Exception("Unknown signal: " + signal)); + return; + } + connector.getService(IProcesses.class).signal(prs.getID(), signo.longValue(), new IProcesses.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (error != null) { + error(error); + } + else { + done(true); + } + } + }); + } + }.getS(monitor, "Sending signal to a process"); //$NON-NLS-1$ } private void sort(IHostProcess[] arr) { @@ -125,31 +184,25 @@ public class TCFProcessService extends AbstractProcessService implements } public IHostProcess[] listAllProcesses(final IHostProcessFilter filter, final IHostProcess up, IProgressMonitor monitor) throws SystemMessageException { - // TODO: figure out better way to flush the cache - final TCFProcessResource parent = new TCFRSETask<TCFProcessResource>() { + new TCFRSETask<Boolean>() { public void run() { TCFProcessResource parent = (TCFProcessResource)up; - if (parent == null) { - error(new IOException("Invalid parent")); //$NON-NLS-1$ - return; - } - if (filter.getPpid() != null && filter.getPpid().equals("*") || parent.getChildrenError() != null) { //$NON-NLS-1$ - for (Iterator<TCFProcessResource> i = pid2res.values().iterator(); i.hasNext();) { - TCFProcessResource r = i.next(); - if (eqaulIDs(parent.getID(), r.getParentID())) { - i.remove(); - if (r.getChildrenLoaded()) r.cancelChildrenLoading(); - } + if (parent != null) { + if (filter.getPpid() == null || filter.getPpid().equals("*") || parent.getChildrenError() != null) { //$NON-NLS-1$ + parent.flushChildrenCache(); } - parent.setChildrenLoaded(false); - parent.setChildrenError(null); } - done(parent); + done(true); } - }.getS(monitor, "Flush processes cache"); //$NON-NLS-1$ + }.getE(); return new TCFRSETask<IHostProcess[]>() { public void run() { - if (!loadProcesses(this, parent)) return; + TCFProcessResource parent = (TCFProcessResource)up; + if (parent == null) { + error(new IOException("Invalid parent")); //$NON-NLS-1$ + return; + } + if (!parent.loadChildren(this)) return; if (parent.getChildrenError() != null) { error(parent.getChildrenError()); return; @@ -157,8 +210,7 @@ public class TCFProcessService extends AbstractProcessService implements List<IHostProcess> l = new ArrayList<IHostProcess>(); for (TCFProcessResource p : pid2res.values()) { if (eqaulIDs(parent.getID(), p.getParentID())) { - Throwable error = p.getError(); - if (error == null && filter.allows(p.getStatusLine())) l.add(p); + if (p.getError() == null && filter.allows(p.getStatusLine())) l.add(p); } } IHostProcess[] arr = new IHostProcess[l.size()]; @@ -193,82 +245,13 @@ public class TCFProcessService extends AbstractProcessService implements } @Override - public IHostProcess[] listRootProcesses(IProgressMonitor monitor) - throws SystemMessageException { + public IHostProcess[] listRootProcesses(IProgressMonitor monitor) throws SystemMessageException { IHostProcess[] roots = new IHostProcess[1]; roots[0] = getProcess(1, monitor); return roots; } - - private boolean loadProcesses(Runnable run, final TCFProcessResource parent) { - if (parent.getChildrenLoading()) { - parent.addChildrenWaitList(run); - return false; - } - if (parent.getChildrenLoaded()) { - return true; - } - parent.setChildrenLoading(true); - try { - final ISysMonitor m = connector.getSysMonitorService(); - m.getChildren(parent.getID(), new ISysMonitor.DoneGetChildren() { - public void doneGetChildren(IToken token, Exception error, String[] ids) { - try { - if (error != null) { - loadProcessesDone(parent, error, null); - } - else if (ids == null) { - loadProcessesDone(parent, null, new TCFProcessResource[0]); - } - else { - final TCFProcessResource[] arr = new TCFProcessResource[ids.length]; - final Set<IHostProcess> pending = new HashSet<IHostProcess>(); - for (int i = 0; i < ids.length; i++) { - final TCFProcessResource r = new TCFProcessResource( - TCFProcessService.this, m, id2res.get(ids[i]), ids[i]); - if (!r.validate(new Runnable() { - public void run() { - pending.remove(r); - if (pending.isEmpty()) loadProcessesDone(parent, null, arr); - } - })) pending.add(r); - arr[i] = r; - } - if (pending.isEmpty()) loadProcessesDone(parent, null, arr); - } - } - catch (Throwable x) { - loadProcessesDone(parent, x, null); - } - } - }); - parent.addChildrenWaitList(run); - return false; - } - catch (Throwable x) { - loadProcessesDone(parent, x, null); - return true; - } - } - - private void loadProcessesDone(TCFProcessResource parent, Throwable error, TCFProcessResource[] arr) { - assert parent.getChildrenLoading(); - parent.setChildrenLoading(false); - parent.setChildrenLoaded(true); - if (arr != null && error == null) { - for (TCFProcessResource r : arr) { - long pid = r.getPid(); - if (pid > 0 && parent.getPid() != pid) { - pid2res.put(new Long(pid), r); - id2res.put(r.getID(), r); - } - } - } - for (Iterator<TCFProcessResource> i = id2res.values().iterator(); i.hasNext();) { - TCFProcessResource r = i.next(); - if (pid2res.get(Long.valueOf(r.getPid())) == null) i.remove(); - } - parent.setChildrenError(error); - parent.runChildrenWaitList(); + + Map<Long,TCFProcessResource> getProcessCache() { + return pid2res; } } diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFRemoteProcess.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFRemoteProcess.java index 1e0647acf..30a5f6902 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFRemoteProcess.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFRemoteProcess.java @@ -32,12 +32,4 @@ public class TCFRemoteProcess extends RemoteProcessImpl { public Map<String,Object> getProperties() { return ((TCFProcessResource)_underlyingProcess).getProperties(); } - - public String getUserTimePC() { - return ((TCFProcessResource)_underlyingProcess).getUserTimePC(); - } - - public String getSysTimePC() { - return ((TCFProcessResource)_underlyingProcess).getSysTimePC(); - } } diff --git a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFSystemViewRemoteProcessAdapter.java b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFSystemViewRemoteProcessAdapter.java index 19cbb2a1e..58bb2f215 100644 --- a/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFSystemViewRemoteProcessAdapter.java +++ b/plugins/org.eclipse.tm.tcf.rse/src/org/eclipse/tm/internal/tcf/rse/processes/TCFSystemViewRemoteProcessAdapter.java @@ -12,6 +12,7 @@ package org.eclipse.tm.internal.tcf.rse.processes; import java.math.BigInteger; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; @@ -26,12 +27,14 @@ import org.eclipse.rse.core.model.ISystemResourceSet; import org.eclipse.rse.core.model.SystemMessageObject; import org.eclipse.rse.core.model.SystemRemoteResourceSet; import org.eclipse.rse.core.subsystems.ISubSystem; +import org.eclipse.rse.internal.processes.ui.actions.SystemKillProcessAction; import org.eclipse.rse.services.clientserver.processes.HostProcessFilterImpl; import org.eclipse.rse.services.clientserver.processes.IHostProcess; import org.eclipse.rse.services.clientserver.processes.IHostProcessFilter; import org.eclipse.rse.services.clientserver.processes.ISystemProcessRemoteTypes; import org.eclipse.rse.subsystems.processes.core.subsystem.IRemoteProcess; import org.eclipse.rse.subsystems.processes.core.subsystem.IRemoteProcessSubSystem; +import org.eclipse.rse.ui.ISystemContextMenuConstants; import org.eclipse.rse.ui.ISystemMessages; import org.eclipse.rse.ui.RSEUIPlugin; import org.eclipse.rse.ui.SystemBasePlugin; @@ -54,10 +57,14 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter private SystemCopyToClipboardAction copyClipboardAction; private static final Object[] EMPTY_LIST = new Object[0]; private static IPropertyDescriptor[] properties = null; - //private SystemKillProcessAction killProcessAction; + private SystemKillProcessAction killProcessAction; - private static final String PROP_PC_UTIME = "PCUTime"; //$NON-NLS-1$ - private static final String PROP_PC_STIME = "PCSTime"; //$NON-NLS-1$ + private static final NumberFormat percent_format; + + static { + percent_format = NumberFormat.getPercentInstance(); + percent_format.setMaximumFractionDigits(3); + } @Override public boolean canDrag(Object element) { @@ -82,12 +89,10 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter @Override public void addActions(SystemMenuManager menu, IStructuredSelection selection, Shell parent, String menuGroup) { - /* - if (killProcessAction == null) - killProcessAction = new SystemKillProcessAction(shell); - menu.add(ISystemContextMenuConstants.GROUP_CHANGE, killProcessAction); - */ - + if (killProcessAction == null) { + killProcessAction = new SystemKillProcessAction(getShell()); + } + menu.add(ISystemContextMenuConstants.GROUP_CHANGE, killProcessAction); if (copyClipboardAction == null) { Clipboard clipboard = RSEUIPlugin.getTheSystemRegistryUI().getSystemClipboard(); copyClipboardAction = new SystemCopyToClipboardAction(getShell(), clipboard); @@ -227,8 +232,8 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_STIME, Messages.PROCESS_STIME_LABEL, Messages.PROCESS_STIME_TOOLTIP)); l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_CUTIME, Messages.PROCESS_CUTIME_LABEL, Messages.PROCESS_CUTIME_TOOLTIP)); l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_CSTIME, Messages.PROCESS_CSTIME_LABEL, Messages.PROCESS_CSTIME_TOOLTIP)); - l.add(createSimplePropertyDescriptor(PROP_PC_UTIME, Messages.PROCESS_PC_UTIME_LABEL, Messages.PROCESS_PC_UTIME_TOOLTIP)); - l.add(createSimplePropertyDescriptor(PROP_PC_STIME, Messages.PROCESS_PC_STIME_LABEL, Messages.PROCESS_PC_STIME_TOOLTIP)); + l.add(createSimplePropertyDescriptor(TCFProcessResource.PROP_PC_UTIME, Messages.PROCESS_PC_UTIME_LABEL, Messages.PROCESS_PC_UTIME_TOOLTIP)); + l.add(createSimplePropertyDescriptor(TCFProcessResource.PROP_PC_STIME, Messages.PROCESS_PC_STIME_LABEL, Messages.PROCESS_PC_STIME_TOOLTIP)); l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_PRIORITY, Messages.PROCESS_PRIORITY_LABEL, Messages.PROCESS_PRIORITY_TOOLTIP)); l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_NICE, Messages.PROCESS_NICE_LABEL, Messages.PROCESS_NICE_TOOLTIP)); l.add(createSimplePropertyDescriptor(ISysMonitor.PROP_ITREALVALUE, Messages.PROCESS_ITREALVALUE_LABEL, Messages.PROCESS_ITREALVALUE_TOOLTIP)); @@ -258,8 +263,40 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter * @return the current value of the given property */ @Override - protected Object internalGetPropertyValue(Object key) { - return getPropertyValue(key, true); + protected Object internalGetPropertyValue(Object property) { + Object v = internalGetPropertyValueOrNull(property); + if (v == null) v = ""; + return v; + } + + private Object internalGetPropertyValueOrNull(Object property) { + TCFRemoteProcess process = (TCFRemoteProcess)propertySourceInput; + Object p = process.getProperties().get(property); + if (property.equals(ISysMonitor.PROP_VSIZE)) { + return NLS.bind(Messages.PROCESS_VMSIZE_VALUE, Long.toString(process.getVmSizeInKB())); + } + if (property.equals(ISysMonitor.PROP_RSS)) { + return NLS.bind(Messages.PROCESS_VMRSS_VALUE, Long.toString(process.getVmRSSInKB())); + } + if (property.equals(ISysMonitor.PROP_SIGNALS)) return formatBitSet(p); + if (property.equals(ISysMonitor.PROP_SIGBLOCK)) return formatBitSet(p); + if (property.equals(ISysMonitor.PROP_SIGCATCH)) return formatBitSet(p); + if (property.equals(ISysMonitor.PROP_SIGIGNORE)) return formatBitSet(p); + if (property.equals(ISysMonitor.PROP_CODESTART)) return formatHex(p); + if (property.equals(ISysMonitor.PROP_CODEEND)) return formatHex(p); + if (property.equals(ISysMonitor.PROP_STACKSTART)) return formatHex(p); + if (property.equals(ISysMonitor.PROP_WCHAN)) return formatHex(p); + if (property.equals(ISysMonitor.PROP_FLAGS)) return formatBitSet(p); + if (property.equals(ISysMonitor.PROP_UTIME)) return formatTime(p); + if (property.equals(ISysMonitor.PROP_STIME)) return formatTime(p); + if (property.equals(ISysMonitor.PROP_CUTIME)) return formatTime(p); + if (property.equals(ISysMonitor.PROP_CSTIME)) return formatTime(p); + if (property.equals(ISysMonitor.PROP_STARTTIME)) return formatTime(p); + if (property.equals(ISysMonitor.PROP_ITREALVALUE)) return formatTime(p); + if (property.equals(TCFProcessResource.PROP_PC_UTIME)) return formatPercent(p); + if (property.equals(TCFProcessResource.PROP_PC_STIME)) return formatPercent(p); + if (p != null) return p.toString(); + return null; } /** @@ -271,42 +308,38 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter */ @Override public Object getPropertyValue(Object property, boolean formatted) { - String name = (String)property; + if (formatted) return getPropertyValue(property); + TCFRemoteProcess process = (TCFRemoteProcess)propertySourceInput; Object p = process.getProperties().get(property); - - if (formatted) { - if (name.equals(ISysMonitor.PROP_VSIZE)) { - return NLS.bind(Messages.PROCESS_VMSIZE_VALUE, Long - .toString(process.getVmSizeInKB())); - } - if (name.equals(ISysMonitor.PROP_RSS)) { - return NLS.bind(Messages.PROCESS_VMRSS_VALUE, Long - .toString(process.getVmRSSInKB())); - } - if (name.equals(ISysMonitor.PROP_SIGNALS))return formatBitSet(p); - if (name.equals(ISysMonitor.PROP_SIGBLOCK)) return formatBitSet(p); - if (name.equals(ISysMonitor.PROP_SIGCATCH)) return formatBitSet(p); - if (name.equals(ISysMonitor.PROP_SIGIGNORE)) return formatBitSet(p); - if (name.equals(ISysMonitor.PROP_CODESTART)) return formatHex(p); - if (name.equals(ISysMonitor.PROP_CODEEND)) return formatHex(p); - if (name.equals(ISysMonitor.PROP_STACKSTART)) return formatHex(p); - if (name.equals(ISysMonitor.PROP_WCHAN)) return formatHex(p); - if (name.equals(ISysMonitor.PROP_FLAGS)) return formatBitSet(p); - if (name.equals(ISysMonitor.PROP_UTIME)) return formatTime(p); - if (name.equals(ISysMonitor.PROP_STIME)) return formatTime(p); - if (name.equals(ISysMonitor.PROP_CUTIME)) return formatTime(p); - if (name.equals(ISysMonitor.PROP_CSTIME)) return formatTime(p); - if (name.equals(ISysMonitor.PROP_STARTTIME)) return formatTime(p); - if (name.equals(ISysMonitor.PROP_ITREALVALUE)) return formatTime(p); - if (name.equals(PROP_PC_UTIME)) return process.getUserTimePC(); - if (name.equals(PROP_PC_STIME)) return process.getSysTimePC(); + if (p == null) { + if (property.equals(ISysMonitor.PROP_PID)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_PPID)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_CODESTART)) return BigInteger.ZERO; + if (property.equals(ISysMonitor.PROP_CODEEND)) return BigInteger.ZERO; + if (property.equals(ISysMonitor.PROP_STACKSTART)) return BigInteger.ZERO; + if (property.equals(ISysMonitor.PROP_WCHAN)) return BigInteger.ZERO; + if (property.equals(ISysMonitor.PROP_UTIME)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_STIME)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_CUTIME)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_CSTIME)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_STARTTIME)) return Long.valueOf(0); + if (property.equals(ISysMonitor.PROP_ITREALVALUE)) return Long.valueOf(0); + if (property.equals(TCFProcessResource.PROP_PC_UTIME)) return Double.valueOf(0); + if (property.equals(TCFProcessResource.PROP_PC_STIME)) return Double.valueOf(0); + if (property.equals(ISysMonitor.PROP_CWD)) return ""; + if (property.equals(ISysMonitor.PROP_FILE)) return ""; } - - if (p == null) return null; - if (formatted) return p.toString(); return p; } + + private String formatPercent(Object o) { + if (o instanceof Number) { + Number n = (Number)o; + return percent_format.format(n.doubleValue()); + } + return null; + } private String formatTime(Object o) { if (o instanceof Number) { @@ -346,7 +379,8 @@ public class TCFSystemViewRemoteProcessAdapter extends AbstractSystemViewAdapter protected String formatHex(Object o) { if (o instanceof Number) { - BigInteger n = new BigInteger(o.toString()); + BigInteger n = o instanceof BigInteger ? + (BigInteger)o : new BigInteger(o.toString()); StringBuffer buf = new StringBuffer(); buf.append("0x"); //$NON-NLS-1$ formatHex(buf, n, 0); |