#region License Information
/* HeuristicLab
* Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using HeuristicLab.Hive.Slave.Common;
using HeuristicLab.Hive.Slave.Communication;
using System.Diagnostics;
using HeuristicLab.Hive.Contracts.BusinessObjects;
using HeuristicLab.Hive.Contracts;
using HeuristicLab.Hive.Slave.Core.ConfigurationManager;
using HeuristicLab.Hive.Slave.Communication.ServerService;
using HeuristicLab.Tracing;
using System.Threading;
//using BO = HeuristicLab.Hive.Contracts.BusinessObjects;
namespace HeuristicLab.Hive.Slave.Core {
///
/// Heartbeat class. It sends every x ms a heartbeat to the server and receives a Message
///
public class Heartbeat {
private bool offline;
public TimeSpan Interval { get; set; }
private Thread heartBeatThread;
private static object locker = new object();
public Heartbeat() {
Interval = new TimeSpan(0,0,10);
}
public Heartbeat(TimeSpan interval) {
Interval = interval;
}
private WcfService wcfService;
private bool abortThreadPending;
///
/// Starts the Heartbeat signal.
///
public void StartHeartbeat() {
wcfService = WcfService.Instance;
wcfService.ProcessHeartBeatCompleted += new EventHandler(wcfService_ProcessHeartBeatCompleted);
abortThreadPending = false;
heartBeatThread = GetHeartBeatThread();
heartBeatThread.Start();
}
private Thread GetHeartBeatThread() {
return new Thread(() => {
while (!abortThreadPending) {
lock (locker) {
// check if cwfService is disconnected for any reason (should happen at first heartbeat)
// [chn] TODO: Client should always send heartbeats. when calendar disallows he should tell the server he does not want to compute anything
if (wcfService.ConnState == NetworkEnum.WcfConnState.Disconnected) {
wcfService.Connect();
}
if (wcfService.ConnState == NetworkEnum.WcfConnState.Loggedin) {
// client is allowed to calculate stuff
ClientDto info = ConfigManager.Instance.GetClientInfo();
HeartBeatData heartBeatData = new HeartBeatData {
SlaveId = info.Id,
FreeCores = info.NrOfCores - ConfigManager.Instance.GetUsedCores(),
FreeMemory = GetFreeMemory(),
JobProgress = ConfigManager.Instance.GetProgressOfAllJobs(),
IsAllowedToCalculate = UptimeManager.Instance.IsOnline() && UptimeManager.Instance.CalendarAvailable
};
if (!heartBeatData.IsAllowedToCalculate) {
// stop all running jobs and send snapshots to server
MessageQueue.GetInstance().AddMessage(MessageContainer.MessageType.UptimeLimitDisconnect);
}
Logger.Debug("Sending Heartbeat: " + heartBeatData);
wcfService.ProcessHeartBeatAsync(heartBeatData);
}
} // lock
Thread.Sleep(Interval);
} // while
abortThreadPending = false;
});
}
private int GetFreeMemory() {
PerformanceCounter counter = new PerformanceCounter("Memory", "Available Bytes", true);
int mb = (int)(counter.NextValue() / 1024 / 1024);
return mb;
}
void wcfService_ProcessHeartBeatCompleted(object sender, ProcessHeartBeatCompletedEventArgs e) {
Logger.Debug("Heartbeat Response received");
e.Result.ActionRequest.ForEach(mc => MessageQueue.GetInstance().AddMessage(mc));
}
public void StopHeartBeat() {
abortThreadPending = true;
}
}
}