* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Alvaro Sanchez-Leon (alvsan09@gmail.com) - Initial API and implementation
+ * Alvaro Sanchez-Leon - Initial API and implementation
+ * Michel Dagenais (michel.dagenais@polymtl.ca) - Reference C implementation, used with permission
*******************************************************************************/
package org.eclipse.linuxtools.lttng.ui.views.controlflow.model;
-import java.util.Vector;
+import java.util.HashMap;
+import java.util.Iterator;
+import org.eclipse.linuxtools.lttng.core.TraceDebug;
+import org.eclipse.linuxtools.lttng.ui.model.trange.ItemContainer;
import org.eclipse.linuxtools.lttng.ui.model.trange.TimeRangeEventProcess;
/**
- * Common location to allocate the processes in use by the Control flow view
+ * Contains the processes in use by the Control flow view
*
* @author alvaro
*
*/
-public class FlowProcessContainer {
+public class FlowProcessContainer implements ItemContainer<TimeRangeEventProcess> {
// ========================================================================
// Data
// ========================================================================
- private final Vector<TimeRangeEventProcess> processes = new Vector<TimeRangeEventProcess>();
- private int idgen = 0;
-
+ private final HashMap<ProcessKey, TimeRangeEventProcess> allProcesses = new HashMap<ProcessKey, TimeRangeEventProcess>();
+ private static Integer uniqueId = 0;
+
// ========================================================================
// Constructor
// ========================================================================
// Methods
// ========================================================================
/**
- * Interface to add processes.
+ * Interface to add a new process.<p>
+ *
+ * Note : Process with the same key will be overwritten, it's calling function job to make sure the new process is unique.
*
- * @param process
+ * @param newProcess The process to add
*/
- public void addProcesse(TimeRangeEventProcess process) {
- if (process != null) {
- processes.add(process);
+ @Override
+ public void addItem(TimeRangeEventProcess newItem) {
+ if (newItem != null) {
+ allProcesses.put(new ProcessKey(newItem), newItem);
}
}
-
+
/**
- * This method is intended for ready only purposes in order to keep the
- * internal data structure in Synch
- *
- * @return
- */
- public Vector<TimeRangeEventProcess> readProcesses() {
- return processes;
+ * Request a unique ID
+ *
+ * @return Integer
+ */
+ @Override
+ public Integer getUniqueId() {
+ return uniqueId++;
+ }
+
+ /**
+ * This method is intended for read only purposes in order to keep the
+ * internal data structure in synch
+ *
+ * @return TimeRangeEventProcess[]
+ */
+ @Override
+ public TimeRangeEventProcess[] readItems() {
+
+ // This allow us to return an Array of the correct type of the exact correct dimension, without looping
+ return allProcesses.values().toArray(new TimeRangeEventProcess[allProcesses.size()]);
}
-
+
/**
- * Clear the children information for processes related to a specific trace
- * e.g. just before refreshing data with a new time range
- *
- * @param traceId
+ * Clear the children information for processes e.g. just before refreshing
+ * data with a new time range
*/
- public void clearChildren(String traceId) {
- String procTraceId;
- for (TimeRangeEventProcess process : processes) {
- procTraceId = process.getTraceID();
- if (procTraceId.equals(traceId)) {
- process.reset();
- }
- }
+ @Override
+ public void clearChildren() {
+ TimeRangeEventProcess process = null;
+ Iterator<ProcessKey> iterator = allProcesses.keySet().iterator();
+
+ while (iterator.hasNext()) {
+ process = allProcesses.get(iterator.next());
+ process.reset();
+ }
}
-
+
/**
- * remove the processes related to a specific trace e.g. during trace
- * removal
- *
- * @param traceId
- */
- public void removeProcesses(String traceId) {
- String procTraceId;
- for (TimeRangeEventProcess process : processes) {
- procTraceId = process.getTraceID();
- if (procTraceId.equals(traceId)) {
- // Children and traceEvent will get claimed by the garbage collector when process is unreferenced
- // Therefore, we don't need to removed them
- processes.remove(process);
- }
- }
+ * Clear all process items
+ */
+ @Override
+ public void clearItems() {
+ allProcesses.clear();
+ }
+
+ /**
+ * Remove the process related to a specific trace e.g. during trace
+ * removal
+ *
+ * @param traceId The trace unique id (trace name?) on which we want to remove process
+ */
+ @Override
+ public void removeItems(String traceId) {
+ ProcessKey iterKey = null;
+
+ Iterator<ProcessKey> iterator = allProcesses.keySet().iterator();
+ while (iterator.hasNext()) {
+ iterKey = iterator.next();
+
+ if (allProcesses.get(iterKey).getTraceID().equals(traceId)) {
+ allProcesses.remove(iterKey);
+ }
+ }
}
+
+ /**
+ * Search by keys (pid, cpuId, traceId and creationTime)<p>
+ *
+ * A match is returned if the four arguments received match an entry
+ * Otherwise null is returned
+ *
+ * @param searchedPid The processId (Pid) we are looking for
+ * @param searchedCpuId The cpu Id we are looking for
+ * @param searchedTraceID The traceId (trace name?) we are looking for
+ * @param searchedCreationtime The creation time we are looking for
+ *
+ * @return TimeRangeEventProcess
+ */
+ public TimeRangeEventProcess findProcess(Long searchedPid, Long searchedCpuId, String searchedTraceID, Long searchedCreationtime) {
+ // Get the TimeRangeEventProcess associated to a key we create here
+ TimeRangeEventProcess foundProcess = allProcesses.get( new ProcessKey(searchedPid, searchedCpuId, searchedTraceID, searchedCreationtime) );
+
+ return foundProcess;
+ }
+}
- /**
- * A match is returned if the three arguments received match an entry in the
- * Map, otherwise null is returned
- *
- * @param pid
- * @param creationtime
- * @param traceID
- * @return
- */
- public TimeRangeEventProcess findProcess(Long pid, Long creationtime,
- String traceID) {
- TimeRangeEventProcess rprocess = null;
- for (TimeRangeEventProcess process : processes) {
- if (process.getPid().equals(pid)) {
- if (process.getCreationTime().equals(creationtime)) {
- if (process.getTraceID().equals(traceID)) {
- return process;
+class ProcessKey {
+ private TimeRangeEventProcess valueRef = null;
+
+ private Long pid = null;
+ private Long cpuId = null;
+ private String traceId = null;
+ private Long creationtime = null;
+
+ @SuppressWarnings("unused")
+ private ProcessKey() { }
+
+ public ProcessKey(TimeRangeEventProcess newRef) {
+ valueRef = newRef;
+ }
+
+ public ProcessKey(Long newPid, Long newCpuId, String newTraceId, Long newCreationTime) {
+ pid = newPid;
+ cpuId = newCpuId;
+ traceId = newTraceId;
+ creationtime = newCreationTime;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ boolean isSame = false;
+
+ if ( obj instanceof ProcessKey ) {
+ ProcessKey procKey = (ProcessKey) obj;
+
+ if (valueRef != null) {
+ if ((procKey.getPid().equals(valueRef.getPid()))
+ && (procKey.getTraceId().equals(valueRef.getTraceID()))
+ && (procKey.getCreationtime().equals(valueRef.getCreationTime()))) {
+ // use the cpu value to validate pid 0
+ if (valueRef.getPid().longValue() == 0L && !procKey.getCpuId().equals(valueRef.getCpu())) {
+ isSame = false;
+ } else {
+ isSame = true;
+ }
+ }
+ } else {
+ if ((procKey.getPid().equals(this.pid)) && (procKey.getTraceId().equals(this.traceId))
+ && (procKey.getCreationtime().equals(this.creationtime))) {
+ // use the cpu value to validate pid 0
+ if (this.pid.longValue() == 0L && !procKey.getCpuId().equals(this.cpuId)) {
+ isSame = false;
+ } else {
+ isSame = true;
}
}
}
- }
-
- return rprocess;
- }
+ }
+ else {
+ TraceDebug.debug("ERROR : The given key is not of the type ProcessKey!" + obj.getClass().toString()); //$NON-NLS-1$
+ }
+
+ return isSame;
+ }
+
+ // *** WARNING : Everything in there work because the check "valueRef != null" is the same for ALL getter
+ // Do NOT change this check without checking.
+ public Long getPid() {
+ if ( valueRef != null ) {
+ return valueRef.getPid();
+ }
+ else {
+ return pid;
+ }
+ }
- /**
- * Generate a unique process id while building the process list
- *
- * @return
- */
- public int bookProcId() {
- return idgen++;
- }
+ public Long getCpuId() {
+ if ( valueRef != null ) {
+ return valueRef.getCpu();
+ }
+ else {
+ return cpuId;
+ }
+ }
+
+ public String getTraceId() {
+ if ( valueRef != null ) {
+ return valueRef.getTraceID();
+ }
+ else {
+ return traceId;
+ }
+ }
+
+ public Long getCreationtime() {
+ if ( valueRef != null ) {
+ return valueRef.getCreationTime();
+ }
+ else {
+ return creationtime;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.toString().hashCode();
+ }
+
+
+ @Override
+ @SuppressWarnings("nls")
+ public String toString() {
+ if ( valueRef != null ) {
+ // return (valueRef.getPid().toString() + ":" +
+ // valueRef.getCpu().toString() + ":"
+ // + valueRef.getTraceID().toString() + ":" +
+ // valueRef.getCreationTime().toString());
+ return (valueRef.getPid().toString() + ":" + valueRef.getTraceID().toString() + ":" + valueRef
+ .getCreationTime().toString());
+ }
+
+ // return (pid.toString() + ":" + cpuId.toString() + ":" +
+ // traceId.toString() + ":" + creationtime.toString());
+ return (pid.toString() + ":" + traceId.toString() + ":" + creationtime.toString());
+ }
}