#region License Information
/* HeuristicLab
* Copyright (C) 2002-2018 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.Web.Http;
using HeuristicLab.Services.Hive;
using HeuristicLab.Services.Hive.DataAccess;
using HeuristicLab.Services.Hive.DataAccess.Interfaces;
using DT = HeuristicLab.Services.WebApp.Statistics.WebApi.DataTransfer;
namespace HeuristicLab.Services.WebApp.Statistics.WebApi {
[Authorize]
public class ClientController : ApiController {
private IPersistenceManager PersistenceManager {
get { return ServiceLocator.Instance.PersistenceManager; }
}
public DT.ClientDetails GetClientDetails(Guid id) {
var pm = PersistenceManager;
var dimClientDao = pm.DimClientDao;
var factClientInfoDao = pm.FactClientInfoDao;
var factTaskDao = pm.FactTaskDao;
return pm.UseTransaction(() => {
var timeData = factClientInfoDao.GetByClientId(id)
.GroupBy(x => x.ClientId)
.Select(x => new {
TotalIdleTime = x.Sum(y => y.IdleTime),
TotalOfflineTime = x.Sum(y => y.OfflineTime),
TotalUnavailableTime = x.Sum(y => y.UnavailableTime)
}).FirstOrDefault();
var taskTimeData = factTaskDao.GetByClientId(id)
.GroupBy(x => x.LastClientId)
.Select(x => new {
TotalCalculatingTime = x.Sum(y => y.CalculatingTime),
TotalTransferringTime = x.Sum(y => y.TransferTime)
}).FirstOrDefault();
var startDate = factClientInfoDao.GetByClientId(id)
.Where(x => x.SlaveState == SlaveState.Offline)
.OrderByDescending(x => x.Time)
.Select(x => x.Time).FirstOrDefault();
long upTime = 0;
if (startDate == default(DateTime)) {
startDate = factClientInfoDao.GetByClientId(id)
.OrderByDescending(x => x.Time)
.Select(x => x.Time)
.FirstOrDefault();
}
if (startDate != default(DateTime)) {
upTime = (long)(DateTime.Now - startDate).TotalSeconds;
}
return (from client in dimClientDao.GetAll().Where(x => x.Id == id)
join info in factClientInfoDao.GetAll()
on client.Id equals info.ClientId into clientInfoJoin
from clientInfo in clientInfoJoin.OrderByDescending(x => x.Time).Take(1)
let offline = (client.DateExpired != null || clientInfo.SlaveState == SlaveState.Offline)
let parent = client.ParentResourceId.HasValue ? dimClientDao.GetById(client.ParentResourceId.Value) : null
select new DT.ClientDetails {
Id = client.Id,
Name = client.Name,
TotalCores = clientInfo.NumTotalCores,
UsedCores = offline ? 0 : clientInfo.NumUsedCores,
TotalMemory = clientInfo.TotalMemory,
UsedMemory = offline ? 0 : clientInfo.UsedMemory,
CpuUtilization = offline ? 0 : clientInfo.CpuUtilization,
State = offline ? SlaveState.Offline.ToString() : clientInfo.SlaveState.ToString(),
LastUpdate = clientInfo.Time,
GroupId = client.ParentResourceId,
GroupName = parent != null ? parent.Name : null,
UpTime = offline ? 0 : upTime,
TotalUnavailableTime = timeData != null ? timeData.TotalUnavailableTime : 0,
TotalCalculatingTime = taskTimeData != null ? taskTimeData.TotalCalculatingTime : 0,
TotalIdleTime = timeData != null ? timeData.TotalIdleTime : 0,
TotalOfflineTime = timeData != null ? timeData.TotalOfflineTime : 0,
TotalTransferringTime = taskTimeData != null ? taskTimeData.TotalTransferringTime : 0,
TasksStates = factTaskDao.GetByClientId(id)
.GroupBy(x => x.TaskState)
.Select(x => new DT.TaskStateCount {
State = x.Key.ToString(),
Count = x.Count()
}).ToList(),
Users = factTaskDao.GetAll()
.Where(x => x.LastClientId == id)
.Select(x => new DT.User {
Id = x.DimJob.UserId,
Name = x.DimJob.UserName
})
.Distinct()
.ToList()
})
.FirstOrDefault();
});
}
public DT.ClientPage GetClients(int page, int size, bool expired = false) {
var pm = PersistenceManager;
var dimClientDao = pm.DimClientDao;
var factClientInfoDao = pm.FactClientInfoDao;
return pm.UseTransaction(() => {
var clients = expired ? dimClientDao.GetAllExpiredSlaves() : dimClientDao.GetAllOnlineSlaves();
var query = (from client in clients
join info in factClientInfoDao.GetAll()
on client.Id equals info.ClientId into clientInfoJoin
from clientInfo in clientInfoJoin.OrderByDescending(x => x.Time).Take(1)
let offline = (expired || clientInfo.SlaveState == SlaveState.Offline)
let parent = client.ParentResourceId.HasValue ? dimClientDao.GetById(client.ParentResourceId.Value) : null
select new DT.Client {
Id = client.Id,
Name = client.Name,
TotalCores = clientInfo.NumTotalCores,
UsedCores = offline ? 0 : clientInfo.NumUsedCores,
TotalMemory = clientInfo.TotalMemory,
UsedMemory = offline ? 0 : clientInfo.UsedMemory,
CpuUtilization = offline ? 0 : clientInfo.CpuUtilization,
State = offline ? SlaveState.Offline.ToString() : clientInfo.SlaveState.ToString(),
GroupId = client.ParentResourceId,
GroupName = parent != null ? parent.Name : null,
IsAllowedToCalculate = clientInfo.IsAllowedToCalculate
});
return new DT.ClientPage {
TotalClients = query.Count(),
Clients = query.Skip((page - 1) * size)
.Take(size)
.ToList()
};
});
}
public IEnumerable
GetClientHistory(Guid id, DateTime start, DateTime end) {
TimeSpan ts = end - start;
int increment = 1;
double totalMinutes = ts.TotalMinutes;
while (totalMinutes > 5761) {
totalMinutes -= 5761;
increment += 5;
}
var pm = PersistenceManager;
var factClientInfo = pm.FactClientInfoDao;
var clientInfos = factClientInfo.GetByClientId(id)
.Where(x => x.Time >= start && x.Time <= end)
.OrderBy(x => x.Time)
.ToList();
var clientStatus = new DT.ClientStatus {
CpuUtilization = 0,
TotalCores = 0,
UsedCores = 0,
TotalMemory = 0,
UsedMemory = 0
};
int i = 1;
foreach (var clientInfo in clientInfos) {
clientStatus.CpuUtilization += clientInfo.CpuUtilization;
clientStatus.TotalCores += clientInfo.NumTotalCores;
clientStatus.UsedCores += clientInfo.NumUsedCores;
clientStatus.TotalMemory += clientInfo.TotalMemory;
clientStatus.UsedMemory += clientInfo.UsedMemory;
if (i >= increment) {
clientStatus.Timestamp = JavascriptUtils.ToTimestamp(clientInfo.Time);
clientStatus.CpuUtilization /= i;
clientStatus.TotalCores /= i;
clientStatus.UsedCores /= i;
clientStatus.TotalMemory /= i;
clientStatus.UsedMemory /= i;
yield return clientStatus;
clientStatus = new DT.ClientStatus {
CpuUtilization = 0,
TotalCores = 0,
UsedCores = 0,
TotalMemory = 0,
UsedMemory = 0
};
i = 1;
} else {
++i;
}
}
}
public DT.ClientPage GetClientsByGroupId(Guid id, int page, int size, bool expired = false) {
var pm = PersistenceManager;
var dimClientDao = pm.DimClientDao;
var factClientInfoDao = pm.FactClientInfoDao;
return pm.UseTransaction(() => {
var clients = expired ? dimClientDao.GetAllExpiredClients() : dimClientDao.GetAllOnlineClients();
clients = clients.Where(x => x.ParentResourceId == id);
var query = (from client in clients
join info in factClientInfoDao.GetAll()
on client.Id equals info.ClientId into clientInfoJoin
from clientInfo in clientInfoJoin.OrderByDescending(x => x.Time).Take(1)
let offline = (expired || clientInfo.SlaveState == SlaveState.Offline)
let parent = client.ParentResourceId.HasValue ? dimClientDao.GetById(client.ParentResourceId.Value) : null
select new DT.Client {
Id = client.Id,
Name = client.Name,
TotalCores = clientInfo.NumTotalCores,
UsedCores = offline ? 0 : clientInfo.NumUsedCores,
TotalMemory = clientInfo.TotalMemory,
UsedMemory = offline ? 0 : clientInfo.UsedMemory,
CpuUtilization = offline ? 0 : clientInfo.CpuUtilization,
State = offline ? SlaveState.Offline.ToString() : clientInfo.SlaveState.ToString(),
GroupId = client.ParentResourceId,
GroupName = parent != null ? parent.Name : null,
IsAllowedToCalculate = clientInfo.IsAllowedToCalculate
});
return new DT.ClientPage {
TotalClients = query.Count(),
Clients = query.Skip((page - 1) * size)
.Take(size)
.ToList()
};
});
}
public IEnumerable GetClientHistoryByGroupId(Guid id, DateTime start, DateTime end) {
TimeSpan ts = end - start;
int increment = 1;
double totalMinutes = ts.TotalMinutes;
while (totalMinutes > 5761) {
totalMinutes -= 5761;
increment += 5;
}
var pm = PersistenceManager;
var factClientInfo = pm.FactClientInfoDao;
var dimClientDao = pm.DimClientDao;
var clientInfos = factClientInfo.GetAll()
.Where(x => x.Time >= start && x.Time <= end)
.OrderBy(x => x.Time)
.Join(dimClientDao.GetAll(),
fact => fact.ClientId,
client => client.Id,
(fact, client) => new {
client.ParentResourceId,
fact.Time,
fact.CpuUtilization,
fact.NumTotalCores,
fact.NumUsedCores,
fact.TotalMemory,
fact.UsedMemory
})
.Where(x => x.ParentResourceId == id)
.ToList();
var clientStatus = new DT.ClientStatus {
CpuUtilization = 0,
TotalCores = 0,
UsedCores = 0,
TotalMemory = 0,
UsedMemory = 0
};
int i = 1;
foreach (var clientInfo in clientInfos) {
clientStatus.CpuUtilization += clientInfo.CpuUtilization;
clientStatus.TotalCores += clientInfo.NumTotalCores;
clientStatus.UsedCores += clientInfo.NumUsedCores;
clientStatus.TotalMemory += clientInfo.TotalMemory;
clientStatus.UsedMemory += clientInfo.UsedMemory;
if (i >= increment) {
clientStatus.Timestamp = JavascriptUtils.ToTimestamp(clientInfo.Time);
clientStatus.CpuUtilization /= i;
clientStatus.TotalCores /= i;
clientStatus.UsedCores /= i;
clientStatus.TotalMemory /= i;
clientStatus.UsedMemory /= i;
yield return clientStatus;
clientStatus = new DT.ClientStatus {
CpuUtilization = 0,
TotalCores = 0,
UsedCores = 0,
TotalMemory = 0,
UsedMemory = 0
};
i = 1;
} else {
++i;
}
}
}
}
}