Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 9577)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml	(revision 9578)
@@ -236,8 +236,9 @@
       <Column Name="ResultSize" Type="System.Int64" DbType="BigInt" CanBeNull="true" />
       <Column Name="Priority" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" />
-      <Column Name="LastClientId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
-      <Column Name="JobId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
-      <Column Name="StartTime" Type="System.DateTime" DbType="DateTime NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
-      <Column Name="EndTime" Type="System.DateTime" DbType="DateTime NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
+      <Column Name="LastClientId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" CanBeNull="false" />
+      <Column Name="JobId" Type="System.Guid" DbType="UniqueIdentifier NOT NULL" CanBeNull="false" />
+      <Column Name="StartTime" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="false" />
+      <Column Name="EndTime" Type="System.DateTime" DbType="DateTime NOT NULL" CanBeNull="true" />
+      <Column Name="TaskState" Type="global::HeuristicLab.Services.Hive.DataAccess.TaskState" DbType="varchar(30)" CanBeNull="false" />
       <Association Name="DimClient_FactTask" Member="DimClient" ThisKey="LastClientId" OtherKey="Id" Type="DimClient" IsForeignKey="true" />
       <Association Name="DimJob_FactTask" Member="DimJob" ThisKey="JobId" OtherKey="JobId" Type="DimJob" IsForeignKey="true" />
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 9577)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.dbml.layout	(revision 9578)
@@ -253,8 +253,8 @@
       </nestedChildShapes>
     </classShape>
-    <classShape Id="04f52807-ce17-4d65-bd23-cc38c6dfbd7a" absoluteBounds="6.875, 11.25, 2, 3.2326684570312523">
+    <classShape Id="04f52807-ce17-4d65-bd23-cc38c6dfbd7a" absoluteBounds="6.875, 11.25, 2, 3.3970157877604166">
       <DataClassMoniker Name="/HiveDataContext/FactTask" />
       <nestedChildShapes>
-        <elementListCompartment Id="63e3ddcb-a6fe-48e0-a674-e650a55a9f2c" absoluteBounds="6.8900000000000006, 11.71, 1.9700000000000002, 2.67266845703125" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
+        <elementListCompartment Id="63e3ddcb-a6fe-48e0-a674-e650a55a9f2c" absoluteBounds="6.8900000000000006, 11.71, 1.9700000000000002, 2.8370157877604165" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" />
       </nestedChildShapes>
     </classShape>
@@ -283,5 +283,5 @@
       </nestedChildShapes>
     </classShape>
-    <associationConnector edgePoints="[(6.625 : 16.1191239261004); (7.875 : 16.1191239261004); (7.875 : 14.4826684570313)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(6.625 : 15.25); (6.875 : 14.6470157877604)]" fixedFrom="NotFixed" fixedTo="NotFixed">
       <AssociationMoniker Name="/HiveDataContext/DimClient/DimClient_FactTask" />
       <nodes>
@@ -290,5 +290,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(8.5 : 10.5498478190104); (8.5 : 11.25)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(8.5 : 10.5498478190104); (8.5 : 11.25)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/DimJob/DimJob_FactTask" />
       <nodes>
@@ -297,5 +297,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(5.15625 : 10.0891951497396); (5.15625 : 14.3889184570313); (6.875 : 14.3889184570313)]" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(5.02343625 : 10.0891951497396); (5.02343625 : 14.4398396223958); (6.875 : 14.4398396223958)]" fixedFrom="Algorithm" fixedTo="Algorithm">
       <AssociationMoniker Name="/HiveDataContext/DimTime/DimTime_FactTask" />
       <nodes>
@@ -304,5 +304,5 @@
       </nodes>
     </associationConnector>
-    <associationConnector edgePoints="[(5.4218775 : 10.0891951497396); (5.4218775 : 13.3576659570313); (6.71675495975 : 13.3576659570313); (6.71675495975 : 13.359301744963); (6.875 : 13.359301744963)]" manuallyRouted="true" fixedFrom="NotFixed" fixedTo="NotFixed">
+    <associationConnector edgePoints="[(5.4218775 : 10.0891951497396); (5.4218775 : 13.3576659570313); (6.71675495975 : 13.3576659570313); (6.71675495975 : 13.4665376449926); (6.875 : 13.4665376449926)]" manuallyRouted="true" fixedFrom="NotFixed" fixedTo="NotFixed">
       <AssociationMoniker Name="/HiveDataContext/DimTime/DimTime_FactTask1" />
       <nodes>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 9577)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HiveDataContext.designer.cs	(revision 9578)
@@ -4884,5 +4884,7 @@
 		private System.DateTime _StartTime;
 		
-		private System.DateTime _EndTime;
+		private System.Nullable<System.DateTime> _EndTime;
+		
+		private global::HeuristicLab.Services.Hive.DataAccess.TaskState _TaskState;
 		
 		private EntityRef<DimClient> _DimClient;
@@ -4926,6 +4928,8 @@
     partial void OnStartTimeChanging(System.DateTime value);
     partial void OnStartTimeChanged();
-    partial void OnEndTimeChanging(System.DateTime value);
+    partial void OnEndTimeChanging(System.Nullable<System.DateTime> value);
     partial void OnEndTimeChanged();
+    partial void OnTaskStateChanging(global::HeuristicLab.Services.Hive.DataAccess.TaskState value);
+    partial void OnTaskStateChanged();
     #endregion
 		
@@ -5159,5 +5163,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_LastClientId", DbType="UniqueIdentifier NOT NULL", IsPrimaryKey=true)]
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_LastClientId", DbType="UniqueIdentifier NOT NULL")]
 		public System.Guid LastClientId
 		{
@@ -5183,5 +5187,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_JobId", DbType="UniqueIdentifier NOT NULL", IsPrimaryKey=true)]
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_JobId", DbType="UniqueIdentifier NOT NULL")]
 		public System.Guid JobId
 		{
@@ -5207,5 +5211,5 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_StartTime", DbType="DateTime NOT NULL", IsPrimaryKey=true)]
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_StartTime", DbType="DateTime NOT NULL")]
 		public System.DateTime StartTime
 		{
@@ -5231,6 +5235,6 @@
 		}
 		
-		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_EndTime", DbType="DateTime NOT NULL", IsPrimaryKey=true)]
-		public System.DateTime EndTime
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_EndTime", DbType="DateTime NOT NULL")]
+		public System.Nullable<System.DateTime> EndTime
 		{
 			get
@@ -5255,4 +5259,24 @@
 		}
 		
+		[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_TaskState", DbType="varchar(30)", CanBeNull=false)]
+		public global::HeuristicLab.Services.Hive.DataAccess.TaskState TaskState
+		{
+			get
+			{
+				return this._TaskState;
+			}
+			set
+			{
+				if ((this._TaskState != value))
+				{
+					this.OnTaskStateChanging(value);
+					this.SendPropertyChanging();
+					this._TaskState = value;
+					this.SendPropertyChanged("TaskState");
+					this.OnTaskStateChanged();
+				}
+			}
+		}
+		
 		[global::System.Data.Linq.Mapping.AssociationAttribute(Name="DimClient_FactTask", Storage="_DimClient", ThisKey="LastClientId", OtherKey="Id", IsForeignKey=true)]
 		public DimClient DimClient
@@ -5350,5 +5374,5 @@
 					else
 					{
-						this._EndTime = default(System.DateTime);
+						this._EndTime = default(Nullable<System.DateTime>);
 					}
 					this.SendPropertyChanged("DimTimeEnd");
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 9577)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Initialize Hive Database.sql	(revision 9578)
@@ -267,6 +267,7 @@
     [JobId]              UNIQUEIDENTIFIER NOT NULL,
     [StartTime]          DATETIME         NOT NULL,
-    [EndTime]            DATETIME         NOT NULL,
-    CONSTRAINT [PK_FactTask] PRIMARY KEY CLUSTERED ([TaskId] ASC, [LastClientId] ASC, [JobId] ASC, [StartTime] ASC, [EndTime] ASC),
+    [EndTime]            DATETIME         NULL,
+	[TaskState]          VARCHAR (30)     NOT NULL,
+    CONSTRAINT [PK_FactTask] PRIMARY KEY CLUSTERED ([TaskId] ASC),
     CONSTRAINT [FK_FactTask_DimClient] FOREIGN KEY ([LastClientId]) REFERENCES [statistics].[DimClient] ([Id]),
     CONSTRAINT [FK_FactTask_DimJob] FOREIGN KEY ([JobId]) REFERENCES [statistics].[DimJob] ([JobId]),
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs	(revision 9577)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/HiveStatisticsGenerator.cs	(revision 9578)
@@ -223,65 +223,61 @@
 
     private void UpdateTaskFacts(DimTime newTime, HiveDataContext db) {
-      var time = newTime.Time;
-
-      var lastFacts =
+      // old Task facts
+      var oldFacts =
         from fact in db.FactTasks
-        group fact by fact.TaskId into factsPerTask
-        select factsPerTask.OrderByDescending(x => x.EndTime).First();
-
-      var lastFactAndStateLogsAndLastClientPerTask =
-        from task in db.Tasks.Where(task => !task.IsParentTask)
-        join lastFact in lastFacts on task.TaskId equals lastFact.TaskId into lastFactsPerTask
-        from lastFact in lastFactsPerTask.DefaultIfEmpty()
-        let newStateLogs = task.StateLogs.Where(stateLog => (lastFact == null || stateLog.DateTime > lastFact.EndTime) && stateLog.DateTime < time)
-        let lastStateLog = lastFact == null ? null : (task.StateLogs.Where(stateLog => stateLog.DateTime < lastFact.EndTime).OrderByDescending(stateLog => stateLog.DateTime).First())
-        let lastSlaveId = newStateLogs.OrderByDescending(stateLog => stateLog.DateTime).First(stateLog => stateLog.SlaveId != null).SlaveId
-        join client in db.DimClients.Where(client => client.ExpirationTime == null) on lastSlaveId equals client.ResourceId into clientPerTask
-        from client in clientPerTask.DefaultIfEmpty()
-        where newStateLogs.Any()
+        where fact.EndTime == null
+        select fact;
+
+      // query Task facts data
+      var newFacts =
+        from task in db.Tasks
+        where !task.IsParentTask
+          && (!db.FactTasks.Select(fact => fact.TaskId).Contains(task.TaskId) || oldFacts.Select(fact => fact.TaskId).Contains(task.TaskId))
+        join lastFact in oldFacts on task.TaskId equals lastFact.TaskId into lastFactPerTask
+        from lastFact in lastFactPerTask.DefaultIfEmpty()
+        let lastSlaveId = task.StateLogs.OrderByDescending(sl => sl.DateTime).First(sl => sl.SlaveId != null).SlaveId
+        join client in db.DimClients.Where(client => client.ExpirationTime == null) on lastSlaveId equals client.ResourceId into clientsPerSlaveId
+        from client in clientsPerSlaveId.DefaultIfEmpty()
         select new {
           Task = task,
           TaskDataSize = task.JobData.DataSize,
-          LastFact = lastFact,
-          StateLogs = newStateLogs.OrderBy(stateLog => stateLog.DateTime),
-          LastStateLog = lastStateLog,
-          LastClientId = client != null ? client.Id : default(Guid?)
-        };
-
+          StateLogs = task.StateLogs.OrderBy(sl => sl.DateTime),
+          LastClientId = client != null ? client.Id : default(Guid?),
+          LastFact = lastFact
+        };
+
+      // new Task facts
       var newTaskFacts =
-        from t in lastFactAndStateLogsAndLastClientPerTask.ToList()
-        let stateLogsLinkedList = t.LastStateLog == null ? new LinkedList<StateLog>(t.StateLogs) : new LinkedList<StateLog>(t.StateLogs).AddFirst(t.LastStateLog).List
+        from t in newFacts.ToList()
+        let stateLogsLinkedList = new LinkedList<StateLog>(t.StateLogs)
         select new FactTask {
           TaskId = t.Task.TaskId,
           JobId = t.Task.JobId,
           DimTimeStart = t.LastFact != null ? t.LastFact.DimTimeStart : newTime,
-          DimTimeEnd = newTime,
+          DimTimeEnd = new[] { TaskState.Finished, TaskState.Failed, TaskState.Aborted }.Contains(t.Task.State) ? newTime : null,
           LastClientId = t.LastClientId ?? (t.LastFact != null ? t.LastFact.LastClientId : Guid.Empty),
           Priority = t.Task.Priority,
           CoresRequired = t.Task.CoresNeeded,
           MemoryRequired = t.Task.MemoryNeeded,
-          TaskSize = t.LastFact != null ? t.LastFact.TaskSize : t.TaskDataSize,
+          TaskSize = t.LastFact == null ? t.TaskDataSize : t.LastFact.TaskSize,
           ResultSize = t.Task.State == TaskState.Finished ? t.TaskDataSize : default(long?),
-          NumCalculationRuns =
-            (t.LastFact != null ? t.LastFact.NumCalculationRuns : 0) +
-            t.StateLogs.Count(x => x.State == TaskState.Calculating),
-          NumRetries =
-            (t.LastFact != null ? t.LastFact.NumRetries : 0) +
-            stateLogsLinkedList.EnumerateNodes().Count(sl => sl.Value.State == TaskState.Calculating && sl.Next != null && !sl.NextIs(nsl => nsl.State == TaskState.Transferring)),       //TotalWaitingTime = SumTotalWaitingTime(t.LastFact, stateLogsLinkedList),
-          TotalWaitingTime = SumTotalTime(t.LastFact, fact => fact.TotalWaitingTime, stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Waiting),
-          TotalRuntime = SumTotalTime(t.LastFact, fact => fact.TotalRuntime, stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Calculating && stateLog.NextIs(x => x.State == TaskState.Transferring)),
-          TotalTransferTime = SumTotalTime(t.LastFact, fact => fact.TotalTransferTime, stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Transferring)
-        };
-
+          NumCalculationRuns = stateLogsLinkedList.EnumerateNodes()
+            .Count(sl => sl.Value.State == TaskState.Calculating && sl.NextIs(nsl => nsl.State == TaskState.Transferring)),
+          NumRetries = stateLogsLinkedList.EnumerateNodes()
+            .Count(sl => sl.Value.State == TaskState.Calculating && sl.Next != null && sl.NextIs(nsl => nsl.State != TaskState.Transferring)),
+          TotalWaitingTime = SumTotalTime(stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Waiting),
+          TotalRuntime = SumTotalTime(stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Calculating && stateLog.NextIs(x => x.State == TaskState.Transferring)),
+          TotalTransferTime = SumTotalTime(stateLogsLinkedList, stateLog => stateLog.Value.State == TaskState.Transferring),
+          TaskState = t.Task.State
+        };
+
+      db.FactTasks.DeleteAllOnSubmit(oldFacts.ToList());
       db.FactTasks.InsertAllOnSubmit(newTaskFacts);
     }
 
-    private double SumTotalTime(FactTask lastFact, Func<FactTask, double> lastValue, LinkedList<StateLog> stateLogs, Predicate<LinkedListNode<StateLog>> predicate) {
-      double sum = lastFact != null ? lastValue(lastFact) : 0.0;
-
-      sum += stateLogs.EnumerateNodes()
+    private double SumTotalTime(LinkedList<StateLog> stateLogs, Predicate<LinkedListNode<StateLog>> predicate) {
+      return stateLogs.EnumerateNodes()
                       .Where(sl => predicate(sl))
                       .Sum(stateLog => stateLog.Next != null ? (stateLog.Next.Value.DateTime - stateLog.Value.DateTime).TotalMinutes : 0);
-      return sum;
     }
   }
