Added priorities in task queue.

This commit is contained in:
Ylian Saint-Hilaire 2019-02-08 14:17:35 -08:00
parent 9beaa45f9f
commit a5b5124e5f
8 changed files with 33 additions and 24 deletions

View File

@ -179,17 +179,19 @@ module.exports.checkPasswordRequirements = function(password, requirements) {
// This is useful to limit the number of agents upgrading at the same time, to not swamp
// the network with traffic.
// taskLimiterQueue.launch(somethingToDo, argument);
// taskLimiterQueue.launch(somethingToDo, argument, priority);
//
// function somethingToDo(argument, taskid, taskLimiterQueue) {
// setTimeout(function () { taskLimiterQueue.completed(taskid); }, Math.random() * 2000);
// }
module.exports.createTaskLimiterQueue = function(maxTasks, maxTaskTime, cleaningInterval) {
var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [], timer: null };
module.exports.createTaskLimiterQueue = function (maxTasks, maxTaskTime, cleaningInterval) {
var obj = { maxTasks: maxTasks, maxTaskTime: (maxTaskTime * 1000), nextTaskId: 0, currentCount: 0, current: {}, pending: [[], [], []], timer: null };
// Add a task to the super queue
obj.launch = function (func, arg) {
// Priority: 0 = High, 1 = Medium, 2 = Low
obj.launch = function (func, arg, pri) {
if (typeof pri != 'number') { pri = 2; }
if (obj.currentCount < obj.maxTasks) {
// Run this task now
const id = obj.nextTaskId++;
@ -201,7 +203,7 @@ module.exports.createTaskLimiterQueue = function(maxTasks, maxTaskTime, cleaning
} else {
// Hold this task
//console.log('Holding');
obj.pending.push({ func: func, arg: arg });
obj.pending[pri].push({ func: func, arg: arg });
}
}
@ -209,15 +211,22 @@ module.exports.createTaskLimiterQueue = function(maxTasks, maxTaskTime, cleaning
obj.completed = function (taskid) {
//console.log('Completed ' + taskid);
if (obj.current[taskid]) { delete obj.current[taskid]; obj.currentCount--; } else { return; }
while ((obj.pending.length > 0) && (obj.currentCount < obj.maxTasks)) {
while ((obj.currentCount < obj.maxTasks) && ((obj.pending[0].length > 0) || (obj.pending[1].length > 0) || (obj.pending[2].length > 0))) {
// Run this task now
const t = obj.pending.shift(), id = obj.nextTaskId++;
var t = null;
if (obj.pending[0].length > 0) { t = obj.pending[0].shift(); }
else if (obj.pending[1].length > 0) { t = obj.pending[1].shift(); }
else if (obj.pending[2].length > 0) { t = obj.pending[2].shift(); }
const id = obj.nextTaskId++;
obj.current[id] = Date.now() + obj.maxTaskTime;
obj.currentCount++;
//console.log('PendingLaunch ' + id);
t.func(t.arg, id, obj); // Start the task
}
if ((obj.pending.length == 0) && (obj.timer != null)) { clearInterval(obj.timer); obj.timer = null; } // All done, clear the timer
if ((obj.pending[0].length == 0) && (obj.pending[1].length == 0) && (obj.pending[2].length == 0) && (obj.timer != null)) {
// All done, clear the timer
clearInterval(obj.timer); obj.timer = null;
}
}
// Look for long standing tasks and clean them up
@ -227,4 +236,4 @@ module.exports.createTaskLimiterQueue = function(maxTasks, maxTaskTime, cleaning
}
return obj;
}
}

View File

@ -125,12 +125,12 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
//obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + meshcorehash + obj.parent.parent.defaultMeshCores[corename]); // MeshCommand_CoreModule, start core update
//obj.parent.parent.debug(1, 'Updating code ' + corename);
// Update new core with task limiting so not to flood the server.
// Update new core with task limiting so not to flood the server. This is a high priority task.
obj.parent.parent.taskLimiter.launch(function (argument, taskid, taskLimiterQueue) {
obj.send(obj.common.ShortToStr(10) + obj.common.ShortToStr(0) + argument.hash + argument.core, function () { obj.parent.parent.taskLimiter.completed(taskid); }); // MeshCommand_CoreModule, start core update
obj.parent.parent.debug(1, 'Updating code ' + argument.name);
agentCoreIsStable();
}, { hash: meshcorehash, core: obj.parent.parent.defaultMeshCores[corename], name: corename });
}, { hash: meshcorehash, core: obj.parent.parent.defaultMeshCores[corename], name: corename }, 0);
}
obj.agentCoreCheck++;
}
@ -169,7 +169,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
if ((msg.length == 52) && (obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
var agenthash = obj.common.rstr2hex(msg.substring(4)).toLowerCase();
if ((agenthash != obj.agentExeInfo.hash) && (agenthash != '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')) {
// Mesh agent update required, do it using task limiter so not to flood the network.
// Mesh agent update required, do it using task limiter so not to flood the network. Medium priority task.
obj.parent.parent.taskLimiter.launch(function (argument, taskid, taskLimiterQueue) {
if (obj.nodeid != null) { obj.parent.parent.debug(1, 'Agent update required, NodeID=0x' + obj.nodeid.substring(0, 16) + ', ' + obj.agentExeInfo.desc); }
obj.fs.open(obj.agentExeInfo.path, 'r', function (err, fd) {
@ -203,7 +203,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
obj.send(obj.agentUpdate.buf); // Command 14, mesh agent first data block
}
});
}, null);
}, null, 1);
} else {
// Check the mesh core, if the agent is capable of running one

View File

@ -1,6 +1,6 @@
{
"name": "meshcentral",
"version": "0.2.7-o",
"version": "0.2.7-p",
"keywords": [
"Remote Management",
"Intel AMT",

View File

@ -215,11 +215,11 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
socket.tag.updatePtr = 0;
//console.log('Performing legacy agent update from ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' to ' + socket.tag.update.ver + '.' + socket.tag.update.arch + ' on ' + nodeblock.agentname + '.');
// Start the agent download using the task limiter so not to flood the server.
// Start the agent download using the task limiter so not to flood the server. Low priority task
obj.parent.taskLimiter.launch(function (socket, taskid, taskLimiterQueue) {
socket.tag.taskid = taskid;
obj.SendCommand(socket, LegacyMeshProtocol.GETSTATE, common.IntToStr(5) + common.IntToStr(0)); // agent.SendQuery(5, 0); // Start the agent download
}, socket);
}, socket, 2);
} else {
//console.log('No legacy agent update for ' + nodeblock.agentversion + '.' + nodeblock.agenttype + ' on ' + nodeblock.agentname + '.');
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -249,7 +249,7 @@
<br style=clear:both />
</div>
<strong>Device Groups</strong>
( <a onclick=account_createMesh() style=cursor:pointer><img height=12 src="images/icon-addnew.png" width=12 border=0 /> New</a> )
( <a onclick=account_createMesh() style=cursor:pointer><img src="images/icon-addnew.png" width=12 height=12 border=0 /> New</a> )
<br /><br />
<div id=p3meshes></div>
<div id=p3noMeshFound style=margin-left:9px;display:none>No device groups. <a onclick=account_createMesh() style=cursor:pointer><strong>Get started here!</strong></a></div>

View File

@ -3312,7 +3312,7 @@
// Add node name
var nname = EscapeHtml(node.name);
if (nname.length == 0) { nname = '<i>None</i>'; }
if ((meshrights & 4) != 0) { nname = '<span title="Click here to edit the server-side device name" onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + ' <img class=hoverButton src="images/link5.png" /></span>'; }
if ((meshrights & 4) != 0) { nname = '<span title="Click here to edit the server-side device name" onclick=showEditNodeValueDialog(0) style=cursor:pointer>' + nname + ' <img class=hoverButton width=10 height=10 src="images/link5.png" /></span>'; }
QH('p10deviceName', nname);
QH('p11deviceName', nname);
QH('p12deviceName', nname);
@ -3346,7 +3346,7 @@
// Attribute: Description
var description = node.desc?EscapeHtml(node.desc):"<i>None</i>";
if ((meshrights & 4) != 0) {
x += addDeviceAttribute('Description', '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton src="images/link5.png" /></span>');
x += addDeviceAttribute('Description', '<span onclick=showEditNodeValueDialog(2) style=cursor:pointer>' + description + ' <img class=hoverButton width=10 height=10 src="images/link5.png" /></span>');
} else {
x += addDeviceAttribute('Description', description);
}
@ -3421,7 +3421,7 @@
// Node grouping tags
var groupingTags = '<i>None</i>';
if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton width=10 height=10 src="images/link5.png" /></span>');
x += '</table><br />';
// Show action button, only show if we have permissions 4, 8, 64
@ -6360,7 +6360,7 @@
var x = '<div style=min-height:80px><table style=width:100%>';
var email = user.email?EscapeHtml(user.email):'<i>Not set</i>', everify = '';
if (serverinfo.emailcheck) { everify = ((user.emailVerified == true)?'<b style=color:green;cursor:pointer title="Email is verified">&#x1F5F8</b> ':'<b style=color:red;cursor:pointer title="Email not verified">&#x1F5F4</b> '); }
x += addDeviceAttribute('Email', everify + "<a style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img src="images/link1.png" /></a>');
x += addDeviceAttribute('Email', everify + "<a style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img class=hoverButton width=10 height=10 src="images/link1.png" /></a>');
x += addDeviceAttribute('Server Rights', "<a style=cursor:pointer onclick=showUserAdminDialog(event,\"" + userid + "\")>" + msg + "</a>");
if (user.quota) x += addDeviceAttribute('Server Quota', EscapeHtml(parseInt(user.quota) / 1024) + ' k');
x += addDeviceAttribute('Creation', new Date(user.creation * 1000).toLocaleString());
@ -6919,7 +6919,7 @@
function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } }
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
//function addLink(x, f) { return "<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='" + f + "'>&diams; " + x + "</a>"; }
function addLink(x, f) { return "<span style=cursor:pointer;text-decoration:none onclick='" + f + "'>" + x + " <img class=hoverButton src=images/link5.png></span>"; }
function addLink(x, f) { return "<span style=cursor:pointer;text-decoration:none onclick='" + f + "'>" + x + " <img class=hoverButton width=10 height=10 src=images/link5.png></span>"; }
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
function addOption(q, t, i) { var option = document.createElement("option"); option.text = t; option.value = i; Q(q).add(option); }