first commit
This commit is contained in:
+94
@@ -0,0 +1,94 @@
|
||||
import {get} from './get.js';
|
||||
|
||||
/**
|
||||
* Get the list of children and grandchildren pids of the given PID.
|
||||
* @param {number|string} pid A PID. If -1 will return all the pids.
|
||||
* @param {object} [options] Optional options object.
|
||||
* @param {boolean} [options.root=false] Include the provided PID in the list.
|
||||
* @param {boolean} [options.advanced=false] Returns a list of objects in the
|
||||
* format {ppid: X, pid: Y}.
|
||||
* @param {Function} callback callback(err, list) Called when the list is ready.
|
||||
*/
|
||||
export function pidtreeCallback(pid, options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (typeof options !== 'object' || options === null) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
pid = Number.parseInt(pid, 10);
|
||||
if (Number.isNaN(pid) || pid < -1) {
|
||||
callback(new TypeError('The pid provided is invalid'));
|
||||
return;
|
||||
}
|
||||
|
||||
get((error, list) => {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user wants the whole list just return it.
|
||||
if (pid === -1) {
|
||||
const all = list.map((entry) =>
|
||||
options.advanced ? {ppid: entry[0], pid: entry[1]} : entry[1],
|
||||
);
|
||||
callback(null, all);
|
||||
return;
|
||||
}
|
||||
|
||||
let root;
|
||||
for (const entry of list) {
|
||||
if (entry[1] === pid) {
|
||||
root = options.advanced ? {ppid: entry[0], pid} : pid;
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry[0] === pid) {
|
||||
// Special pids like 0 on *nix.
|
||||
root = options.advanced ? {pid} : pid;
|
||||
}
|
||||
}
|
||||
|
||||
if (root === undefined) {
|
||||
callback(new Error('No matching pid found'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the adjacency Hash Map (pid -> [children of pid]).
|
||||
const tree = {};
|
||||
for (const [parentPid, childPid] of list) {
|
||||
if (tree[parentPid]) {
|
||||
tree[parentPid].push(childPid);
|
||||
} else {
|
||||
tree[parentPid] = [childPid];
|
||||
}
|
||||
}
|
||||
|
||||
// Starting from the PID provided by the user, traverse the tree using the
|
||||
// adjacency Hash Map until the whole subtree is visited. Each pid
|
||||
// encountered while visiting is added to the pids array.
|
||||
const pids = [root];
|
||||
let index = 0;
|
||||
while (index < pids.length) {
|
||||
const current = options.advanced ? pids[index].pid : pids[index];
|
||||
index++;
|
||||
const children = tree[current];
|
||||
if (!children) continue;
|
||||
for (const childPid of children) {
|
||||
pids.push(options.advanced ? {ppid: current, pid: childPid} : childPid);
|
||||
}
|
||||
|
||||
delete tree[current];
|
||||
}
|
||||
|
||||
if (!options.root) {
|
||||
pids.shift(); // Remove root.
|
||||
}
|
||||
|
||||
callback(null, pids);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user