Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs @ 12484

Last change on this file since 12484 was 12484, checked in by dglaser, 9 years ago

#2388: Updated Hive, DataAccess and WebApp

HeuristicLab.Services.Hive.DataAccess:

  • Updated database statistics schema

HeuristicLab.Services.Hive:

  • Fixed event flag in HiveJanitor Service
  • Improved UpdateTaskFactsTable in the HiveStatisticsGenerator

HeuristicLab.Services.WebApp:

  • Updated Statistics DataController to match the new statistics schema
File size: 13.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Data.Linq;
25using System.Linq;
26using HeuristicLab.Services.Hive.DataAccess;
27using HeuristicLab.Services.Hive.DataAccess.Manager;
28
29namespace HeuristicLab.Services.Hive {
30  public class HiveStatisticsGenerator : IStatisticsGenerator {
31
32    private const string UnknownUserName = "Unknown";
33    private static readonly TimeSpan SmallestTimeSpan = new TimeSpan(0, 5, 0);
34
35    public void GenerateStatistics() {
36      using (var pm = new PersistenceManager()) {
37        pm.UseTransaction(() => {
38          UpdateDimUserTable(pm);
39          UpdateDimJobTable(pm);
40          UpdateDimClientsTable(pm);
41          pm.SubmitChanges();
42        });
43
44        pm.UseTransaction(() => {
45          var newTime = UpdateDimTimeTable(pm);
46          if (newTime != null) {
47            pm.SubmitChanges();
48            UpdateFactClientInfoTable(newTime, pm);
49            UpdateTaskFactsTable(newTime, pm);
50            try {
51              pm.SubmitChanges();
52            }
53            catch (DuplicateKeyException e) {
54              var logger = LogFactory.GetLogger(typeof(HiveStatisticsGenerator).Namespace);
55              logger.Log(string.Format(
56                @"Propable change from summertime to wintertime, resulting in overlapping times.
57                          On wintertime to summertime change, slave timeouts and a fact gap will occur.
58                          Exception Details: {0}", e));
59            }
60          }
61        });
62      }
63    }
64
65    private DimTime UpdateDimTimeTable(PersistenceManager pm) {
66      var dimTimeDao = pm.DimTimeDao;
67      var now = DateTime.Now;
68      var timeEntry = new DimTime {
69        Time = now,
70        Minute = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0),
71        Hour = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0),
72        Day = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0),
73        Month = new DateTime(now.Year, now.Month, 1, 0, 0, 0),
74        Year = new DateTime(now.Year, 1, 1, 0, 0, 0)
75      };
76      return dimTimeDao.Save(timeEntry);
77    }
78
79    private void UpdateDimUserTable(PersistenceManager pm) {
80      var dimUserDao = pm.DimUserDao;
81      var resourceDao = pm.ResourceDao;
82      var jobDao = pm.JobDao;
83      var existingUserIds = dimUserDao.GetAll().Select(x => x.UserId);
84      var vaildResourceOwnerIds = resourceDao.GetResourcesWithValidOwner().Select(x => x.OwnerUserId.Value);
85      var jobOwnerIds = jobDao.GetAll().Select(x => x.OwnerUserId);
86      var newUserIds = vaildResourceOwnerIds
87        .Union(jobOwnerIds)
88        .Where(id => !existingUserIds.Contains(id))
89        .ToList();
90      dimUserDao.Save(newUserIds.Select(x => new DimUser {
91        UserId = x,
92        Name = GetUserName(x)
93      }));
94    }
95
96    private void UpdateDimJobTable(PersistenceManager pm) {
97      var dimJobDao = pm.DimJobDao;
98      var jobDao = pm.JobDao;
99      var dimJobIds = dimJobDao.GetAll().Select(x => x.JobId);
100      var newJobs = jobDao.GetAll()
101        .Where(x => !dimJobIds.Contains(x.JobId))
102        .Select(x => new {
103          JobId = x.JobId,
104          UserId = x.OwnerUserId,
105          JobName = x.Name ?? string.Empty,
106          DateCreated = x.DateCreated
107        })
108        .ToList();
109      dimJobDao.Save(newJobs.Select(x => new DimJob {
110        JobId = x.JobId,
111        JobName = x.JobName,
112        UserId = x.UserId,
113        UserName = GetUserName(x.UserId),
114        DateCreated = x.DateCreated
115      }));
116    }
117
118    private void UpdateDimClientsTable(PersistenceManager pm) {
119      var dimClientDao = pm.DimClientDao;
120      var slaveDao = pm.SlaveDao;
121      var slaves = slaveDao.GetAll();
122      var recentlyAddedClients = dimClientDao.GetRecentlyAddedClients();
123      var slaveIds = slaves.Select(x => x.ResourceId);
124
125      var removedClientIds = recentlyAddedClients
126        .Where(x => !slaveIds.Contains(x.ResourceId))
127        .Select(x => x.Id);
128      var modifiedClients =
129        from slave in slaves
130        join client in recentlyAddedClients on slave.ResourceId equals client.ResourceId
131        where (slave.Name != client.Name
132               || slave.ParentResourceId != client.ResourceGroupId
133               || slave.ParentResource.ParentResourceId != client.ResourceGroup2Id)
134        select new {
135          SlaveId = slave.ResourceId,
136          ClientId = client.Id
137        };
138      var clientIds = dimClientDao.GetAll().Select(x => x.ResourceId);
139      var modifiedClientIds = modifiedClients.Select(x => x.SlaveId);
140      var newClients = slaves
141        .Where(x => !clientIds.Contains(x.ResourceId)
142                    || modifiedClientIds.Contains(x.ResourceId))
143        .Select(x => new {
144          x.ResourceId,
145          x.Name,
146          ResourceGroupId = x.ParentResourceId,
147          ResourceGroup2Id = x.ParentResource.ParentResourceId
148        })
149        .ToList();
150
151      var clientsToUpdate = removedClientIds.Union(modifiedClients.Select(x => x.ClientId));
152      dimClientDao.UpdateExpirationTime(clientsToUpdate, DateTime.Now);
153      dimClientDao.Save(newClients.Select(x => new DimClient {
154        ResourceId = x.ResourceId,
155        Name = x.Name,
156        ExpirationTime = null,
157        ResourceGroupId = x.ResourceGroupId,
158        ResourceGroup2Id = x.ResourceGroup2Id
159      }));
160    }
161
162    private void UpdateFactClientInfoTable(DimTime newTime, PersistenceManager pm) {
163      var factClientInfoDao = pm.FactClientInfoDao;
164      var slaveDao = pm.SlaveDao;
165      var dimClientDao = pm.DimClientDao;
166
167      var newRawFactInfos =
168        from s in slaveDao.GetAll()
169        join c in dimClientDao.GetRecentlyAddedClients() on s.ResourceId equals c.ResourceId
170        join lcf in factClientInfoDao.GetLastUpdateTimestamps() on c.ResourceId equals lcf.ResourceId into joinCf
171        from cf in joinCf.DefaultIfEmpty()
172        select new {
173          ClientId = c.Id,
174          UserId = s.OwnerUserId ?? Guid.Empty,
175          TotalCores = s.Cores ?? 0,
176          FreeCores = s.FreeCores ?? 0,
177          TotalMemory = s.Memory ?? 0,
178          FreeMemory = s.FreeMemory ?? 0,
179          CpuUtilization = s.CpuUtilization,
180          SlaveState = s.SlaveState,
181          IsAllowedToCalculate = s.IsAllowedToCalculate,
182          LastFactTimestamp = cf.Timestamp
183        };
184
185      factClientInfoDao.Save(
186        from x in newRawFactInfos.ToList()
187        let duration = x.LastFactTimestamp != null
188                       ? (newTime.Time - (DateTime)x.LastFactTimestamp).TotalMinutes
189                       : SmallestTimeSpan.TotalMinutes
190        select new FactClientInfo {
191          ClientId = x.ClientId,
192          DimTime = newTime,
193          UserId = x.UserId,
194          NumUsedCores = x.TotalCores - x.FreeCores,
195          NumTotalCores = x.TotalMemory,
196          UsedMemory = x.TotalMemory - x.FreeMemory,
197          TotalMemory = x.TotalMemory,
198          CpuUtilization = x.CpuUtilization,
199          SlaveState = x.SlaveState,
200          TotalTimeIdle = x.SlaveState == SlaveState.Idle && x.IsAllowedToCalculate ? duration : 0.0,
201          TotalTimeCalculating = x.SlaveState == SlaveState.Calculating ? duration : 0.0,
202          TotalTimeUnavailable = x.SlaveState == SlaveState.Idle && !x.IsAllowedToCalculate ? duration : 0.0,
203          TotalTimeOffline = x.SlaveState == SlaveState.Offline ? duration : 0.0
204        }
205      );
206    }
207
208    private void UpdateTaskFactsTable(DimTime newTime, PersistenceManager pm) {
209      var factTaskDao = pm.FactTaskDao;
210      var taskDao = pm.TaskDao;
211      var dimClientDao = pm.DimClientDao;
212      var stateLogDao = pm.StateLogDao;
213
214      var factTaskIds = factTaskDao.GetAll().Select(x => x.TaskId);
215      var notFinishedFactTasks = factTaskDao.GetNotFinishedTasks().Select(x => new {
216        x.TaskId,
217        x.LastClientId
218      });
219
220      var newTasks =
221        from task in taskDao.GetAllChildTasks()
222        let stateLogs = task.StateLogs.OrderByDescending(x => x.DateTime)
223        let lastSlaveId = stateLogs.First(x => x.SlaveId != null).SlaveId
224        where (!factTaskIds.Contains(task.TaskId)
225               || notFinishedFactTasks.Select(x => x.TaskId).Contains(task.TaskId))
226        join lastFactTask in notFinishedFactTasks on task.TaskId equals lastFactTask.TaskId into lastFactPerTask
227        from lastFact in lastFactPerTask.DefaultIfEmpty()
228        join client in dimClientDao.GetRecentlyAddedClients() on lastSlaveId equals client.ResourceId into clientsPerSlaveId
229        from client in clientsPerSlaveId.DefaultIfEmpty()
230        select new {
231          TaskId = task.TaskId,
232          JobId = task.JobId,
233          Priority = task.Priority,
234          CoresRequired = task.CoresNeeded,
235          MemoryRequired = task.MemoryNeeded,
236          State = task.State,
237          StateLogs = stateLogs.OrderBy(x => x.DateTime),
238          LastClientId = client != null
239                         ? client.Id : lastFact != null
240                         ? lastFact.LastClientId : (Guid?)null
241        };
242      factTaskDao.Save(
243        from x in newTasks.ToList()
244        let taskData = CalculateFactTaskData(x.StateLogs)
245        select new FactTask {
246          TaskId = x.TaskId,
247          JobId = x.JobId,
248          StartTime = taskData.StartTime,
249          EndTime = taskData.EndTime,
250          LastClientId = x.LastClientId,
251          Priority = x.Priority,
252          CoresRequired = x.CoresRequired,
253          MemoryRequired = x.MemoryRequired,
254          NumCalculationRuns = taskData.CalculationRuns,
255          NumRetries = taskData.Retries,
256          WaitingTime = taskData.WaitingTime,
257          CalculatingTime = taskData.CalculatingTime,
258          TransferTime = taskData.TransferTime,
259          TaskState = x.State,
260          Exception = taskData.Exception,
261          InitialWaitingTime = taskData.InitialWaitingTime
262        });
263      factTaskDao.Delete(notFinishedFactTasks.Select(x => x.TaskId));
264    }
265
266    private string GetUserName(Guid userId) {
267      try {
268        var userManager = ServiceLocator.Instance.UserManager;
269        var user = userManager.GetUserById(userId);
270        return user != null ? user.UserName : UnknownUserName;
271      }
272      catch (Exception) {
273        return UnknownUserName;
274      }
275    }
276
277    private class FactTaskData {
278      public int CalculationRuns { get; set; }
279      public int Retries { get; set; }
280      public double CalculatingTime { get; set; }
281      public double WaitingTime { get; set; }
282      public double TransferTime { get; set; }
283      public double InitialWaitingTime { get; set; }
284      public string Exception { get; set; }
285      public DateTime? StartTime { get; set; }
286      public DateTime? EndTime { get; set; }
287    }
288
289    private FactTaskData CalculateFactTaskData(IEnumerable<StateLog> stateLogs) {
290      var factTaskData = new FactTaskData();
291      var enumerator = stateLogs.GetEnumerator();
292      if (enumerator.MoveNext()) {
293        StateLog current = enumerator.Current, first = current, prev = null;
294        while (current != null) {
295          var next = enumerator.MoveNext() ? enumerator.Current : null;
296          int timeSpanInSeconds;
297          if (next != null) {
298            timeSpanInSeconds = (int)(next.DateTime - current.DateTime).TotalSeconds;
299          } else {
300            timeSpanInSeconds = (int)(DateTime.Now - current.DateTime).TotalSeconds;
301            factTaskData.Exception = current.Exception;
302          }
303          switch (current.State) {
304            case TaskState.Calculating:
305              factTaskData.CalculatingTime += timeSpanInSeconds;
306              factTaskData.CalculationRuns++;
307              if (factTaskData.CalculationRuns == 1) {
308                factTaskData.StartTime = current.DateTime;
309                factTaskData.InitialWaitingTime = (int)(current.DateTime - first.DateTime).TotalSeconds;
310              }
311              if (prev != null && prev.State != TaskState.Transferring) {
312                factTaskData.Retries++;
313              }
314              break;
315
316            case TaskState.Waiting:
317              factTaskData.WaitingTime += timeSpanInSeconds;
318              break;
319
320            case TaskState.Transferring:
321              factTaskData.TransferTime += timeSpanInSeconds;
322              break;
323
324            case TaskState.Finished:
325            case TaskState.Failed:
326            case TaskState.Aborted:
327              factTaskData.EndTime = current.DateTime;
328              break;
329          }
330          prev = current;
331          current = next;
332        }
333      }
334      return factTaskData;
335    }
336  }
337}
Note: See TracBrowser for help on using the repository browser.