diff --git a/chrome/content/progress_panel.js b/chrome/content/progress_panel.js index eddca6af..746f6670 100644 --- a/chrome/content/progress_panel.js +++ b/chrome/content/progress_panel.js @@ -79,7 +79,7 @@ exchProgressPanel.prototype = { if (!this._document.getElementById("exchWebServiceProgress.progress.grid"+rowCount)) { grid = this._document.createElement("exchangeProgressGrid"); grid.setAttribute("id","exchWebServiceProgress.progress.grid"+rowCount); - grid.setAttribute("serverUrl",server); + grid.setAttribute("serverUrl",jobList[server].server); mainVBox.appendChild(grid); } else { @@ -154,7 +154,7 @@ exchProgressPanel.prototype = { } if (topic == "onExchangeProgressChange") { - if ((!this.timerRunning) && (!this.timerRunning)) { + if (!this.timerRunning) { this.timerRunning = true; this.timer.initWithCallback(this, 200, this.timer.TYPE_REPEATING_SLACK); } diff --git a/interfaces/exchangeLoadBalancer/mivExchangeLoadBalancer.js b/interfaces/exchangeLoadBalancer/mivExchangeLoadBalancer.js index 59852ac7..f817ad84 100644 --- a/interfaces/exchangeLoadBalancer/mivExchangeLoadBalancer.js +++ b/interfaces/exchangeLoadBalancer/mivExchangeLoadBalancer.js @@ -106,42 +106,79 @@ jobObject.prototype = { } -function mivExchangeLoadBalancer() { - this.serverQueue = {}; - this.runningJobs = {}; - this.jobsRunning = 0; - - - this.timer = null; - +function serverQueue(aServer, aLoadBalancer) +{ this.observerService = Cc["@mozilla.org/observer-service;1"] .getService(Ci.nsIObserverService); - this.globalFunctions = Cc["@1st-setup.nl/global/functions;1"] - .getService(Ci.mivFunctions); - + this.server = aServer; + this.loadBalancer = aLoadBalancer; + this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + this.timerStopped = true; + this.uuid = this.loadBalancer.globalFunctions.getUUID(); + this.calendars = []; + this.calendarIndex = 0; + this.jobs = {}; + this.calendarNames = {}; + this.jobCount = 0; + this.runningJobs = []; + this.jobsRunning = 0; } -var PREF_MAINPART = 'extensions.1st-setup.exchangecalendar.loadbalancer.'; +serverQueue.prototype = { + matchesServer: function _matchesServer(aServer) + { + return (aServer.toLowerCase() == this.server.toLowerCase()); + }, -var mivExchangeLoadBalancerGUID = "2db8c940-1927-11e2-892e-0800200c9a55"; + clearQueueForCalendar: function _clearQueueForCalendar(aCalendar) + { + if (this.jobs[aCalendar.id]) { + this.jobCount = this.jobCount - this.jobs[aCalendar.id].length; + delete this.jobs[aCalendar.id]; + this.observerService.notifyObservers(aCalendar, "onExchangeProgressChange", null); + } + }, -mivExchangeLoadBalancer.prototype = { + stopRunningJobsForCalendar: function _stopRunningJobsForCalendar(aCalendar) + { + if (this.jobs[aCalendar.id]) { + for (var index in this.runningJobs) { + // only stop for current calendar + try { + if ((this.runningJobs[index].exchangeRequest) && (this.runningJobs[index].exchangeRequest.isRunning) && (this.runningJobs[index].calendar) && (this.runningJobs[index].calendar.id == aCalendar.id)) { + this.runningJobs[index].exchangeRequest.stopRequest(); + } + } + catch(err) { + this.loadBalancer.globalFunctions.LOG("serverQueue:"+this.server+":stopRunningJobsForCalendar Error:"+err + " ("+this.globalFunctions.STACKshort()+")", -1); + } + } + } + }, - // methods from nsISupport - QueryInterface: XPCOMUtils.generateQI([Ci.mivExchangeLoadBalancer, - Ci.nsISupports]), + addJob: function _addJob(aJob) + { + // Check if we already have this calendar id; + if (!this.jobs[aJob.calendar.id]) { + this.calendars.push(aJob.calendar.id); + this.jobs[aJob.calendar.id] = []; + this.calendarNames[aJob.calendar.id] = aJob.calendar.name; + } - // Attributes from nsIClassInfo - classDescription: "Load balancer for requests to Exchange server.", - classID: components.ID("{"+mivExchangeLoadBalancerGUID+"}"), - contractID: "@1st-setup.nl/exchange/loadbalancer;1", - flags: Ci.nsIClassInfo.SINGLETON, - implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, + this.jobs[aJob.calendar.id].push(aJob); + this.jobCount++; - // External methods + if (this.timerStopped) { + this.loadBalancer.logInfo("serverQueue:"+this.server+": Timer started.",1); + this.timerStopped = false; + this.timer.initWithCallback(this, 10, this.timer.TYPE_REPEATING_SLACK); + } + + this.loadBalancer.logInfo("serverQueue:"+this.server+": Added job to queue for server '"+this.server+"' for calendar '"+aJob.calendar.name+"'. We now have:"+this.jobs[aJob.calendar.id].length+" jobs.",2); + this.observerService.notifyObservers(aJob.calendar, "onExchangeProgressChange", null); + }, - // Internal methods. get maxJobs() { return 1; // Currently going for default one at a time to the same server because the xmlhttprequest cannot handle more simultaniously. @@ -150,181 +187,173 @@ mivExchangeLoadBalancer.prototype = { get sleepBetweenJobs() { - return 200; // Currently going for default zero because it works. + return 50; // Currently going for default zero because it works. //return this.globalFunctions.safeGetIntPref(null, PREF_MAINPART+"sleepBetweenJobs", 2, true); }, - notify: function _notify() { - this.processQueue(); - }, + notify: function _notify(aTimer) { +//dump(this.server+":loadBalancer: starting Job\n"); +try{ + // Cleanup jobs wich have finished + var newJobList = []; + for (var index in this.runningJobs) { + if ((this.runningJobs[index].exchangeRequest) && (!this.runningJobs[index].exchangeRequest.isRunning)) { + // Job stopped. + this.loadBalancer.logInfo("serverQueue:"+this.server+": Removing stopped job.",1); + this.jobsRunning--; + this.runningJobs[index].clear(); + } + else { + newJobList.push(this.runningJobs[index]); + if (this.runningJobs[index].state == jobObject.RUNNING) { + var timeNow = new Date().getTime(); + var timeDiff = timeNow - this.runningJobs[index].startTime; + if (timeDiff > 300000) { + dump("We have a job which is running longer than 5 minutes:"+this.runningJobs[index].job.ecRequest+"\n"); + if (this.runningJobs[index].exchangeRequest["runs"]) { + dump(" ## runs="+this.runningJobs[index].exchangeRequest["runs"]+" ##\n"); + } + //dump("We have a job which is running longer than 5 minutes\n"); + this.runningJobs[index].startTime = new Date().getTime(); + } + } + } + } + this.runningJobs = newJobList; - addToQueue: function _addToQueue(aJob) - { + //this.loadBalancer.logInfo("serverQueue:"+this.server+": Notify: this.runningJobs:"+this.runningJobs.length+".",2); - if (!aJob.arguments) { - this.logInfo("addToQueue: arguments is not defined!!!????:"+this.globalFunctions.STACK()); - return; - } + if ((this.runningJobs.length < this.maxJobs) && (this.jobCount > 0)) { - if (!this.serverQueue[aJob.arguments.serverUrl]) { - this.serverQueue[aJob.arguments.serverUrl] = { currentCalendar: 0, - calendarList: new Array(), - calendarNames: {}, - runningJobs: new Array(), - jobs: {} }; - } + // Try to find next calendar with a job. + var oldCalendarIndex = this.calendarIndex; + do { + this.calendarIndex++; + if (this.calendarIndex >= this.calendars.length) { + this.calendarIndex = 0; + } + } while ((this.jobs[this.calendars[this.calendarIndex]].length == 0) && (this.calendarIndex != oldCalendarIndex)); - if (!this.serverQueue[aJob.arguments.serverUrl].jobs[aJob.calendar.id]) { - this.serverQueue[aJob.arguments.serverUrl].jobs[aJob.calendar.id] = new Array(); - this.serverQueue[aJob.arguments.serverUrl].calendarNames[aJob.calendar.id] = aJob.calendar.name; - } + if (this.jobs[this.calendars[this.calendarIndex]].length > 0) { + var job = this.jobs[this.calendars[this.calendarIndex]].shift(); + if (job === undefined) { + dump("%%%%%%%%%%%%%%%%% job === undefined &&&&&&&&&&&&&&&&&&&&\n"); + } + this.jobCount--; - this.serverQueue[aJob.arguments.serverUrl].jobs[aJob.calendar.id].push(aJob); - this.logInfo("Adding job to queue for server '"+aJob.arguments.serverUrl+"' for calendar '"+aJob.calendar.id+"'. We now have:"+this.serverQueue[aJob.arguments.serverUrl].jobs[aJob.calendar.id].length+" jobs.",2); + this.observerService.notifyObservers(job.calendar, "onExchangeProgressChange", null); - // Check if the calendar.id is allready in the list. - var inList = false; - var counter = 0; - while ((!inList) && (counter < this.serverQueue[aJob.arguments.serverUrl].calendarList.length)) { - if (this.serverQueue[aJob.arguments.serverUrl].calendarList[counter] == aJob.calendar.id) { - inList = true; + job.arguments["cbOk"] = job.cbOk; + job.arguments["cbError"] = job.cbError; + job.arguments["job"] = job; + job.arguments["calendar"] = job.calendar; + var newJob = new jobObject(job, this.server, this.loadBalancer); + this.runningJobs.push(newJob); + + this.jobsRunning++; + this.loadBalancer.logInfo("serverQueue:"+this.server+":Starting job for calendar '"+job.calendar.name+"'. We now have:"+this.jobs[job.calendar.id].length+" jobs in queue and "+this.runningJobs.length+" jobs running.",2); + + //dump(server+":loadBalancer: starting timeout for Job\n"); + newJob.timer.initWithCallback(newJob, this.sleepBetweenJobs, Ci.nsITimer.TYPE_ONE_SHOT); + this.loadBalancer.logInfo("serverQueue:"+this.server+": Started timer for new job.",1); + } + else { + dump("serverQueue:"+this.server+": Strange. this.jobCount == "+this.jobCount+" but could not find calendar with jobs.\n"); } - counter++; - } - if (!inList) { - this.serverQueue[aJob.arguments.serverUrl].calendarList.push(aJob.calendar.id); } - this.observerService.notifyObservers(aJob.calendar, "onExchangeProgressChange", null); - - if (!this.timer) { - this.logInfo("Start timer"); - this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this.timer.initWithCallback(this, 10, this.timer.TYPE_REPEATING_SLACK); + if ((this.jobCount == 0) && (this.runningJobs.length == 0)) { + this.loadBalancer.logInfo("serverQueue:"+this.server+": Stopping server queue timer.",1); + this.timer.cancel(); + this.timerStopped = true; + this.loadBalancer.logInfo("serverQueue:"+this.server+": Timer stopped.",1); } +} +catch(err) { + dump("serverQueue: notify: err:"+err+"\n"); +} }, +} - get jobList() - { - return this.serverQueue; - }, +function mivExchangeLoadBalancer() { + this.serverQueues = []; - processQueue: function _processQueue() - { - for (var server in this.serverQueue) { - - // Cleanup jobs wich have finished - var oldList = this.serverQueue[server].runningJobs; - this.serverQueue[server].runningJobs = new Array(); - for (var runningJob in oldList) { - if ((oldList[runningJob].state == jobObject.QUEUED) || - ((oldList[runningJob].state == jobObject.RUNNING) && (oldList[runningJob].exchangeRequest) && (oldList[runningJob].exchangeRequest.isRunning))) { - //this.logInfo("this.jobsRunning:"+this.jobsRunning); - this.serverQueue[server].runningJobs.push(oldList[runningJob]); - // Check how long this job is running - if (oldList[runningJob].state == jobObject.RUNNING) { - var timeNow = new Date().getTime(); - var timeDiff = timeNow - oldList[runningJob].startTime; - if (timeDiff > 300000) { - dump("We have a job which is running longer than 5 minutes:"+oldList[runningJob].job.ecRequest+"\n"); - if (oldList[runningJob].exchangeRequest["runs"]) { - dump(" ## runs="+oldList[runningJob].exchangeRequest["runs"]+" ##\n"); - } - //dump("We have a job which is running longer than 5 minutes\n"); - oldList[runningJob].startTime = new Date().getTime(); - } - } - } - else { - // Running job stopped. - this.jobsRunning--; - oldList[runningJob].clear; - //dump(server+":running job stopped:"+this.jobsRunning+"\n"); - } - } + this.observerService = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); - // See if we can start another job for this url/server - //this.logInfo("Runningjobs:"+this.serverQueue[server].runningJobs.length+", maxJobs:"+this.maxJobs); - if (this.serverQueue[server].runningJobs.length < this.maxJobs) { - if (this.serverQueue[server].currentCalendar >= this.serverQueue[server].calendarList.length) { - this.serverQueue[server].currentCalendar = 0; - } - var initialCurrentCalendar = this.serverQueue[server].currentCalendar; - var noJobsLeft = false - while ((!noJobsLeft) && (this.serverQueue[server].currentCalendar < this.serverQueue[server].calendarList.length) && (this.serverQueue[server].jobs[this.serverQueue[server].calendarList[this.serverQueue[server].currentCalendar]].length == 0)) { - this.serverQueue[server].currentCalendar++; + this.globalFunctions = Cc["@1st-setup.nl/global/functions;1"] + .getService(Ci.mivFunctions); - if (this.serverQueue[server].currentCalendar >= this.serverQueue[server].calendarList.length) { - this.serverQueue[server].currentCalendar = 0; - } +} - if (this.serverQueue[server].currentCalendar == initialCurrentCalendar) { - // Stop processing for this server because there are now jobs left. - noJobsLeft = true; - - } +var PREF_MAINPART = 'extensions.1st-setup.exchangecalendar.loadbalancer.'; - } - if ((!noJobsLeft) && (this.serverQueue[server].currentCalendar < this.serverQueue[server].calendarList.length) && (this.serverQueue[server].jobs[this.serverQueue[server].calendarList[this.serverQueue[server].currentCalendar]].length > 0)) { - var job = this.serverQueue[server].jobs[this.serverQueue[server].calendarList[this.serverQueue[server].currentCalendar]].shift(); +var mivExchangeLoadBalancerGUID = "2db8c940-1927-11e2-892e-0800200c9a55"; - this.serverQueue[server].currentCalendar++; - if (this.serverQueue[server].currentCalendar >= this.serverQueue[server].calendarList.length) { - this.serverQueue[server].currentCalendar = 0; - } +mivExchangeLoadBalancer.prototype = { - this.observerService.notifyObservers(job.calendar, "onExchangeProgressChange", null); - - job.arguments["cbOk"] = job.cbOk; - job.arguments["cbError"] = job.cbError; - job.arguments["job"] = job; - job.arguments["calendar"] = job.calendar; - var newJob = new jobObject(job, server, this); - this.serverQueue[server].runningJobs.push(newJob); - - this.logInfo("Starting job to queue for server '"+server+"' for calendar '"+job.calendar.id+"'. We now have:"+this.serverQueue[server].jobs[job.calendar.id].length+" jobs in queue and "+this.serverQueue[server].runningJobs.length+" jobs running.",2); - this.jobsRunning++; - this.logInfo("this.jobsRunning:"+this.jobsRunning,1); - -//dump(server+":loadBalancer: starting timeout for Job\n"); - newJob.timer.initWithCallback(newJob, this.sleepBetweenJobs, Ci.nsITimer.TYPE_ONE_SHOT); - } + // methods from nsISupport + QueryInterface: XPCOMUtils.generateQI([Ci.mivExchangeLoadBalancer, + Ci.nsISupports]), + + // Attributes from nsIClassInfo + classDescription: "Load balancer for requests to Exchange server.", + classID: components.ID("{"+mivExchangeLoadBalancerGUID+"}"), + contractID: "@1st-setup.nl/exchange/loadbalancer;1", + flags: Ci.nsIClassInfo.SINGLETON, + implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT, + + // External methods + + addToQueue: function _addToQueue(aJob) + { + if (!aJob.arguments) { + this.logInfo("addToQueue: arguments is not defined!!!????:"+this.globalFunctions.STACK()); + return; + } + + var queueToUse = undefined; + for each(var serverq in this.serverQueues) { + if (serverq.matchesServer(aJob.arguments.serverUrl)) { + queueToUse = serverq; + break; } } - if (this.jobsRunning == 0) { - this.logInfo("No more jobs left. Stop Timer.",2); - this.timer.cancel(); - delete this.timer; + if (queueToUse === undefined) { + queueToUse = new serverQueue(aJob.arguments.serverUrl, this); + this.serverQueues.push(queueToUse); } + queueToUse.addJob(aJob); + }, + + get jobList() + { + return this.serverQueues; }, clearQueueForCalendar: function _clearQueueForCalendar(aServer, aCalendar) { - if (this.serverQueue[aServer]) { - if (this.serverQueue[aServer].jobs[aCalendar.id]) { - this.observerService.notifyObservers(aCalendar, "onExchangeProgressChange", null); - this.serverQueue[aServer].jobs[aCalendar.id] = new Array(); - } + var queueToUse = undefined; + for each(var serverq in this.serverQueues) { + if (serverq.matchesServer(aServer)) { + serverq.clearQueueForCalendar(aCalendar); + break; + } } }, stopRunningJobsForCalendar: function _stopRunningJobsForCalendar(aServer, aCalendar) { - if (this.serverQueue[aServer]) { - for (var index in this.serverQueue[aServer].runningJobs) { - // only stop for current calendar - try { - if ((this.serverQueue[aServer].runningJobs[index].exchangeRequest.isRunning) && (this.serverQueue[aServer].runningJobs[index].calendar) && (this.serverQueue[aServer].runningJobs[index].calendar.id == aCalendar.id)) { - this.serverQueue[aServer].runningJobs[index].exchangeRequest.stopRequest(); - } - } - catch(err) { - this.globalFunctions.LOG("stopRunningJobsForCalendar Error:"+err + " ("+this.globalFunctions.STACKshort()+")", -1); - } + var queueToUse = undefined; + for each(var serverq in this.serverQueues) { + if (serverq.matchesServer(aServer)) { + serverq.stopRunningJobsForCalendar(aCalendar); + break; } } + }, logInfo: function _logInfo(message, aDebugLevel) {