#region License Information /* HeuristicLab * Copyright (C) 2002-2010 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.Diagnostics; using System.Threading; using HeuristicLab.Common; using HeuristicLab.Services.Hive.Common; using HeuristicLab.Services.Hive.Common.DataTransfer; namespace HeuristicLab.Clients.Hive.Slave { /// /// Heartbeat class. It sends every x ms a heartbeat to the server and receives a Message /// public class HeartbeatManager { private static object locker = new object(); public TimeSpan Interval { get; set; } private Thread heartBeatThread; private AutoResetEvent waitHandle; public HeartbeatManager() { Interval = new TimeSpan(0, 0, 10); } public HeartbeatManager(TimeSpan interval) { Interval = interval; } private WcfService wcfService; private bool threadStopped; ReaderWriterLockSlim heartBeatThreadIsSleepingLock = new ReaderWriterLockSlim(); /// /// Starts the Heartbeat signal. /// public void StartHeartbeat() { this.waitHandle = new AutoResetEvent(true); wcfService = WcfService.Instance; threadStopped = false; heartBeatThread = new Thread(RunHeartBeatThread); heartBeatThread.Start(); } /// /// Stop the heartbeat /// public void StopHeartBeat() { threadStopped = true; waitHandle.Set(); heartBeatThread.Join(); } /// /// use this method to singalize there is work to do (to avoid the waiting period if its clear that actions are required) /// public void AwakeHeartBeatThread() { if (!threadStopped) waitHandle.Set(); } private void RunHeartBeatThread() { while (!threadStopped) { try { lock (locker) { if (wcfService.ConnState != NetworkEnum.WcfConnState.Connected) { wcfService.Connect(ConfigManager.Instance.GetClientInfo()); // Login happens automatically upon successfull connection } if (wcfService.ConnState == NetworkEnum.WcfConnState.Connected) { HeuristicLab.Services.Hive.Common.DataTransfer.Slave info = ConfigManager.Instance.GetClientInfo(); Heartbeat heartBeatData = new Heartbeat { SlaveId = info.Id, FreeCores = info.Cores.HasValue ? info.Cores.Value - ConfigManager.Instance.GetUsedCores() : 0, FreeMemory = GetFreeMemory(), JobProgress = ConfigManager.Instance.GetExecutionTimeOfAllJobs() }; SlaveClientCom.Instance.ClientCom.LogMessage("Sending Heartbeat: " + heartBeatData); List msgs = wcfService.SendHeartbeat(heartBeatData); if (msgs == null) { SlaveClientCom.Instance.ClientCom.LogMessage("Error getting response from Heartbeat"); OnExceptionOccured(new Exception("Error getting response from Heartbeat")); } SlaveClientCom.Instance.ClientCom.LogMessage("Heartbeat Response received: "); msgs.ForEach(mc => SlaveClientCom.Instance.ClientCom.LogMessage(mc.Message.ToString())); msgs.ForEach(mc => MessageQueue.GetInstance().AddMessage(mc)); } } } catch (Exception e) { SlaveClientCom.Instance.ClientCom.LogMessage("Heartbeat Thread failed badly: " + e.Message); OnExceptionOccured(e); } waitHandle.WaitOne(this.Interval); } waitHandle.Close(); SlaveClientCom.Instance.ClientCom.LogMessage("Heartbeat thread stopped"); } #region Eventhandler public event EventHandler> ExceptionOccured; private void OnExceptionOccured(Exception e) { var handler = ExceptionOccured; if (handler != null) handler(this, new EventArgs(e)); } #endregion #region Helpers private int GetFreeMemory() { PerformanceCounter counter = new PerformanceCounter("Memory", "Available Bytes", true); int mb = (int)(counter.NextValue() / 1024 / 1024); return mb; } #endregion } }