Index: /branches/HiveStatistics/sources/HeuristicLab 3.3 Services.sln
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab 3.3 Services.sln	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab 3.3 Services.sln	(revision 12761)
@@ -71,5 +71,5 @@
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Services.WebApp.Statistics-3.3", "HeuristicLab.Services.WebApp.Statistics\3.3\HeuristicLab.Services.WebApp.Statistics-3.3.csproj", "{1BC54353-7D4C-4734-BAA9-3D11B3242B59}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleServiceTest", "ConsoleServiceTest\ConsoleServiceTest.csproj", "{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.Services.WebApp.Maintenance-3.3", "HeuristicLab.Services.WebApp.Maintenance\3.3\HeuristicLab.Services.WebApp.Maintenance-3.3.csproj", "{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}"
 EndProject
 Global
@@ -258,12 +258,12 @@
 		{1BC54353-7D4C-4734-BAA9-3D11B3242B59}.Release|x86.ActiveCfg = Release|x86
 		{1BC54353-7D4C-4734-BAA9-3D11B3242B59}.Release|x86.Build.0 = Release|x86
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Release|Any CPU.Build.0 = Release|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Release|x64.ActiveCfg = Release|Any CPU
-		{72EAF349-27C8-4CFE-B03B-47E2C5E124FD}.Release|x86.ActiveCfg = Release|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Release|x64.ActiveCfg = Release|Any CPU
+		{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/DimTimeDao.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/DimTimeDao.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/DimTimeDao.cs	(revision 12761)
@@ -31,6 +31,11 @@
       return GetByIdQuery(DataContext, id);
     }
+
     public DimTime GetLastEntry() {
       return GetLastEntryQuery(DataContext);
+    }
+
+    public int DeleteUnusedTimes() {
+      return DataContext.ExecuteCommand(DeleteUnusedTimeEntriesStringQuery);
     }
 
@@ -48,4 +53,12 @@
          select dimTime).FirstOrDefault());
     #endregion
+
+    #region String queries
+    private const string DeleteUnusedTimeEntriesStringQuery = @"
+      DELETE FROM [statistics].[DimTime]
+      WHERE NOT EXISTS (SELECT [Time] FROM [statistics].[FactClientInfo] fci
+                        WHERE fci.[Time] = [statistics].[DimTime].[Time]);    
+    ";
+    #endregion
   }
 }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/FactTaskDao.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/FactTaskDao.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/HiveStatistics/FactTaskDao.cs	(revision 12761)
@@ -89,4 +89,8 @@
     }
 
+    public void DeleteByJobId(Guid jobId) {
+      DataContext.ExecuteCommand(DeleteByJobIdQuery, jobId);
+    }
+
     #region Compiled queries
     private static readonly Func<DataContext, Guid, FactTask> GetByIdQuery =
@@ -108,4 +112,8 @@
       @"DELETE FROM [statistics].[FactTask]
          WHERE TaskId IN ({0});";
+
+    private const string DeleteByJobIdQuery =
+      @"DELETE FROM [statistics].[FactTask]
+         WHERE JobId = {0};";
     #endregion
   }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/PluginDao.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/PluginDao.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Daos/PluginDao.cs	(revision 12761)
@@ -37,4 +37,8 @@
     }
 
+    public int DeleteUnusedPlugins() {
+      return DataContext.ExecuteCommand(DeleteUnusedPluginsStringQuery);
+    }
+
     #region Compiled queries
     private static readonly Func<DataContext, Guid, Plugin> GetByIdQuery =
@@ -50,4 +54,17 @@
          select plugin));
     #endregion
+
+    #region String queries
+    private const string DeleteUnusedPluginsStringQuery = @"
+      DELETE FROM [Plugin]
+      WHERE  [Plugin].[PluginId] NOT IN (
+        SELECT DISTINCT rp.[PluginId] 
+        FROM [RequiredPlugins] rp
+        WHERE EXISTS (SELECT [TaskId] 
+                      FROM [Task] t
+                      WHERE t.[TaskId] = rp.[TaskId])
+      );
+    ";
+    #endregion
   }
 }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Data/TableInformation.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Data/TableInformation.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Data/TableInformation.cs	(revision 12761)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Services.Hive.DataAccess.Data {
+  public class TableInformation {
+    public string Name { get; set; }
+    public int Rows { get; set; }
+    public int Reserved { get; set; }
+    public int Data { get; set; }
+    public int IndexSize { get; set; }
+    public int Unused { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/HeuristicLab.Services.Hive.DataAccess-3.3.csproj	(revision 12761)
@@ -127,4 +127,5 @@
     <Compile Include="Daos\TaskDataDao.cs" />
     <Compile Include="Daos\UserPriorityDao.cs" />
+    <Compile Include="Data\TableInformation.cs" />
     <Compile Include="Interfaces\IGenericDao.cs" />
     <Compile Include="Enums\Command.cs" />
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Interfaces/IPersistenceManager.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Interfaces/IPersistenceManager.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Interfaces/IPersistenceManager.cs	(revision 12761)
@@ -24,4 +24,5 @@
 using HeuristicLab.Services.Hive.DataAccess.Daos;
 using HeuristicLab.Services.Hive.DataAccess.Daos.HiveStatistics;
+using HeuristicLab.Services.Hive.DataAccess.Data;
 
 namespace HeuristicLab.Services.Hive.DataAccess.Interfaces {
@@ -62,4 +63,5 @@
     #endregion
 
+    TableInformation GetTableInformation(string table);
     void SubmitChanges();
   }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Manager/PersistenceManager.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Manager/PersistenceManager.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/Manager/PersistenceManager.cs	(revision 12761)
@@ -22,7 +22,9 @@
 using System;
 using System.Data.Linq;
+using System.Linq;
 using System.Transactions;
 using HeuristicLab.Services.Hive.DataAccess.Daos;
 using HeuristicLab.Services.Hive.DataAccess.Daos.HiveStatistics;
+using HeuristicLab.Services.Hive.DataAccess.Data;
 using HeuristicLab.Services.Hive.DataAccess.Interfaces;
 
@@ -200,4 +202,19 @@
     #endregion
 
+    // str.Remove(str.IndexOf(','));
+    public TableInformation GetTableInformation(string table) {
+      string query = string.Format("sp_spaceused '{0}', @updateusage='true'", table);
+      var result = dataContext.ExecuteQuery<SqlServerTableInformation>(query).FirstOrDefault();
+      if (result == null) return null;
+      return new TableInformation {
+        Name = result.Name,
+        Rows = int.Parse(result.Rows.Remove(result.Rows.IndexOf(' '))),
+        Reserved = int.Parse(result.Reserved.Remove(result.Reserved.IndexOf(' '))),
+        Data = int.Parse(result.Data.Remove(result.Data.IndexOf(' '))),
+        IndexSize = int.Parse(result.Index_Size.Remove(result.Index_Size.IndexOf(' '))),
+        Unused = int.Parse(result.Unused.Remove(result.Unused.IndexOf(' ')))
+      };
+    }
+
     public void SubmitChanges() {
       if (dataContext != null) {
@@ -211,4 +228,13 @@
       //}
     }
+
+    private class SqlServerTableInformation {
+      public string Name { get; set; }
+      public string Rows { get; set; }
+      public string Reserved { get; set; }
+      public string Data { get; set; }
+      public string Index_Size { get; set; } // naming of sp_spaceused...
+      public string Unused { get; set; }
+    }
   }
 }
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive.DataAccess/3.3/SQL Scripts/Prepare Hive Database.sql	(revision 12761)
@@ -182,6 +182,6 @@
 CREATE TRIGGER [dbo].[tr_JobDeleteCascade] ON [dbo].[Job] INSTEAD OF DELETE AS 
 BEGIN
-	DELETE Task FROM deleted, Task WHERE deleted.JobId = Task.JobId
-	DELETE Job FROM deleted, Job WHERE deleted.JobId = Job.JobId
+    DELETE Task FROM deleted, Task WHERE deleted.JobId = Task.JobId
+    DELETE Job FROM deleted, Job WHERE deleted.JobId = Job.JobId
 END
 GO
@@ -194,45 +194,45 @@
 CREATE TRIGGER [dbo].[tr_TaskDeleteCascade] ON [dbo].[Task] INSTEAD OF DELETE AS 
 BEGIN
-	-- add statistics
-	INSERT INTO dbo.DeletedJobStatistics (UserId, ExecutionTimeS, ExecutionTimeSFinishedJobs, StartToEndTimeS)
-	SELECT 
-		he.OwnerUserId AS UserId, 
-		ROUND(SUM(j.ExecutionTimeMs) / 1000, 0) AS ExecutionTimeS,  
-		ROUND(ISNULL(SUM(CASE ls.State WHEN 'Finished' THEN j.ExecutionTimeMs END), 0) / 1000, 0) AS ExecutionTimeSFinishedJobs,
-		ISNULL(SUM(CASE ls.State WHEN 'Finished' THEN DATEDIFF(s, fs.DateTime, ls.DateTime) ELSE 0 END), 0) AS StartToEndTimeS
-	FROM 
-		deleted j, 
-		Job he, 
-		view_FirstState fs, 
-		view_LastState ls
-	WHERE 
-		he.JobId = j.JobId AND 
-		fs.TaskId = j.TaskId AND 
-		ls.TaskId = j.TaskId
-	GROUP BY he.OwnerUserId
-
-	-- recursively delete jobs
-	CREATE TABLE #Table( 
-		TaskId uniqueidentifier 
-	)
-	INSERT INTO #Table (TaskId)
-	SELECT TaskId FROM deleted
-	
-	DECLARE @c INT
-	SET @c = 0
-	
-	WHILE @c <> (SELECT COUNT(TaskId) FROM #Table) BEGIN
-		SELECT @c = COUNT(TaskId) FROM #Table
-		
-		INSERT INTO #Table (TaskId)
-			SELECT Task.TaskId
-			FROM Task
-			LEFT OUTER JOIN #Table ON Task.TaskId = #Table.TaskId
-			WHERE Task.ParentTaskId IN (SELECT TaskId FROM #Table)
-				AND #Table.TaskId IS NULL
-	END
-	
-	DELETE TaskData FROM TaskData INNER JOIN #Table ON TaskData.TaskId = #Table.TaskId
-	DELETE Task FROM Task INNER JOIN #Table ON Task.TaskId = #Table.TaskId
+    -- add statistics
+    INSERT INTO dbo.DeletedJobStatistics (UserId, ExecutionTimeS, ExecutionTimeSFinishedJobs, StartToEndTimeS)
+    SELECT 
+        he.OwnerUserId AS UserId, 
+        ROUND(SUM(j.ExecutionTimeMs) / 1000, 0) AS ExecutionTimeS,  
+        ROUND(ISNULL(SUM(CASE ls.State WHEN 'Finished' THEN j.ExecutionTimeMs END), 0) / 1000, 0) AS ExecutionTimeSFinishedJobs,
+        ISNULL(SUM(CASE ls.State WHEN 'Finished' THEN DATEDIFF(s, fs.DateTime, ls.DateTime) ELSE 0 END), 0) AS StartToEndTimeS
+    FROM 
+        deleted j, 
+        Job he, 
+        view_FirstState fs, 
+        view_LastState ls
+    WHERE 
+        he.JobId = j.JobId AND 
+        fs.TaskId = j.TaskId AND 
+        ls.TaskId = j.TaskId
+    GROUP BY he.OwnerUserId
+
+    -- recursively delete jobs
+    CREATE TABLE #Table( 
+        TaskId uniqueidentifier 
+    )
+    INSERT INTO #Table (TaskId)
+    SELECT TaskId FROM deleted
+    
+    DECLARE @c INT
+    SET @c = 0
+    
+    WHILE @c <> (SELECT COUNT(TaskId) FROM #Table) BEGIN
+        SELECT @c = COUNT(TaskId) FROM #Table
+        
+        INSERT INTO #Table (TaskId)
+            SELECT Task.TaskId
+            FROM Task
+            LEFT OUTER JOIN #Table ON Task.TaskId = #Table.TaskId
+            WHERE Task.ParentTaskId IN (SELECT TaskId FROM #Table)
+                AND #Table.TaskId IS NULL
+    END
+    
+    DELETE TaskData FROM TaskData INNER JOIN #Table ON TaskData.TaskId = #Table.TaskId
+    DELETE Task FROM Task INNER JOIN #Table ON Task.TaskId = #Table.TaskId
 END
 GO
@@ -241,7 +241,7 @@
 CREATE TRIGGER [dbo].[tr_StatisticsDeleteCascade] ON [dbo].[Statistics] INSTEAD OF DELETE AS 
 BEGIN
-	DELETE SlaveStatistics FROM deleted, SlaveStatistics WHERE deleted.StatisticsId = SlaveStatistics.StatisticsId
-	-- should also remove UserStatistics here 
-	DELETE [Statistics] FROM deleted, [Statistics] WHERE deleted.StatisticsId = [Statistics].StatisticsId
+    DELETE SlaveStatistics FROM deleted, SlaveStatistics WHERE deleted.StatisticsId = SlaveStatistics.StatisticsId
+    -- should also remove UserStatistics here 
+    DELETE [Statistics] FROM deleted, [Statistics] WHERE deleted.StatisticsId = [Statistics].StatisticsId
 END
 GO
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs	(revision 12761)
@@ -234,5 +234,5 @@
 
     [OperationContract]
-    void UpdateDowntime(Downtime downtime);
+    void UpdateDowntime(Downtime downtimeDto);
 
     [OperationContract]
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/HeuristicLab.Services.WebApp.Maintenance-3.3.csproj
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/HeuristicLab.Services.WebApp.Maintenance-3.3.csproj	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/HeuristicLab.Services.WebApp.Maintenance-3.3.csproj	(revision 12761)
@@ -0,0 +1,157 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{3F22B7DA-FDDB-48F0-8BB7-0ABA5120FC87}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HeuristicLab.Services.WebApp.Maintenance</RootNamespace>
+    <AssemblyName>HeuristicLab.Services.WebApp.Maintenance-3.3</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>HeuristicLab.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System.Web.Http.WebHost, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="WebApi\DataTransfer\FactClientInfo.cs" />
+    <Compile Include="WebApi\DataTransfer\Job.cs" />
+    <Compile Include="WebApi\DataTransfer\JobPage.cs" />
+    <Compile Include="WebApi\DataTransfer\Plugin.cs" />
+    <Compile Include="WebApi\DataTransfer\PluginPage.cs" />
+    <Compile Include="WebApi\DataTransfer\TableInformation.cs" />
+    <Compile Include="WebApi\FactClientInfoController.cs" />
+    <Compile Include="WebApi\FactTaskController.cs" />
+    <Compile Include="WebApi\PluginController.cs" />
+    <Compile Include="WebApi\SpaceUsageController.cs" />
+    <Compile Include="WebApi\CleanupController.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+    <None Include="HeuristicLab.snk" />
+    <None Include="packages.config" />
+    <Content Include="WebApp\factclientinfo\factclientinfoCtrl.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\facttask\facttaskCtrl.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\plugin\plugin.cshtml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <None Include="WebApp\factclientinfo\factclientinfo.cshtml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Include="WebApp\facttask\facttask.cshtml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+    <None Include="WebApp\spaceUsage\spaceUsage.cshtml">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="maintenance.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\plugin\pluginCtrl.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\services\factclientinfoService.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\services\facttaskService.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\services\pluginService.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\services\spaceUsageService.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="WebApp\spaceUsage\spaceUsageCtrl.js">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <ProjectReference Include="..\..\HeuristicLab.Services.Hive.DataAccess\3.3\HeuristicLab.Services.Hive.DataAccess-3.3.csproj">
+      <Project>{EC2C8109-6E1E-4C88-9A2B-908CFF2EF4AC}</Project>
+      <Name>HeuristicLab.Services.Hive.DataAccess-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Services.Hive\3.3\HeuristicLab.Services.Hive-3.3.csproj">
+      <Project>{CF9DA321-AC1B-4FD3-9EC3-67BC6B861BDE}</Project>
+      <Name>HeuristicLab.Services.Hive-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
+  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs	(revision 12761)
@@ -0,0 +1,36 @@
+﻿using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Services.WebApp.Maintenance-3.3")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab.Services.WebApp.Maintenance-3.3")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e6a974eb-73cc-4bf9-bec0-c8ace0d33b3e")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs.frame
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs.frame	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/Properties/AssemblyInfo.cs.frame	(revision 12761)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("HeuristicLab.Services.WebApp")]
+[assembly: AssemblyDescription("HeuristicLab Services Application Container")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("HeuristicLab")]
+[assembly: AssemblyCopyright("(c) 2002-2015 HEAL")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("daa57a9d-2df7-4b13-80b5-2496239ba459")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.3.0.0")]
+[assembly: AssemblyFileVersion("3.3.11.$WCREV$")]
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/CleanupController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/CleanupController.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/CleanupController.cs	(revision 12761)
@@ -0,0 +1,167 @@
+﻿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.Maintenance.WebApi.DataTransfer;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi {
+  public class CleanupController : ApiController {
+
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    [HttpGet, HttpPost]
+    public bool CleanupJob(Guid jobId) {
+      using (var pm = PersistenceManager) {
+        var jobDao = pm.JobDao;
+        var factTaskDao = pm.FactTaskDao;
+        return pm.UseTransaction(() => {
+          if (jobDao.Exists(jobId)) return false;
+          var jobTimeData = factTaskDao.GetByJobId(jobId).GroupBy(x => x.JobId).Select(x => new {
+            CalculatingTime = x.Sum(y => y.CalculatingTime),
+            WaitingTime = x.Sum(y => y.WaitingTime),
+            TransferTime = x.Sum(y => y.TransferTime),
+            InitialWaitingTime = x.Sum(y => y.InitialWaitingTime),
+            StartTime = x.Min(y => y.StartTime),
+            EndTime = x.Max(y => y.EndTime)
+          }).SingleOrDefault();
+          factTaskDao.DeleteByJobId(jobId);
+          factTaskDao.Save(new FactTask {
+            TaskId = Guid.NewGuid(),
+            JobId = jobId,
+            CalculatingTime = jobTimeData.CalculatingTime,
+            WaitingTime = jobTimeData.WaitingTime,
+            TransferTime = jobTimeData.TransferTime,
+            InitialWaitingTime = jobTimeData.InitialWaitingTime,
+            StartTime = jobTimeData.StartTime,
+            EndTime = jobTimeData.EndTime,
+            NumCalculationRuns = 0,
+            NumRetries = 0,
+            CoresRequired = 0,
+            MemoryRequired = 0,
+            Priority = 0,
+            TaskState = TaskState.Finished
+          });
+          pm.SubmitChanges();
+          return true;
+        });
+      }
+    }
+
+    [HttpGet, HttpPost]
+    public void AggregateClient(Guid clientId, int entries) {
+      using (var pm = PersistenceManager) {
+        var factClientInfoDao = pm.FactClientInfoDao;
+        var clientInfos = pm.UseTransaction(() => factClientInfoDao.GetByClientId(clientId).OrderBy(x => x.Time).ToList());
+        FactClientInfo lastClientInfo = null, sumClientInfo = new FactClientInfo();
+        int counter = 0;
+        var aggregatedClientInfos = new List<FactClientInfo>();
+        foreach (var clientInfo in clientInfos) {
+          if (lastClientInfo != null) {
+            if (lastClientInfo.SlaveState != clientInfo.SlaveState ||
+                lastClientInfo.IsAllowedToCalculate != clientInfo.IsAllowedToCalculate) {
+              // update into 'lastClientInfo'
+              if (aggregatedClientInfos.Any()) {
+                counter = aggregatedClientInfos.Count();
+                pm.UseTransaction(() => {
+                  factClientInfoDao.Delete(aggregatedClientInfos);
+                  lastClientInfo.NumUsedCores = sumClientInfo.NumUsedCores / counter;
+                  lastClientInfo.NumTotalCores = sumClientInfo.NumTotalCores / counter;
+                  lastClientInfo.UsedMemory = sumClientInfo.UsedMemory / counter;
+                  lastClientInfo.TotalMemory = sumClientInfo.TotalMemory / counter;
+                  lastClientInfo.CpuUtilization = sumClientInfo.CpuUtilization / counter;
+                  lastClientInfo.IdleTime = sumClientInfo.IdleTime;
+                  lastClientInfo.OfflineTime = sumClientInfo.OfflineTime;
+                  lastClientInfo.UnavailableTime = sumClientInfo.UnavailableTime;
+                  pm.SubmitChanges();
+                });
+              }
+              aggregatedClientInfos.Clear();
+              counter = 0;
+              sumClientInfo = new FactClientInfo();
+            } else {
+              // sum up 
+              sumClientInfo.NumUsedCores += clientInfo.NumUsedCores;
+              sumClientInfo.NumTotalCores += clientInfo.NumTotalCores;
+              sumClientInfo.UsedMemory += clientInfo.UsedMemory;
+              sumClientInfo.TotalMemory += clientInfo.TotalMemory;
+              sumClientInfo.CpuUtilization += clientInfo.CpuUtilization;
+              sumClientInfo.IdleTime += clientInfo.IdleTime;
+              sumClientInfo.OfflineTime += clientInfo.OfflineTime;
+              sumClientInfo.UnavailableTime += clientInfo.UnavailableTime;
+              counter++;
+              if (counter >= entries) {
+                pm.UseTransaction(() => {
+                  factClientInfoDao.Delete(aggregatedClientInfos);
+                  clientInfo.NumUsedCores = sumClientInfo.NumUsedCores / counter;
+                  clientInfo.NumTotalCores = sumClientInfo.NumTotalCores / counter;
+                  clientInfo.UsedMemory = sumClientInfo.UsedMemory / counter;
+                  clientInfo.TotalMemory = sumClientInfo.TotalMemory / counter;
+                  clientInfo.CpuUtilization = sumClientInfo.CpuUtilization / counter;
+                  clientInfo.IdleTime = sumClientInfo.IdleTime;
+                  clientInfo.OfflineTime = sumClientInfo.OfflineTime;
+                  clientInfo.UnavailableTime = sumClientInfo.UnavailableTime;
+                  pm.SubmitChanges();
+                });
+                aggregatedClientInfos.Clear();
+                counter = 0;
+                sumClientInfo = new FactClientInfo();
+              } else {
+                aggregatedClientInfos.Add(clientInfo);
+              }
+            }
+          }
+          lastClientInfo = clientInfo;
+        }
+      }
+    }
+
+    public IEnumerable<DT.Plugin> GetUnusedPlugins() {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        var requiredPluginDao = pm.RequiredPluginDao;
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          var taskIds = taskDao.GetAll().Select(x => x.TaskId);
+          var usedPluginIds = requiredPluginDao.GetAll()
+            .Where(x => taskIds.Contains(x.TaskId))
+            .Select(x => x.PluginId)
+            .Distinct();
+          return pluginDao.GetAll()
+            .Where(x => !usedPluginIds.Any(y => y == x.PluginId))
+            .Select(x => new DT.Plugin {
+              Name = x.Name,
+              Version = x.Version,
+              DateCreated = x.DateCreated
+            })
+            .ToList();
+        });
+      }
+    }
+
+    public void DeletePlugin(Guid id) {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        pm.UseTransaction(() => {
+          pluginDao.Delete(id);
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    public void DeleteUnusedPlugins() {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        pm.UseTransaction(() => {
+          pluginDao.DeleteUnusedPlugins();
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/FactClientInfo.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/FactClientInfo.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/FactClientInfo.cs	(revision 12761)
@@ -0,0 +1,28 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class FactClientInfo {
+    public int Rows { get; set; }
+    public int Clients { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Job.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Job.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Job.cs	(revision 12761)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class Job {
+    public Guid Id { get; set; }
+    public string Name { get; set; }
+    public string Username { get; set; }
+    public DateTime DateCreated { get; set; }
+    public int Tasks { get; set; }
+    public bool Aggregated { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/JobPage.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/JobPage.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/JobPage.cs	(revision 12761)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class JobPage {
+    public int TotalJobs { get; set; }
+    public IEnumerable<Job> Jobs { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Plugin.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Plugin.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/Plugin.cs	(revision 12761)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class Plugin {
+    public Guid Id { get; set; }
+    public string Name { get; set; }
+    public string Version { get; set; }
+    public DateTime DateCreated { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/PluginPage.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/PluginPage.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/PluginPage.cs	(revision 12761)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class PluginPage {
+    public int TotalPlugins { get; set; }
+    public IEnumerable<Plugin> Plugins { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/TableInformation.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/TableInformation.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/DataTransfer/TableInformation.cs	(revision 12761)
@@ -0,0 +1,31 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer {
+  public class TableInformation {
+    public string Name { get; set; }
+    public int Rows { get; set; }
+    public int Reserved { get; set; }
+    public int Data { get; set; }
+    public int IndexSize { get; set; }
+    public int Unused { get; set; }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactClientInfoController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactClientInfoController.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactClientInfoController.cs	(revision 12761)
@@ -0,0 +1,129 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#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.Maintenance.WebApi.DataTransfer;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi {
+  public class FactClientInfoController : ApiController {
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    public DT.FactClientInfo GetFactClientInfo(DateTime start, DateTime end) {
+      using (var pm = PersistenceManager) {
+        var factClientInfo = pm.FactClientInfoDao;
+        var query = factClientInfo.GetAll().Where(x => x.Time >= start && x.Time <= end);
+        return new DT.FactClientInfo {
+          Rows = query.Count(),
+          Clients = query.Select(x => x.ClientId).Distinct().Count()
+        };
+      }
+    }
+
+    public void Aggregate(DateTime start, DateTime end, int entries) {
+      using (var pm = PersistenceManager) {
+        var factClientInfoDao = pm.FactClientInfoDao;
+        var dimTimeDao = pm.DimTimeDao;
+        var clientIds = pm.UseTransaction(() => factClientInfoDao.GetAll()
+          .Where(x => x.Time >= start && x.Time <= end)
+          .Select(x => x.ClientId)
+          .Distinct()
+        );
+        foreach (var id in clientIds) {
+          AggregateClient(pm, id, entries);
+        }
+        dimTimeDao.DeleteUnusedTimes();
+      }
+    }
+
+    private void AggregateClient(IPersistenceManager pm, Guid clientId, int entries) {
+      var factClientInfoDao = pm.FactClientInfoDao;
+      var clientInfos = pm.UseTransaction(() => factClientInfoDao.GetByClientId(clientId).OrderBy(x => x.Time).ToList());
+      FactClientInfo lastClientInfo = null, sumClientInfo = new FactClientInfo();
+      int counter = 0;
+      var aggregatedClientInfos = new List<FactClientInfo>();
+      foreach (var clientInfo in clientInfos) {
+        if (lastClientInfo != null) {
+          if (lastClientInfo.SlaveState != clientInfo.SlaveState ||
+              lastClientInfo.IsAllowedToCalculate != clientInfo.IsAllowedToCalculate) {
+            // update into 'lastClientInfo'
+            if (aggregatedClientInfos.Any()) {
+              counter = aggregatedClientInfos.Count();
+              pm.UseTransaction(() => {
+                factClientInfoDao.Delete(aggregatedClientInfos);
+                lastClientInfo.NumUsedCores = sumClientInfo.NumUsedCores / counter;
+                lastClientInfo.NumTotalCores = sumClientInfo.NumTotalCores / counter;
+                lastClientInfo.UsedMemory = sumClientInfo.UsedMemory / counter;
+                lastClientInfo.TotalMemory = sumClientInfo.TotalMemory / counter;
+                lastClientInfo.CpuUtilization = sumClientInfo.CpuUtilization / counter;
+                lastClientInfo.IdleTime = sumClientInfo.IdleTime;
+                lastClientInfo.OfflineTime = sumClientInfo.OfflineTime;
+                lastClientInfo.UnavailableTime = sumClientInfo.UnavailableTime;
+                pm.SubmitChanges();
+              });
+            }
+            aggregatedClientInfos.Clear();
+            counter = 0;
+            sumClientInfo = new FactClientInfo();
+          } else {
+            // sum up 
+            sumClientInfo.NumUsedCores += clientInfo.NumUsedCores;
+            sumClientInfo.NumTotalCores += clientInfo.NumTotalCores;
+            sumClientInfo.UsedMemory += clientInfo.UsedMemory;
+            sumClientInfo.TotalMemory += clientInfo.TotalMemory;
+            sumClientInfo.CpuUtilization += clientInfo.CpuUtilization;
+            sumClientInfo.IdleTime += clientInfo.IdleTime;
+            sumClientInfo.OfflineTime += clientInfo.OfflineTime;
+            sumClientInfo.UnavailableTime += clientInfo.UnavailableTime;
+            counter++;
+            if (counter >= entries) {
+              pm.UseTransaction(() => {
+                factClientInfoDao.Delete(aggregatedClientInfos);
+                clientInfo.NumUsedCores = sumClientInfo.NumUsedCores / counter;
+                clientInfo.NumTotalCores = sumClientInfo.NumTotalCores / counter;
+                clientInfo.UsedMemory = sumClientInfo.UsedMemory / counter;
+                clientInfo.TotalMemory = sumClientInfo.TotalMemory / counter;
+                clientInfo.CpuUtilization = sumClientInfo.CpuUtilization / counter;
+                clientInfo.IdleTime = sumClientInfo.IdleTime;
+                clientInfo.OfflineTime = sumClientInfo.OfflineTime;
+                clientInfo.UnavailableTime = sumClientInfo.UnavailableTime;
+                pm.SubmitChanges();
+              });
+              aggregatedClientInfos.Clear();
+              counter = 0;
+              sumClientInfo = new FactClientInfo();
+            } else {
+              aggregatedClientInfos.Add(clientInfo);
+            }
+          }
+        }
+        lastClientInfo = clientInfo;
+      }
+    }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactTaskController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactTaskController.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/FactTaskController.cs	(revision 12761)
@@ -0,0 +1,119 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+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.Maintenance.WebApi.DataTransfer;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi {
+  public class FactTaskController : ApiController {
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    public DT.JobPage GetJobs(DateTime start, DateTime end, int page, int size) {
+      using (var pm = PersistenceManager) {
+        var dimJobDao = pm.DimJobDao;
+        var factTaskDao = pm.FactTaskDao;
+        return pm.UseTransaction(() => {
+          var query = dimJobDao.GetAll().Where(x => x.DateCreated >= start && x.DateCreated <= end);
+          return new DT.JobPage {
+            TotalJobs = query.Count(),
+            Jobs = query.OrderBy(x => x.DateCreated)
+              .Skip((page - 1) * size)
+              .Take(size)
+              .Select(x => new DT.Job {
+                Id = x.JobId,
+                Name = x.JobName,
+                Username = x.UserName,
+                DateCreated = x.DateCreated,
+                Tasks = x.TotalTasks,
+                Aggregated = !(factTaskDao.GetAll().Count(y => y.JobId == x.JobId) > 1)
+              })
+              .ToList()
+          };
+        });
+      }
+    }
+
+    [HttpPost]
+    public void AggregateJob(Guid id) {
+      using (var pm = PersistenceManager) {
+        AggregateJob(pm, id);
+      }
+    }
+
+    [HttpPost]
+    public void AggregateAllJobs(DateTime start, DateTime end) {
+      using (var pm = PersistenceManager) {
+        var dimJobDao = pm.DimJobDao;
+        var jobIds = pm.UseTransaction(() => dimJobDao.GetAll()
+          .Where(x => x.DateCreated >= start && x.DateCreated <= end)
+          .Select(x => x.JobId)
+          .ToList()
+        );
+        foreach (var id in jobIds) {
+          AggregateJob(pm, id);
+        }
+      }
+    }
+
+    private void AggregateJob(IPersistenceManager pm, Guid id) {
+      var jobDao = pm.JobDao;
+      var factTaskDao = pm.FactTaskDao;
+      pm.UseTransaction(() => {
+        if (jobDao.Exists(id)) return;
+        var jobTimeData = factTaskDao.GetByJobId(id).GroupBy(x => x.JobId).Select(x => new {
+          CalculatingTime = x.Sum(y => y.CalculatingTime),
+          WaitingTime = x.Sum(y => y.WaitingTime),
+          TransferTime = x.Sum(y => y.TransferTime),
+          InitialWaitingTime = x.Sum(y => y.InitialWaitingTime),
+          StartTime = x.Min(y => y.StartTime),
+          EndTime = x.Max(y => y.EndTime)
+        }).SingleOrDefault();
+        if (jobTimeData != null) {
+          factTaskDao.DeleteByJobId(id);
+          factTaskDao.Save(new FactTask {
+            TaskId = Guid.NewGuid(),
+            JobId = id,
+            CalculatingTime = jobTimeData.CalculatingTime,
+            WaitingTime = jobTimeData.WaitingTime,
+            TransferTime = jobTimeData.TransferTime,
+            InitialWaitingTime = jobTimeData.InitialWaitingTime,
+            StartTime = jobTimeData.StartTime,
+            EndTime = jobTimeData.EndTime,
+            NumCalculationRuns = 0,
+            NumRetries = 0,
+            CoresRequired = 0,
+            MemoryRequired = 0,
+            Priority = 0,
+            TaskState = TaskState.Finished
+          });
+        }
+        pm.SubmitChanges();
+      });
+    }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/PluginController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/PluginController.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/PluginController.cs	(revision 12761)
@@ -0,0 +1,85 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System;
+using System.Linq;
+using System.Web.Http;
+using HeuristicLab.Services.Hive;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using DT = HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi {
+  public class PluginController : ApiController {
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    public DT.PluginPage GetUnusedPlugins(int page, int size) {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        var requiredPluginDao = pm.RequiredPluginDao;
+        var taskDao = pm.TaskDao;
+        return pm.UseTransaction(() => {
+          var taskIds = taskDao.GetAll().Select(x => x.TaskId);
+          var usedPluginIds = requiredPluginDao.GetAll()
+            .Where(x => taskIds.Contains(x.TaskId))
+            .Select(x => x.PluginId)
+            .Distinct();
+          var query = pluginDao.GetAll().Where(x => !usedPluginIds.Any(y => y == x.PluginId));
+          return new DT.PluginPage {
+            TotalPlugins = query.Count(),
+            Plugins = query.OrderBy(x => x.DateCreated)
+              .Skip((page - 1) * size)
+              .Take(size).Select(x => new DT.Plugin {
+                Id = x.PluginId,
+                Name = x.Name,
+                Version = x.Version,
+                DateCreated = x.DateCreated
+              })
+              .ToList()
+          };
+        });
+      }
+    }
+
+    [HttpPost]
+    public void DeletePlugin(Guid id) {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        pm.UseTransaction(() => {
+          pluginDao.Delete(id);
+          pm.SubmitChanges();
+        });
+      }
+    }
+
+    [HttpPost]
+    public void DeleteUnusedPlugins() {
+      using (var pm = PersistenceManager) {
+        var pluginDao = pm.PluginDao;
+        pm.UseTransaction(() => {
+          pluginDao.DeleteUnusedPlugins();
+          pm.SubmitChanges();
+        });
+      }
+    }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/SpaceUsageController.cs
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/SpaceUsageController.cs	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApi/SpaceUsageController.cs	(revision 12761)
@@ -0,0 +1,95 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Http;
+using HeuristicLab.Services.Hive;
+using HeuristicLab.Services.Hive.DataAccess.Interfaces;
+using HeuristicLab.Services.WebApp.Maintenance.WebApi.DataTransfer;
+using DA = HeuristicLab.Services.Hive.DataAccess.Data;
+
+namespace HeuristicLab.Services.WebApp.Maintenance.WebApi {
+  public class SpaceUsageController : ApiController {
+    private IPersistenceManager PersistenceManager {
+      get { return ServiceLocator.Instance.PersistenceManager; }
+    }
+
+    public IEnumerable<TableInformation> GetHiveTableInformation() {
+      var tables = new List<string> {
+        "AssignedResources",
+        "Downtime",
+        "Job",
+        "JobPermission",
+        "Lifecycle",
+        "Plugin",
+        "PluginData",
+        "RequiredPlugins",
+        "Resource",
+        "ResourcePermission",
+        "StateLog",
+        "Task",
+        "TaskData",
+        "UserPriority"
+      };
+      using (var pm = PersistenceManager) {
+        return pm.UseTransaction(() => (
+          from table in tables
+          select pm.GetTableInformation(table) into tableInformation
+          where tableInformation != null
+          select Convert(tableInformation)
+          ).ToList()
+        );
+      }
+    }
+
+    public IEnumerable<TableInformation> GetStatisticsTableInformation() {
+      var tables = new List<string> {
+        "statistics.DimClient",
+        "statistics.DimJob",
+        "statistics.DimTime",
+        "statistics.DimUser",
+        "statistics.FactClientInfo",
+        "statistics.FactTask"
+      };
+      using (var pm = PersistenceManager) {
+        return pm.UseTransaction(() => (
+          from table in tables
+          select pm.GetTableInformation(table) into tableInformation
+          where tableInformation != null
+          select Convert(tableInformation)
+          ).ToList()
+        );
+      }
+    }
+
+    private TableInformation Convert(DA.TableInformation tableInformation) {
+      return new TableInformation {
+        Name = tableInformation.Name,
+        Rows = tableInformation.Rows,
+        Reserved = tableInformation.Reserved,
+        Data = tableInformation.Data,
+        IndexSize = tableInformation.IndexSize,
+        Unused = tableInformation.Unused
+      };
+    }
+  }
+}
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfo.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfo.cshtml	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfo.cshtml	(revision 12761)
@@ -0,0 +1,70 @@
+﻿@using HeuristicLab.Services.Hive
+<header class="view-header">
+    <ul class="nav nav-list nav-list-topbar pull-left">
+        <li>
+            <a ng-href="#/maintenance/spaceusage">Space Usage</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/plugin">Plugin</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/facttask">FactTask</a>
+        </li>
+        <li class="active">
+            <a ng-href="#/maintenance/factclientinfo">FactClientInfo</a>
+        </li>
+    </ul>
+</header>
+
+<div class="default-view-header">
+    <form class="form-inline">
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <label for="fromDate">From:&nbsp;</label>
+            <div class="input-group">
+                <input id="fromDate" type="text" class="form-control" datepicker-popup="dd.MM.yyyy" ng-model="fromDate" is-open="fromIsOpen" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
+                <span class="input-group-btn">
+                    <button type="button" class="btn btn-default" ng-click="openFromDateSelection($event)"><i class="glyphicon glyphicon-calendar"></i></button>
+                </span>
+            </div>
+        </div>
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <label for="fromDate">To:&nbsp;</label>
+            <div class="input-group">
+                <input id="fromDate" type="text" class="form-control" datepicker-popup="dd.MM.yyyy" ng-model="toDate" is-open="toIsOpen" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
+                <span class="input-group-btn">
+                    <button type="button" class="btn btn-default" ng-click="openToDateSelection($event)"><i class="glyphicon glyphicon-calendar"></i></button>
+                </span>
+            </div>
+        </div>
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <button type="button" class="btn btn-default" ng-click="getFactClientInfo()">
+                Apply
+            </button>
+        </div>
+    </form>
+</div>
+
+<div class="default-view-container">
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h3 class="panel-title">FactClientInfo</h3>
+                </div>
+                <div class="panel-body">
+                    <form class="form-inline">
+                        <p>
+                            Rows: {{factClientInfo.Rows}}<br/>
+                            Clients: {{factClientInfo.Clients}}
+                        </p>
+                        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+                            <button type="button" class="btn btn-default" ng-click="aggregate()">
+                                Aggregate
+                            </button>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfoCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfoCtrl.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/factclientinfo/factclientinfoCtrl.js	(revision 12761)
@@ -0,0 +1,63 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    module.controller('app.maintenance.factclientinfoCtrl',
+        ['$scope', '$interval', 'app.maintenance.factclientinfoService', function ($scope, $interval, factclientinfoService) {
+            $scope.interval = defaultPageUpdateInterval;
+            $scope.entries = 2;
+
+            $scope.fromDate = new Date();
+            $scope.toDate = new Date();
+
+            $scope.fromIsOpen = false;
+            $scope.toIsOpen = false;
+
+            $scope.openFromDateSelection = function ($event) {
+                $event.preventDefault();
+                $event.stopPropagation();
+                $scope.toIsOpen = false;
+                $scope.fromIsOpen = true;
+            };
+
+            $scope.openToDateSelection = function ($event) {
+                $event.preventDefault();
+                $event.stopPropagation();
+                $scope.fromIsOpen = false;
+                $scope.toIsOpen = true;
+            };
+
+            $scope.dateOptions = {
+                formatYear: 'yy',
+                startingDay: 1
+            };
+
+            $scope.getFactClientInfo = function () {
+                factclientinfoService.getFactClientInfo({
+                    start: ConvertFromDate($scope.fromDate),
+                    end: ConvertToDate($scope.toDate)
+                },
+                function (factClientInfo) {
+                    $scope.factClientInfo = factClientInfo;
+                    $scope.aggregateStartDate = ConvertFromDate($scope.fromDate);
+                    $scope.aggregateEndDate = ConvertToDate($scope.toDate);
+                });
+            };
+
+            $scope.aggregate = function () {
+                factclientinfoService.aggregate({
+                    start: $scope.aggregateStartDate,
+                    end: $scope.aggregateEndDate,
+                    entries: $scope.entries
+                }, function () {
+                    $scope.getFactClientInfo();
+                });
+            };
+
+            $scope.updateInterval = $interval($scope.getFactClientInfo, $scope.interval);
+            var cancelInterval = $scope.$on('$locationChangeSuccess', function () {
+                $interval.cancel($scope.updateInterval);
+                cancelInterval();
+            });
+            $scope.getFactClientInfo(); // init page
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttask.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttask.cshtml	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttask.cshtml	(revision 12761)
@@ -0,0 +1,90 @@
+﻿@using HeuristicLab.Services.Hive
+<header class="view-header">
+    <ul class="nav nav-list nav-list-topbar pull-left">
+        <li>
+            <a ng-href="#/maintenance/spaceusage">Space Usage</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/plugin">Plugin</a>
+        </li>
+        <li class="active">
+            <a ng-href="#/maintenance/facttask">FactTask</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/factclientinfo">FactClientInfo</a>
+        </li>
+    </ul>
+</header>
+
+<div class="default-view-header">
+    <form class="form-inline">
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <label for="fromDate">From:&nbsp;</label>
+            <div class="input-group">
+                <input id="fromDate" type="text" class="form-control" datepicker-popup="dd.MM.yyyy" ng-model="fromDate" is-open="fromIsOpen" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
+                <span class="input-group-btn">
+                    <button type="button" class="btn btn-default" ng-click="openFromDateSelection($event)"><i class="glyphicon glyphicon-calendar"></i></button>
+                </span>
+            </div>
+        </div>
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <label for="fromDate">To:&nbsp;</label>
+            <div class="input-group">
+                <input id="fromDate" type="text" class="form-control" datepicker-popup="dd.MM.yyyy" ng-model="toDate" is-open="toIsOpen" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
+                <span class="input-group-btn">
+                    <button type="button" class="btn btn-default" ng-click="openToDateSelection($event)"><i class="glyphicon glyphicon-calendar"></i></button>
+                </span>
+            </div>
+        </div>
+        <div class="form-group" style="margin-left: 5px; margin-right: 5px;">
+            <button type="button" class="btn btn-default" ng-click="getJobs()">
+                Apply
+            </button>
+        </div>
+    </form>
+</div>
+
+<div class="default-view-container">
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h3 class="panel-title">Jobs</h3>
+                </div>
+                <div class="panel-body">
+                    <table class="table table-hover table-condensed" ts-wrapper>
+                        <thead>
+                        <tr>
+                            <th>#</th>
+                            <th ts-criteria="Name">Job Name</th>
+                            <th ts-criteria="Username">Username</th>
+                            <th ts-criteria="DateCreated">Date Created</th>
+                            <th ts-criteria="Tasks">Tasks</th>
+                            <th class="text-center">
+                                <a ng-show="jobPage.Jobs.length" class="cursor-pointer" ng-href="" ng-click="aggregateAllJobs()">Aggregate All</a>
+                            </th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                            <tr ng-repeat="job in jobPage.Jobs" ts-repeat>
+                                <td>{{($index + 1)+((curJobsPage-1)*(jobsPageSize))}}</td>
+                                <td>{{job.Name}}</td>
+                                <td>{{job.Username}}</td>
+                                <td>{{job.DateCreated | toDate}}</td>
+                                <td>{{job.Tasks}}</td>
+                                <td class="text-center">
+                                    <a ng-hide="job.Aggregated" class="cursor-pointer" ng-href="" ng-click="aggregateJob(job.Id)">Aggregate</a>
+                                </td>
+                            </tr>
+                        </tbody>
+                    </table>
+                    <div class="row text-center" ng-show="jobPage.TotalJobs > jobPage.Jobs.length">
+                        <pagination max-size="10" total-items="jobPage.TotalJobs" ng-model="curJobsPage" ng-change="changeJobsPage()" items-per-page="jobsPageSize"
+                                    boundary-links="true" rotate="false" num-pages="numPages"></pagination>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttaskCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttaskCtrl.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/facttask/facttaskCtrl.js	(revision 12761)
@@ -0,0 +1,74 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    module.controller('app.maintenance.facttaskCtrl',
+        ['$scope', '$interval', 'app.maintenance.facttaskService', function ($scope, $interval, facttaskService) {
+            $scope.interval = defaultPageUpdateInterval;
+            $scope.curJobsPage = 1;
+            $scope.jobsPageSize = 20;
+
+            $scope.fromDate = new Date();
+            $scope.toDate = new Date();
+
+            $scope.fromIsOpen = false;
+            $scope.toIsOpen = false;
+
+            $scope.openFromDateSelection = function ($event) {
+                $event.preventDefault();
+                $event.stopPropagation();
+                $scope.toIsOpen = false;
+                $scope.fromIsOpen = true;
+            };
+
+            $scope.openToDateSelection = function ($event) {
+                $event.preventDefault();
+                $event.stopPropagation();
+                $scope.fromIsOpen = false;
+                $scope.toIsOpen = true;
+            };
+
+            $scope.dateOptions = {
+                formatYear: 'yy',
+                startingDay: 1
+            };
+
+            $scope.getJobs = function () {
+                facttaskService.getJobs({
+                    start: ConvertFromDate($scope.fromDate),
+                    end: ConvertToDate($scope.toDate),
+                    page: $scope.curJobsPage,
+                    size: $scope.jobsPageSize
+                },
+                function (jobPage) {
+                    $scope.jobPage = jobPage;
+                });
+            };
+
+            $scope.aggregateJob = function (id) {
+                facttaskService.aggregateJob({ id: id }, function () {
+                    $scope.getJobs();
+                });
+            };
+
+            $scope.aggregateAllJobs = function () {
+                facttaskService.aggregateAllJobs({
+                    start: ConvertFromDate($scope.fromDate),
+                    end: ConvertToDate($scope.toDate)
+                },
+                function () {
+                    $scope.getJobs();
+                });
+            };
+
+            $scope.changeJobsPage = function () {
+                $scope.getJobs();
+            };
+
+            $scope.updateInterval = $interval($scope.getJobs, $scope.interval);
+            var cancelInterval = $scope.$on('$locationChangeSuccess', function () {
+                $interval.cancel($scope.updateInterval);
+                cancelInterval();
+            });
+            $scope.getJobs(); // init page
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/plugin.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/plugin.cshtml	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/plugin.cshtml	(revision 12761)
@@ -0,0 +1,58 @@
+﻿@using HeuristicLab.Services.Hive
+<header class="view-header">
+    <ul class="nav nav-list nav-list-topbar pull-left">
+        <li>
+            <a ng-href="#/maintenance/spaceusage">Space Usage</a>
+        </li>
+        <li class="active">
+            <a ng-href="#/maintenance/plugin">Plugin</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/facttask">FactTask</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/factclientinfo">FactClientInfo</a>
+        </li>
+    </ul>
+</header>
+
+<div class="default-view-container">
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h3 class="panel-title">Unused Plugins</h3>
+                </div>
+                <div class="panel-body">
+                    <table class="table table-hover table-condensed" ts-wrapper>
+                        <thead>
+                            <tr>
+                                <th>#</th>
+                                <th ts-criteria="Name">Plugin Name</th>
+                                <th ts-criteria="Version">Version</th>
+                                <th ts-criteria="DateCreated">Date Created</th>
+                                <th class="text-center">
+                                    <a ng-show="pluginPage.Plugins.length" class="cursor-pointer" ng-href="" ng-click="deleteUnusedPlugins()">Delete All</a>
+                                </th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <tr ng-repeat="plugin in pluginPage.Plugins" ts-repeat>
+                                <td>{{($index + 1)+((curPluginsPage-1)*(pluginsPageSize))}}</td>
+                                <td>{{plugin.Name}}</td>
+                                <td>{{plugin.Version}}</td>
+                                <td>{{plugin.DateCreated | toDate}}</td>
+                                <td class="text-center"><a class="cursor-pointer" ng-href="" ng-click="deletePlugin(plugin.Id)">Delete</a></td>
+                            </tr>
+                        </tbody>
+                    </table>
+                    <div class="row text-center" ng-show="pluginPage.TotalPlugins > pluginPage.Plugins.length">
+                        <pagination max-size="10" total-items="pluginPage.TotalPlugins" ng-model="curPluginsPage" ng-change="changePluginsPage()" items-per-page="pluginsPageSize"
+                                    boundary-links="true" rotate="false" num-pages="numPages"></pagination>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/pluginCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/pluginCtrl.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/plugin/pluginCtrl.js	(revision 12761)
@@ -0,0 +1,39 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    module.controller('app.maintenance.pluginCtrl',
+        ['$scope', '$interval', 'app.maintenance.pluginService', function ($scope, $interval, pluginService) {
+            $scope.interval = defaultPageUpdateInterval;
+            $scope.curPluginsPage = 1;
+            $scope.pluginsPageSize = 20;
+
+            var getUnusedPlugins = function () {
+                pluginService.getUnusedPlugins({ page: $scope.curPluginsPage, size: $scope.pluginsPageSize }, function (pluginPage) {
+                    $scope.pluginPage = pluginPage;
+                });
+            };
+
+            $scope.deletePlugin = function(id) {
+                pluginService.deletePlugin({ id: id }, function() {
+                    getUnusedPlugins();
+                });
+            };
+
+            $scope.deleteUnusedPlugins = function() {
+                pluginService.deleteUnusedPlugins({}, function() {
+                    getUnusedPlugins();
+                });
+            };
+
+            $scope.changePluginsPage = function () {
+                getUnusedPlugins();
+            };
+
+            $scope.updateInterval = $interval(getUnusedPlugins, $scope.interval);
+            var cancelInterval = $scope.$on('$locationChangeSuccess', function () {
+                $interval.cancel($scope.updateInterval);
+                cancelInterval();
+            });
+            getUnusedPlugins(); // init page
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/factclientinfoService.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/factclientinfoService.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/factclientinfoService.js	(revision 12761)
@@ -0,0 +1,12 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    var apiUrl = 'api/Maintenance/FactClientInfo/';
+    module.factory('app.maintenance.factclientinfoService',
+        ['$resource', function ($resource) {
+            return $resource(apiUrl + ':action', { start: '@start', end: '@end', entries: '@entries' }, {
+                getFactClientInfo: { method: 'GET', params: { action: 'GetFactClientInfo' } },
+                aggregate: { method: 'POST', params: { action: 'Aggregate' } }
+            });
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/facttaskService.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/facttaskService.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/facttaskService.js	(revision 12761)
@@ -0,0 +1,13 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    var apiUrl = 'api/Maintenance/FactTask/';
+    module.factory('app.maintenance.facttaskService',
+        ['$resource', function ($resource) {
+            return $resource(apiUrl + ':action', { start: '@start', end: '@end', id: '@id', page: '@page', size: '@size' }, {
+                getJobs: { method: 'GET', params: { action: 'GetJobs' } },
+                aggregateJob: { method: 'POST', params: { action: 'AggregateJob' } },
+                aggregateAllJobs: { method: 'POST', params: { action: 'AggregateAllJobs' } }
+            });
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/pluginService.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/pluginService.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/pluginService.js	(revision 12761)
@@ -0,0 +1,13 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    var apiUrl = 'api/Maintenance/Plugin/';
+    module.factory('app.maintenance.pluginService',
+        ['$resource', function ($resource) {
+            return $resource(apiUrl + ':action', { id: '@id', page: '@page', size: '@size' }, {
+                getUnusedPlugins: { method: 'GET', params: { action: 'GetUnusedPlugins' } },
+                deletePlugin: { method: 'POST', params: { action: 'DeletePlugin' } },
+                deleteUnusedPlugins: { method: 'POST', params: { action: 'DeleteUnusedPlugins' } }
+            });
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/spaceUsageService.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/spaceUsageService.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/services/spaceUsageService.js	(revision 12761)
@@ -0,0 +1,12 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    var apiUrl = 'api/Maintenance/SpaceUsage/';
+    module.factory('app.maintenance.spaceUsageService',
+        ['$resource', function ($resource) {
+            return $resource(apiUrl + ':action', {}, {
+                getHiveTableInformation: { method: 'GET', params: { action: 'GetHiveTableInformation' }, isArray: true },
+                getStatisticsTableInformation: { method: 'GET', params: { action: 'GetStatisticsTableInformation' }, isArray: true }
+            });
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsage.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsage.cshtml	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsage.cshtml	(revision 12761)
@@ -0,0 +1,91 @@
+﻿@using HeuristicLab.Services.Hive
+<header class="view-header">
+    <ul class="nav nav-list nav-list-topbar pull-left">
+        <li class="active">
+            <a ng-href="#/maintenance/spaceusage">Space Usage</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/plugin">Plugin</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/facttask">FactTask</a>
+        </li>
+        <li>
+            <a ng-href="#/maintenance/factclientinfo">FactClientInfo</a>
+        </li>
+    </ul>
+</header>
+
+<div class="default-view-container">
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h3 class="panel-title">Statistics Tables Space Usage</h3>
+                </div>
+                <div class="panel-body">
+                    <table class="table table-hover table-condensed" ts-wrapper>
+                        <thead>
+                            <tr>
+                                <th>#</th>
+                                <th ts-criteria="Name">Table Name</th>
+                                <th ts-criteria="Rows" class="text-right">Rows</th>
+                                <th ts-criteria="Reserved" class="text-right">Reserved</th>
+                                <th ts-criteria="Data" class="text-right">Data</th>
+                                <th ts-criteria="IndexSize" class="text-right">Index Size</th>
+                                <th ts-criteria="Unused" class="text-right">Unused</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <tr ng-repeat="tableInformation in statisticsTableInformation" ts-repeat>
+                                <td>{{$index + 1}}</td>
+                                <td>{{tableInformation.Name}}</td>
+                                <td class="text-right">{{tableInformation.Rows}}</td>
+                                <td class="text-right">{{tableInformation.Reserved}} KB</td>
+                                <td class="text-right">{{tableInformation.Data}} KB</td>
+                                <td class="text-right">{{tableInformation.IndexSize}} KB</td>
+                                <td class="text-right">{{tableInformation.Unused}} KB</td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="row">
+        <div class="col-lg-12">
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <h3 class="panel-title">Hive Tables Space Usage</h3>
+                </div>
+                <div class="panel-body">
+                    <table class="table table-hover table-condensed" ts-wrapper>
+                        <thead>
+                            <tr>
+                                <th>#</th>
+                                <th ts-criteria="Name">Table Name</th>
+                                <th ts-criteria="Rows" class="text-right">Rows</th>
+                                <th ts-criteria="Reserved" class="text-right">Reserved</th>
+                                <th ts-criteria="Data" class="text-right">Data</th>
+                                <th ts-criteria="IndexSize" class="text-right">Index Size</th>
+                                <th ts-criteria="Unused" class="text-right">Unused</th>
+                            </tr>
+                        </thead>
+                        <tbody>
+                            <tr ng-repeat="tableInformation in hiveTableInformation" ts-repeat>
+                                <td>{{$index + 1}}</td>
+                                <td>{{tableInformation.Name}}</td>
+                                <td class="text-right">{{tableInformation.Rows}}</td>
+                                <td class="text-right">{{tableInformation.Reserved}} KB</td>
+                                <td class="text-right">{{tableInformation.Data}} KB</td>
+                                <td class="text-right">{{tableInformation.IndexSize}} KB</td>
+                                <td class="text-right">{{tableInformation.Unused}} KB</td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsageCtrl.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsageCtrl.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/WebApp/spaceUsage/spaceUsageCtrl.js	(revision 12761)
@@ -0,0 +1,24 @@
+﻿(function () {
+    var module = appMaintenancePlugin.getAngularModule();
+    module.controller('app.maintenance.spaceUsageCtrl',
+        ['$scope', '$interval', 'app.maintenance.spaceUsageService', function ($scope, $interval, spaceUsageService) {
+            $scope.interval = defaultPageUpdateInterval;
+
+            var getTableInformations = function () {
+                spaceUsageService.getHiveTableInformation({}, function (tableInformations) {
+                    $scope.hiveTableInformation = tableInformations;
+                });
+                spaceUsageService.getStatisticsTableInformation({}, function (tableInformations) {
+                    $scope.statisticsTableInformation = tableInformations;
+                });
+            };
+
+            $scope.updateInterval = $interval(getTableInformations, $scope.interval);
+            var cancelInterval = $scope.$on('$locationChangeSuccess', function () {
+                $interval.cancel($scope.updateInterval);
+                cancelInterval();
+            });
+            getTableInformations(); // init page
+        }]
+    );
+})();
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/app.config
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/app.config	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/app.config	(revision 12761)
@@ -0,0 +1,11 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/maintenance.js
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/maintenance.js	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/maintenance.js	(revision 12761)
@@ -0,0 +1,32 @@
+﻿var appMaintenancePlugin = app.registerPlugin('maintenance');
+(function () {
+    var plugin = appMaintenancePlugin;
+    plugin.dependencies = ['ngResource', 'ui.knob', 'ui.bootstrap', 'tableSort'];
+    plugin.files = [
+        'WebApp/services/spaceUsageService.js',
+        'WebApp/services/pluginService.js',
+        'WebApp/services/facttaskService.js',
+        'WebApp/services/factclientinfoService.js',
+        'WebApp/plugin/pluginCtrl.js',
+        'WebApp/facttask/facttaskCtrl.js',
+        'WebApp/factclientinfo/factclientinfoCtrl.js',
+        'WebApp/spaceUsage/spaceUsageCtrl.js'
+    ];
+    plugin.view = 'WebApp/spaceUsage/spaceUsage.cshtml';
+    plugin.controller = 'app.maintenance.spaceUsageCtrl';
+    plugin.routes = [
+        new Route('spaceusage', 'WebApp/spaceUsage/spaceUsage.cshtml', 'app.maintenance.spaceUsageCtrl'),
+        new Route('facttask', 'WebApp/facttask/facttask.cshtml', 'app.maintenance.facttaskCtrl'),
+        new Route('factclientinfo', 'WebApp/factclientinfo/factclientinfo.cshtml', 'app.maintenance.factclientinfoCtrl'),
+        new Route('plugin', 'WebApp/plugin/plugin.cshtml', 'app.maintenance.pluginCtrl')
+    ];
+    var menu = app.getMenu();
+    var section = menu.getSection('Administration', -1);
+    section.addEntry({
+        name: 'Maintenance',
+        route: '#/maintenance',
+        icon: 'glyphicon glyphicon-cog',
+        entries: []
+    });
+})();
+
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/packages.config
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/packages.config	(revision 12761)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Maintenance/3.3/packages.config	(revision 12761)
@@ -0,0 +1,8 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
+  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
+  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
+  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
+  <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
+</packages>
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/history.cshtml
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/history.cshtml	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/history.cshtml	(revision 12761)
@@ -51,5 +51,4 @@
 </div>
 
-
 <div class="default-view-container">
     <div class="row">
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Web.config
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Web.config	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/Web.config	(revision 12761)
@@ -38,5 +38,4 @@
       <mimeMap fileExtension=".woff2" mimeType="application/font-woff" />
     </staticContent>
-  
     <modules>
       <remove name="FormsAuthentication" />
@@ -54,5 +53,6 @@
       <remove name="TRACEVerbHandler" />
       <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
-    </handlers></system.webServer>
+    </handlers>
+  </system.webServer>
   <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
Index: /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/app.css
===================================================================
--- /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/app.css	(revision 12760)
+++ /branches/HiveStatistics/sources/HeuristicLab.Services.WebApp/3.3/WebApp/app.css	(revision 12761)
@@ -416,4 +416,10 @@
 }
 
+.default-view-header {
+  padding: 30px;
+  background: #F5F5F5;
+  border-bottom: 1px solid #D3D3D3;
+}
+
 .panel-heading a:after {
     font-family:'Glyphicons Halflings';
