pidtree.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. 'use strict';
  2. var getAll = require('./get');
  3. /**
  4. * Get the list of children and grandchildren pids of the given PID.
  5. * @param {Number|String} PID A PID. If -1 will return all the pids.
  6. * @param {Object} [options] Optional options object.
  7. * @param {Boolean} [options.root=false] Include the provided PID in the list.
  8. * @param {Boolean} [options.advanced=false] Returns a list of objects in the
  9. * format {pid: X, ppid: Y}.
  10. * @param {Function} callback(err, list) Called when the list is ready.
  11. */
  12. function list(PID, options, callback) {
  13. if (typeof options === 'function') {
  14. callback = options;
  15. options = {};
  16. }
  17. if (typeof options !== 'object') {
  18. options = {};
  19. }
  20. PID = parseInt(PID, 10);
  21. if (isNaN(PID) || PID < -1) {
  22. callback(new TypeError('The pid provided is invalid'));
  23. return;
  24. }
  25. getAll(function(err, list) {
  26. if (err) {
  27. callback(err);
  28. return;
  29. }
  30. // If the user wants the whole list just return it
  31. if (PID === -1) {
  32. for (var i = 0; i < list.length; i++) {
  33. list[i] = options.advanced
  34. ? {ppid: list[i][0], pid: list[i][1]}
  35. : (list[i] = list[i][1]);
  36. }
  37. callback(null, list);
  38. return;
  39. }
  40. var root;
  41. for (var l = 0; l < list.length; l++) {
  42. if (list[l][1] === PID) {
  43. root = options.advanced ? {ppid: list[l][0], pid: PID} : PID;
  44. break;
  45. }
  46. if (list[l][0] === PID) {
  47. root = options.advanced ? {pid: PID} : PID; // Special pids like 0 on *nix
  48. }
  49. }
  50. if (!root) {
  51. callback(new Error('No matching pid found'));
  52. return;
  53. }
  54. // Build the adiacency Hash Map (pid -> [children of pid])
  55. var tree = {};
  56. while (list.length > 0) {
  57. var element = list.pop();
  58. if (tree[element[0]]) {
  59. tree[element[0]].push(element[1]);
  60. } else {
  61. tree[element[0]] = [element[1]];
  62. }
  63. }
  64. // Starting by the PID provided by the user, traverse the tree using the
  65. // adiacency Hash Map until the whole subtree is visited.
  66. // Each pid encountered while visiting is added to the pids array.
  67. var idx = 0;
  68. var pids = [root];
  69. while (idx < pids.length) {
  70. var curpid = options.advanced ? pids[idx++].pid : pids[idx++];
  71. if (!tree[curpid]) continue;
  72. var length = tree[curpid].length;
  73. for (var j = 0; j < length; j++) {
  74. pids.push(
  75. options.advanced
  76. ? {ppid: curpid, pid: tree[curpid][j]}
  77. : tree[curpid][j]
  78. );
  79. }
  80. delete tree[curpid];
  81. }
  82. if (!options.root) {
  83. pids.shift(); // Remove root
  84. }
  85. callback(null, pids);
  86. });
  87. }
  88. module.exports = list;