incubator-ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maha...@apache.org
Subject [07/30] AMBARI-3266. Contribute Ambari-SCOM. (Tom Beerbower via mahadev)
Date Fri, 18 Oct 2013 00:25:29 GMT
http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringFormatter.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringFormatter.cs b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringFormatter.cs
new file mode 100644
index 0000000..67f6c82
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringFormatter.cs
@@ -0,0 +1,85 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.ComponentModel.Composition;
+using System.Linq;
+using Microsoft.EnterpriseManagement.Presentation.DataAccess;
+
+namespace Ambari.SCOM.Widgets.Components {
+    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
+    public class StringFormatter : InitializableComponentBase {
+        private string formatString;
+        public string FormatString {
+            get { return formatString; }
+            set {
+                if (formatString == value) return;
+                formatString = value;
+                NotifyPropertyChanged("FormatString");
+                Format();
+            }
+        }
+
+        private IEnumerable<IDataObject> arguments;
+        public IEnumerable<IDataObject> Arguments {
+            get { return arguments; }
+            set {
+                if (arguments == value) return;
+                ForEachObservableArgument(a => a.PropertyChanged -= ArgumentChanged);
+                arguments = value;
+                ForEachObservableArgument(a => a.PropertyChanged += ArgumentChanged);
+                NotifyPropertyChanged("Arguments");
+                Format();
+            }
+        }
+
+        private void ForEachObservableArgument(Action<ObservableDataObject> action) {
+            if (arguments == null) return;
+            foreach (var argument in arguments) {
+                if (!(argument is ObservableDataObject)) continue;
+                action((ObservableDataObject)argument);
+            }
+        }
+
+        private void ArgumentChanged(object sender, PropertyChangedEventArgs e) {
+            Format();
+        }
+
+        private string output;
+        public string Output {
+            get { return output; }
+            set {
+                if (output == value) return;
+                output = value;
+                NotifyPropertyChanged("Output");
+            }
+        }
+
+        protected override void Initialize() {
+            Format();
+        }
+
+        private void Format() {
+            if (!IsInitialized) return;
+            if (String.IsNullOrEmpty(formatString) || arguments == null)
+                Output = null;
+            Output = String.Format(formatString, arguments.OrderBy(a => a["Index"]).Select(a => a["Value"]).ToArray());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringSplitter.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringSplitter.cs b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringSplitter.cs
new file mode 100644
index 0000000..164cd10
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Components/StringSplitter.cs
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using System;
+using System.ComponentModel.Composition;
+
+namespace Ambari.SCOM.Widgets.Components {
+    [Export, PartCreationPolicy(CreationPolicy.NonShared)]
+    public class StringSplitter : InitializableComponentBase {
+        private string input;
+        public string Input {
+            get { return input; }
+            set {
+                if (input == value) return;
+                input = value;
+                NotifyPropertyChanged("Input");
+                Split();
+            }
+        }
+
+        private string separator;
+        public string Separator {
+            get { return separator; }
+            set {
+                if (separator == value) return;
+                separator = value;
+                NotifyPropertyChanged("Separator");
+                Split();
+            }
+        }
+
+        private string[] items;
+        public string[] Items {
+            get { return items; }
+            set {
+                if (items == value) return;
+                items = value;
+                NotifyPropertyChanged("Items");
+            }
+        }
+
+        protected override void Initialize() {
+            Split();
+        }
+
+        private void Split() {
+            if (!IsInitialized) return;
+            if (String.IsNullOrEmpty(input) || String.IsNullOrEmpty(separator))
+                Items = new string[0];
+            Items = input.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Extensions/DataTypeExtensions.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Extensions/DataTypeExtensions.cs b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Extensions/DataTypeExtensions.cs
new file mode 100644
index 0000000..cf2dcb7
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Extensions/DataTypeExtensions.cs
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+using Microsoft.EnterpriseManagement.Presentation.DataAccess;
+
+namespace Ambari.SCOM.Widgets.Extensions {
+    public static class DataTypeExtensions {
+        public static bool IsAssignableTo(this IDataType type, string parentType) {
+            var currentType = type;
+            while (currentType != null) {
+                if (currentType.Name == parentType) return true;
+                currentType = type.BaseType;
+            }
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Properties/AssemblyInfo.cs b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d45a600
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/Properties/AssemblyInfo.cs
@@ -0,0 +1,71 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 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("WidgetsWpf")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Ambari")]
+[assembly: AssemblyProduct("WidgetsWpf")]
+[assembly: AssemblyCopyright("Copyright © Apache Ambari 2013")]
+[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)]
+
+//In order to begin building localizable applications, set 
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>.  For example, if you are using US english
+//in your source files, set the <UICulture> to en-US.  Then uncomment
+//the NeutralResourceLanguage attribute below.  Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+    //(used if a resource is not found in the page, 
+    // or application resource dictionaries)
+    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+    //(used if a resource is not found in the page, 
+    // app, or any theme specific resource dictionaries)
+)]
+
+
+// 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")]

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/WidgetsWpf.csproj
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/WidgetsWpf.csproj b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/WidgetsWpf.csproj
new file mode 100644
index 0000000..3c47b09
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/WidgetsWpf/WidgetsWpf.csproj
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License.-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D4C615D1-9274-41D9-B14E-BC88AE7FCDCE}</ProjectGuid>
+    <OutputType>library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Ambari.SCOM.Widgets</RootNamespace>
+    <AssemblyName>Ambari.SCOM.Widgets.Wpf</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <WarningLevel>4</WarningLevel>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </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>
+  <ItemGroup>
+    <Reference Include="Microsoft.EnterpriseManagement.CompositionEngine, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Items\Libs\SCOM2012\Microsoft.EnterpriseManagement.CompositionEngine.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.EnterpriseManagement.CompositionEngine.Extensibility, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Items\Libs\SCOM2012\Microsoft.EnterpriseManagement.CompositionEngine.Extensibility.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.EnterpriseManagement.Presentation.Controls">
+      <HintPath>..\Items\Libs\SCOM2012\Microsoft.EnterpriseManagement.Presentation.Controls.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.EnterpriseManagement.Presentation.Core">
+      <HintPath>..\Items\Libs\SCOM2012\Microsoft.EnterpriseManagement.Presentation.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.Practices.Unity, Version=2.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Items\Libs\SCOM2012\Microsoft.Practices.Unity.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Windows.Controls.DataVisualization.Toolkit">
+      <HintPath>..\Items\Libs\SCOM2012\System.Windows.Controls.DataVisualization.Toolkit.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Xml" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Xaml">
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="WindowsBase" />
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Charting\Axes\ForegroundDateTimeAxis.cs" />
+    <Compile Include="Charting\Axes\ForegroundDateTimeDataToAxisConverter.cs" />
+    <Compile Include="Charting\Axes\ForegroundLinearAxis.cs" />
+    <Compile Include="Charting\Axes\ForegroundLinearDataToAxisConverter.cs" />
+    <Compile Include="Charting\Chart.xaml.cs">
+      <DependentUpon>Chart.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Charting\ChartingConstants.cs" />
+    <Compile Include="Charting\DataSeriesConverters\ExtendedDataToSeriesConverterBase.cs" />
+    <Compile Include="Charting\DataSeriesConverters\SeriesDefinitionDataToSeriesConverter.cs" />
+    <Compile Include="Charting\DataSeriesConverters\StackedAreaDataToSeriesConverter.cs" />
+    <Compile Include="Charting\SeriesFactories\StackableSeriesFactory.cs" />
+    <Compile Include="Charting\SeriesStacker.cs" />
+    <Compile Include="Charting\StackedSeriesManager.cs" />
+    <Compile Include="Components\CollectionElementAccessor.cs" />
+    <Compile Include="Components\EntitiesToInstancesWithRecursionLevelConverter.cs" />
+    <Compile Include="Components\InitializableComponentBase.cs" />
+    <Compile Include="Components\StringFormatter.cs" />
+    <Compile Include="Components\StringSplitter.cs" />
+    <Compile Include="Extensions\DataTypeExtensions.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <AppDesigner Include="Properties\" />
+  </ItemGroup>
+  <ItemGroup>
+    <Page Include="Charting\Chart.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- 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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/management-pack/Hadoop_MP/build.bat
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/management-pack/Hadoop_MP/build.bat b/contrib/ambari-scom/management-pack/Hadoop_MP/build.bat
new file mode 100644
index 0000000..ca44575
--- /dev/null
+++ b/contrib/ambari-scom/management-pack/Hadoop_MP/build.bat
@@ -0,0 +1,44 @@
+REM Licensed to the Apache Software Foundation (ASF) under one
+REM or more contributor license agreements.  See the NOTICE file
+REM distributed with this work for additional information
+REM regarding copyright ownership.  The ASF licenses this file
+REM to you under the Apache License, Version 2.0 (the
+REM "License"); you may not use this file except in compliance
+REM with the License.  You may obtain a copy of the License at
+REM
+REM     http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing,
+REM software distributed under the License is distributed on an
+REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+REM KIND, either express or implied.  See the License for the
+REM specific language governing permissions and limitations
+REM under the License.
+
+cd Modules || exit /b %errorlevel%
+msbuild Modules.csproj || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd WidgetsSilverlight  || exit /b %errorlevel%
+msbuild WidgetsSilverlight.csproj || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd WidgetsWpf || exit /b %errorlevel%
+msbuild WidgetsWpf.csproj  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd ScomPages || exit /b %errorlevel%
+msbuild ScomPages.csproj  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd HadoopMp || exit /b %errorlevel%
+msbuild HadoopMp.mpproj  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd ManagementMp || exit /b %errorlevel%
+msbuild ManagementMp.mpproj  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+cd PresentationMp || exit /b %errorlevel%
+msbuild PresentationMp.mpproj  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%
+copy HadoopMp\bin\Debug\Ambari.SCOM.Monitoring.mpb Installer\Assets\ManagementPacks  || exit /b %errorlevel%
+copy ManagementMp\bin\Debug\Ambari.SCOM.Management.mpb Installer\Assets\ManagementPacks  || exit /b %errorlevel%
+copy PresentationMp\bin\Debug\Ambari.SCOM.Presentation.mpb Installer\Assets\ManagementPacks  || exit /b %errorlevel%
+cd Installer || exit /b %errorlevel%
+msbuild Installer.sln  || exit /b %errorlevel%
+cd .. || exit /b %errorlevel%

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/metrics-sink/db/Hadoop-Metrics-SQLServer-CREATE.ddl
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/metrics-sink/db/Hadoop-Metrics-SQLServer-CREATE.ddl b/contrib/ambari-scom/metrics-sink/db/Hadoop-Metrics-SQLServer-CREATE.ddl
new file mode 100644
index 0000000..b0ee7b7
--- /dev/null
+++ b/contrib/ambari-scom/metrics-sink/db/Hadoop-Metrics-SQLServer-CREATE.ddl
@@ -0,0 +1,793 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+/*
+Deployment script for HadoopMetrics
+*/
+
+USE [master]
+GO
+
+IF db_id('HadoopMetrics') IS NOT NULL 
+BEGIN
+    Print N'Dropping [dbo].[HadoopMetrics] database...'
+    DROP DATABASE HadoopMetrics
+END
+GO
+ 
+Print N'Creating [dbo].[HadoopMetrics] database...'
+CREATE DATABASE [HadoopMetrics]
+GO
+
+USE [HadoopMetrics]
+GO
+
+SET QUOTED_IDENTIFIER ON;
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'CompletedJob' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[CompletedJob]...';
+	CREATE TABLE [dbo].[CompletedJob] (
+		[ClusterNodeID]          INT      NOT NULL,
+		[TagSetID]               INT      NOT NULL,
+		[MapProgressPercent]     INT      NOT NULL,
+		[CleanupProgressPercent] INT      NOT NULL,
+		[SetupProgressPercent]   INT      NOT NULL,
+		[ReduceProgressPercent]  INT      NOT NULL,
+		[RunState]               INT      NOT NULL,
+		[StartTime]              DATETIME NOT NULL,
+		[EndTime]                DATETIME NOT NULL
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'PK_CompletedJob_ClusterNodeID_TagSetID' AND type_desc = N'CLUSTERED' AND IS_PRIMARY_KEY=N'1')
+BEGIN
+	PRINT N'Creating [dbo].[CompletedJob].[PK_CompletedJob_ClusterNodeID_TagSetID]...';
+	ALTER TABLE [dbo].[CompletedJob]
+		ADD CONSTRAINT [PK_CompletedJob_ClusterNodeID_TagSetID] PRIMARY KEY CLUSTERED ([ClusterNodeID] ASC, [TagSetID] ASC);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_CompletedJob_EndTime' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[CompletedJob].[IX_CompletedJob_EndTime]...';
+	CREATE NONCLUSTERED INDEX [IX_CompletedJob_EndTime]
+		ON [dbo].[CompletedJob]([EndTime] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_CompletedJob_TagSetID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[CompletedJob].[IX_CompletedJob_TagSetID]...';
+	CREATE NONCLUSTERED INDEX [IX_CompletedJob_TagSetID]
+		ON [dbo].[CompletedJob]([TagSetID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'Configuration' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[Configuration]...';
+	CREATE TABLE [dbo].[Configuration] (
+		[RequestedRefreshRate] INT NOT NULL
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'DatabaseVersion' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[DatabaseVersion]...';
+	CREATE TABLE [dbo].[DatabaseVersion] (
+		[Major]    INT NOT NULL,
+		[Minor]    INT NOT NULL,
+		[Build]    INT NOT NULL,
+		[Revision] INT NOT NULL
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'MetricName' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[MetricName]...';
+	CREATE TABLE [dbo].[MetricName] (
+		[MetricID] INT            IDENTITY (1, 1) NOT NULL,
+		[Name]     NVARCHAR (256) NOT NULL,
+		PRIMARY KEY CLUSTERED ([MetricID] ASC)
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricName_Name' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricName].[IX_MetricName_Name]...';
+	CREATE UNIQUE NONCLUSTERED INDEX [IX_MetricName_Name]
+		ON [dbo].[MetricName]([Name] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'MetricPair' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[MetricPair]...';
+	CREATE TABLE [dbo].[MetricPair] (
+		[RecordID]    BIGINT         NOT NULL,
+		[MetricID]    INT            NOT NULL,
+		[MetricValue] NVARCHAR (512) NOT NULL
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'UX_MetricPair_RecordID_MetricID' AND type_desc = N'CLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricPair].[UX_MetricPair_RecordID_MetricID]...';
+	CREATE UNIQUE CLUSTERED INDEX [UX_MetricPair_RecordID_MetricID]
+		ON [dbo].[MetricPair]([RecordID] ASC, [MetricID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'MetricRecord' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord]...';
+	CREATE TABLE [dbo].[MetricRecord] (
+		[RecordID]        BIGINT         IDENTITY (1, 1) NOT NULL,
+		[RecordTypeID]    INT            NOT NULL,
+		[NodeID]          INT            NOT NULL,
+		[SourceIP]        NVARCHAR (256) NULL,
+		[ClusterNodeID]   INT            NOT NULL,
+		[ServiceID]       INT            NOT NULL,
+		[TagSetID]        INT            NOT NULL,
+		[RecordTimestamp] BIGINT         NOT NULL,
+		[RecordDate]      AS             DATEADD(second, CONVERT (INT, RecordTimestamp / 1000), CONVERT (DATETIME, '1970-01-01T00:00:00.000', 126)) PERSISTED,
+		PRIMARY KEY CLUSTERED ([RecordID] ASC)
+	);
+END
+GO
+
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_ClusterNodeID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_ClusterNodeID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_ClusterNodeID]
+		ON [dbo].[MetricRecord]([ClusterNodeID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_NodeID_RecordID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_NodeID_RecordID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_NodeID_RecordID]
+		ON [dbo].[MetricRecord]([NodeID] ASC, [RecordID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_NodeID_RecordTypeID_ClusterNodeID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_NodeID_RecordTypeID_ClusterNodeID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_NodeID_RecordTypeID_ClusterNodeID]
+		ON [dbo].[MetricRecord]([NodeID] ASC, [RecordTypeID] ASC, [ClusterNodeID] ASC)
+		INCLUDE([RecordDate]) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_NodeID_TagSetID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_NodeID_TagSetID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_NodeID_TagSetID]
+		ON [dbo].[MetricRecord]([NodeID] ASC, [TagSetID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_RecordDate' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_RecordDate]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_RecordDate]
+		ON [dbo].[MetricRecord]([RecordDate] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_RecordTimestamp_NodeID_RecordTypeID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_RecordTimestamp_NodeID_RecordTypeID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_RecordTimestamp_NodeID_RecordTypeID]
+		ON [dbo].[MetricRecord]([RecordTimestamp] DESC, [NodeID] ASC, [RecordTypeID] ASC)
+		INCLUDE([RecordID]) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_RecordTypeID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_RecordTypeID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_RecordTypeID]
+		ON [dbo].[MetricRecord]([RecordTypeID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_RecordTypeID_ClusterNodeID_ServiceID_TagSetID_RecordTimestamp' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_RecordTypeID_ClusterNodeID_ServiceID_TagSetID_RecordTimestamp]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_RecordTypeID_ClusterNodeID_ServiceID_TagSetID_RecordTimestamp]
+		ON [dbo].[MetricRecord]([RecordTypeID] ASC, [ClusterNodeID] ASC, [ServiceID] ASC, [TagSetID] ASC, [RecordTimestamp] DESC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_MetricRecord_TagSetID' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[IX_MetricRecord_TagSetID]...';
+	CREATE NONCLUSTERED INDEX [IX_MetricRecord_TagSetID]
+		ON [dbo].[MetricRecord]([TagSetID] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'UX_MetricRecord_RecordTypeID_NodeID_TagSetID_RecordTimestamp' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[MetricRecord].[UX_MetricRecord_RecordTypeID_NodeID_TagSetID_RecordTimestamp]...';
+	CREATE UNIQUE NONCLUSTERED INDEX [UX_MetricRecord_RecordTypeID_NodeID_TagSetID_RecordTimestamp]
+		ON [dbo].[MetricRecord]([RecordTypeID] ASC, [NodeID] ASC, [TagSetID] ASC, [RecordTimestamp] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'Service' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[Service]...';
+	CREATE TABLE [dbo].[Service] (
+		[ServiceID]        BIGINT         IDENTITY (1, 1) NOT NULL,
+		[Name]             NVARCHAR (256),
+		PRIMARY KEY CLUSTERED ([ServiceID] ASC)
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'Node' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[Node]...';
+	CREATE TABLE [dbo].[Node] (
+		[NodeID]                   INT            IDENTITY (1, 1) NOT NULL,
+		[Name]                     NVARCHAR (256) NOT NULL,
+		[LastKnownIP]              NVARCHAR (256) NULL,
+		[LastNameNodeHeartBeat]    DATETIME       NULL,
+		[LastJobTrackerHeartBeat]  DATETIME       NULL,
+		[LastDataNodeHeartBeat]    DATETIME       NULL,
+		[LastTaskTrackerHeartBeat] DATETIME       NULL,
+		PRIMARY KEY CLUSTERED ([NodeID] ASC)
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_Node_Name' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[Node].[IX_Node_Name]...';
+	CREATE UNIQUE NONCLUSTERED INDEX [IX_Node_Name]
+		ON [dbo].[Node]([Name] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'RecordType' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[RecordType]...';
+	CREATE TABLE [dbo].[RecordType] (
+		[RecordTypeID] INT            IDENTITY (1, 1) NOT NULL,
+		[Name]         NVARCHAR (256) NOT NULL,
+		[Context]      NVARCHAR (256) NOT NULL,
+		PRIMARY KEY CLUSTERED ([RecordTypeID] ASC)
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_RecordType_Context_Name' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[RecordType].[IX_RecordType_Context_Name]...';
+	CREATE UNIQUE NONCLUSTERED INDEX [IX_RecordType_Context_Name]
+		ON [dbo].[RecordType]([Context] ASC, [Name] ASC) ;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'TagSet' and type_desc = N'USER_TABLE')
+BEGIN
+	PRINT N'Creating [dbo].[TagSet]...';
+	CREATE TABLE [dbo].[TagSet] (
+		[TagSetID] INT            IDENTITY (1, 1) NOT NULL,
+		[TagPairs] NVARCHAR (512) NOT NULL,
+		PRIMARY KEY CLUSTERED ([TagSetID] ASC)
+	);
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = N'IX_TagSet_TagPairs' AND type_desc = N'NONCLUSTERED')
+BEGIN
+	PRINT N'Creating [dbo].[TagSet].[IX_TagSet_TagPairs]...';
+	CREATE UNIQUE NONCLUSTERED INDEX [IX_TagSet_TagPairs]
+		ON [dbo].[TagSet]([TagPairs] ASC) ;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_CompletedJob_TagSet_TagSetID') 
+BEGIN
+	PRINT N'Creating FK_CompletedJob_TagSet_TagSetID...';
+	ALTER TABLE [dbo].[CompletedJob] WITH NOCHECK
+		ADD CONSTRAINT [FK_CompletedJob_TagSet_TagSetID] FOREIGN KEY ([TagSetID]) REFERENCES [dbo].[TagSet] ([TagSetID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_MetricPair_MetricName_MetricID')
+BEGIN
+	PRINT N'Creating FK_MetricPair_MetricName_MetricID...';
+	ALTER TABLE [dbo].[MetricPair] WITH NOCHECK
+		ADD CONSTRAINT [FK_MetricPair_MetricName_MetricID] FOREIGN KEY ([MetricID]) REFERENCES [dbo].[MetricName] ([MetricID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_MetricPair_MetricRecord_RecordID')
+BEGIN
+	PRINT N'Creating FK_MetricPair_MetricRecord_RecordID...';
+	ALTER TABLE [dbo].[MetricPair] WITH NOCHECK
+		ADD CONSTRAINT [FK_MetricPair_MetricRecord_RecordID] FOREIGN KEY ([RecordID]) REFERENCES [dbo].[MetricRecord] ([RecordID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_MetricRecord_Node_NodeID')
+BEGIN
+	PRINT N'Creating FK_MetricRecord_Node_NodeID...';
+	ALTER TABLE [dbo].[MetricRecord] WITH NOCHECK
+		ADD CONSTRAINT [FK_MetricRecord_Node_NodeID] FOREIGN KEY ([NodeID]) REFERENCES [dbo].[Node] ([NodeID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_MetricRecord_RecordType_RecordTypeID')
+BEGIN
+	PRINT N'Creating FK_MetricRecord_RecordType_RecordTypeID...';
+	ALTER TABLE [dbo].[MetricRecord] WITH NOCHECK
+		ADD CONSTRAINT [FK_MetricRecord_RecordType_RecordTypeID] FOREIGN KEY ([RecordTypeID]) REFERENCES [dbo].[RecordType] ([RecordTypeID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS (SELECT name FROM sys.foreign_keys WHERE name = N'FK_MetricRecord_TagSet_TagSetID')
+BEGIN
+	PRINT N'Creating FK_MetricRecord_TagSet_TagSetID...';
+	ALTER TABLE [dbo].[MetricRecord] WITH NOCHECK
+		ADD CONSTRAINT [FK_MetricRecord_TagSet_TagSetID] FOREIGN KEY ([TagSetID]) REFERENCES [dbo].[TagSet] ([TagSetID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'uspInsertMetricValue' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating [dbo].[uspInsertMetricValue]...';
+	exec('CREATE PROCEDURE [dbo].[uspInsertMetricValue]
+		@recordID bigint, 
+		@metricName nvarchar(256),
+		@metricValue nvarchar(512)
+	AS
+	BEGIN
+		SET NOCOUNT ON;
+
+		DECLARE @metricID int;
+		DECLARE @err int;
+
+		IF @recordID IS NULL OR @metricName IS NULL RETURN;
+
+		BEGIN TRANSACTION;
+		SELECT @metricID = MetricID FROM MetricName WHERE Name = @metricName;
+		IF @metricID IS NULL
+		BEGIN
+			INSERT INTO MetricName (Name) VALUES (@metricName);
+			SELECT @err = @@ERROR, @metricID = SCOPE_IDENTITY();
+			IF @err <> 0 GOTO Abort;
+		END
+		COMMIT TRANSACTION;
+
+		INSERT INTO MetricPair (RecordID, MetricID, MetricValue) VALUES (@recordID, @metricID, @metricValue);
+		RETURN;
+
+	Abort:
+		ROLLBACK TRANSACTION;
+		RETURN;
+	END')
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'uspUpdateHeartBeats' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating [dbo].[uspUpdateHeartBeats]...';
+	exec('CREATE PROCEDURE [dbo].[uspUpdateHeartBeats]
+		@NodeID int,
+		@SourceIP nvarchar(256), 
+		@NameNodeLast datetime,
+		@JobTrackerLast datetime,
+		@DataNodeLast datetime,
+		@TaskTrackerLast datetime,
+		@LastKnownIP nvarchar(256)
+	AS
+	BEGIN
+		IF @NodeID IS NOT NULL
+		BEGIN
+			IF @NameNodeLast IS NOT NULL
+			BEGIN
+				UPDATE Node SET LastNameNodeHeartBeat = @NameNodeLast WHERE NodeID = @NodeID;
+			END
+			IF @JobTrackerLast IS NOT NULL
+			BEGIN
+				UPDATE Node SET LastJobTrackerHeartBeat = @JobTrackerLast WHERE NodeID = @NodeID;
+			END
+			IF @DataNodeLast IS NOT NULL
+			BEGIN
+				UPDATE Node SET LastDataNodeHeartBeat = @DataNodeLast WHERE NodeID = @NodeID;
+			END
+			IF @TaskTrackerLast IS NOT NULL
+			BEGIN
+				UPDATE Node SET LastTaskTrackerHeartBeat = @TaskTrackerLast WHERE NodeID = @NodeID;
+			END
+			IF @LastKnownIP IS NULL OR @SourceIP <> @LastKnownIP
+			BEGIN
+				UPDATE Node SET LastKnownIP = @SourceIP WHERE NodeID = @NodeID;
+			END
+		END
+	END')
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'uspGetMetricRecord' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating [dbo].[uspGetMetricRecord]...';
+	exec('CREATE PROCEDURE [dbo].[uspGetMetricRecord]
+		@recordTypeContext nvarchar(256),
+		@recordTypeName nvarchar(256), 
+		@nodeName nvarchar(256),
+		@sourceIP nvarchar(256),
+		@clusterNodeName nvarchar(256),
+		@serviceName nvarchar(256),
+		@tagPairs nvarchar(512),
+		@recordTimestamp bigint,
+		@metricRecordID bigint OUTPUT
+	AS
+	BEGIN
+		SET NOCOUNT ON;
+
+		DECLARE @recordTypeID int
+		DECLARE @nodeID int
+		DECLARE @clusterNodeID int
+		DECLARE @tagSetID int
+		DECLARE @serviceID int
+		DECLARE @err int
+		DECLARE @recordIDCutoff bigint
+	
+		BEGIN TRANSACTION;
+		SELECT @recordTypeID = RecordTypeID FROM RecordType WHERE Context = @recordTypeContext AND Name = @recordTypeName;
+		IF @recordTypeID IS NULL
+			BEGIN
+				INSERT INTO RecordType (Context, Name) VALUES (@recordTypeContext, @recordTypeName);
+				SELECT @err = @@ERROR, @recordTypeID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		COMMIT TRANSACTION;
+		
+		BEGIN TRANSACTION;
+		SELECT @serviceID = serviceID FROM Service WHERE Name = @serviceName;
+		IF @serviceID IS NULL
+			BEGIN
+				INSERT INTO Service (Name) VALUES (@serviceName);	
+				SELECT @err = @@ERROR, @serviceID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		COMMIT TRANSACTION;
+
+		BEGIN TRANSACTION;
+		SELECT @nodeID = NodeID FROM Node WHERE Name = @nodeName;
+	
+		IF @nodeID IS NULL
+			BEGIN
+		    
+			/* Start with a node type of uninitialized.  HealthNode will determine node type based on metrics delivered over time. */
+				INSERT INTO Node (Name, LastKnownIP) VALUES (@nodeName, @sourceIP);  
+				SELECT @err = @@ERROR, @nodeID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		
+		COMMIT TRANSACTION;
+
+		-- Do our best to determine the cluster node ID based on completely flakey input from user which might be an IP address, a non-FQDN,
+		-- or an FQDN.  Note that worker nodes may have a completely different idea about the name of the namenode (which is the node
+		-- which represents the cluster) compared with the namenode itself
+
+		BEGIN TRANSACTION;
+		IF ((SELECT [dbo].[ufnIsIPAddress](@clusterNodeName)) = 1)
+		BEGIN
+			SELECT TOP 1 @clusterNodeID = NodeID from Node WHERE LastKnownIP = @clusterNodeName ORDER BY LastNameNodeHeartBeat DESC;
+			IF @clusterNodeID IS NULL
+			BEGIN
+				INSERT INTO Node (Name, LastKnownIP) VALUES (@clusterNodeName, @sourceIP);  
+				SELECT @err = @@ERROR, @clusterNodeID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		END
+		ELSE
+		IF ((SELECT CHARINDEX(@clusterNodeName, ''.'', 1)) > 0)
+		BEGIN
+			-- IF this is not an IP address, but there is a dot in the name we assume we are looking at an FQDN
+		SELECT @clusterNodeID = NodeID FROM Node WHERE Name = @clusterNodeName;
+		IF @clusterNodeID IS NULL
+			BEGIN
+				INSERT INTO Node (Name, LastKnownIP) VALUES (@clusterNodeName, @sourceIP);  
+				SELECT @err = @@ERROR, @clusterNodeID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		END
+		ELSE
+		BEGIN
+			-- We have got a non-FQDN, but the NameNode might know its FQDN, so be careful! We must prefer the FQDN if we can find one. 
+			-- Sadly, yes, this could break things if we are monitoring clusters from different domains.  This is now by design!
+			SELECT TOP 1 @clusterNodeID = NodeID FROM Node WHERE Name LIKE @clusterNodeName + ''.%'' ORDER BY LastNameNodeHeartBeat DESC;
+			IF @clusterNodeID IS NULL
+				BEGIN
+					SELECT @clusterNodeID = NodeID FROM Node WHERE Name = @clusterNodeName;
+					if @clusterNodeID IS NULL
+					BEGIN
+						INSERT INTO Node (Name, LastKnownIP) VALUES (@clusterNodeName, @sourceIP);  
+						SELECT @err = @@ERROR, @clusterNodeID = SCOPE_IDENTITY();
+						IF @err <> 0 GOTO Abort;
+					END
+				END
+		END
+		COMMIT TRANSACTION;
+
+		-- Cleanup older metric records and pairs if necessary
+		-- Policy is to keep between 60000 and 90000 metric records and associated metric pairs per node.
+		IF (SELECT COUNT(*) FROM MetricRecord WHERE NodeID = @nodeID) > 90000
+		BEGIN
+			SELECT @recordIDCutoff = MIN(RecordID) FROM MetricRecord WHERE RecordID IN (SELECT TOP 60000 RecordID FROM MetricRecord WHERE NodeID = @nodeID ORDER BY RecordDate DESC);
+			IF @recordIDCutoff IS NOT NULL
+			BEGIN
+				DELETE FROM MetricPair 
+				FROM MetricPair as mp
+				JOIN MetricRecord as mr ON mp.RecordID = mr.RecordID
+				WHERE mr.RecordID < @recordIDCutoff AND mr.NodeID = @nodeID;
+
+				DELETE FROM MetricRecord
+				WHERE RecordID < @recordIDCutoff AND NodeID = @nodeID;
+			END;
+		END;
+
+
+		BEGIN TRANSACTION;
+		SELECT @tagSetID = TagSetID FROM TagSet WHERE TagPairs = @tagPairs;
+		IF @tagSetID IS NULL
+			BEGIN
+				INSERT INTO TagSet (TagPairs) VALUES (@tagPairs);
+				SELECT @err = @@ERROR, @tagSetID = SCOPE_IDENTITY();
+				IF @err <> 0 GOTO Abort;
+			END
+		COMMIT TRANSACTION;
+
+		BEGIN TRANSACTION;
+		SELECT @metricRecordID = RecordID FROM MetricRecord WHERE RecordTypeID = @recordTypeID AND NodeID = @nodeID AND ServiceID = @serviceID AND TagSetID = @tagSetID AND RecordTimestamp = @recordTimestamp;
+		IF @metricRecordID IS NULL
+		BEGIN
+			INSERT INTO MetricRecord (RecordTypeID, NodeID, SourceIP, ClusterNodeID, ServiceID, TagSetID, RecordTimestamp) VALUES (@recordTypeID, @nodeID, @sourceIP, @clusterNodeID, @serviceID, @tagSetID, @recordTimestamp);
+			SELECT @err = @@ERROR, @metricRecordID = SCOPE_IDENTITY();
+			IF @err <> 0 GOTO Abort;
+		END
+		COMMIT TRANSACTION;
+
+		GOTO Success;
+
+	Abort:
+		ROLLBACK TRANSACTION;
+		SET @metricRecordID = NULL;
+		RETURN;
+
+	Success:
+		RETURN;
+
+	END')
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'ufnIsIPAddress' and type_desc = N'SQL_SCALAR_FUNCTION')
+BEGIN
+	PRINT N'Creating [dbo].[ufnIsIPAddress]...';
+	exec('CREATE FUNCTION [dbo].[ufnIsIPAddress]
+	(
+		@inputString nvarchar(max) 
+	)
+	RETURNS BIT
+	AS
+	BEGIN
+		DECLARE @currentPos bigint = 1;
+		DECLARE @nextPos bigint = 0;
+		DECLARE @count int = 0;
+
+		if (LEN(@inputString) = 0) RETURN 0;
+	
+		SELECT @nextPos = CHARINDEX(''.'', @inputString, @currentPos);
+
+		WHILE (@nextPos < LEN(@inputString) AND @count < 4)
+		BEGIN
+			IF (@nextPos = 0) SET @nextPos = LEN(@inputString);
+			IF ((SELECT ISNUMERIC(SUBSTRING(@inputString, @currentPos, @nextPos - @currentPos))) = 1)
+			BEGIN
+				SET @count = @count + 1;
+				SET @currentPos = @nextPos
+				SELECT @nextPos = CHARINDEX(''.'', @inputString, @currentPos + 1);
+			END
+			ELSE BREAK;
+		END
+
+		IF (@count = 4) RETURN 1;
+
+		SET @currentPos = 1;
+		SET @nextPos = 0;
+		SET @count = 0;
+
+		WHILE (@currentPos <= LEN(@inputString))
+		BEGIN
+			IF EXISTS (SELECT 1 WHERE SUBSTRING(@inputString, @currentPos, 1) LIKE ''[0-9A-Fa-f:]'')
+			BEGIN
+				IF (SUBSTRING(@inputString, @currentPos, 1) = N'':'') SET @count = @count + 1;
+				SET @currentPos = @currentPos + 1;
+			END
+			ELSE RETURN 0;
+		END
+		IF @count >= 4 return 1;
+
+		RETURN 0;
+	END')
+END
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'RethrowError' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating Stored Proc: [dbo].[RethrowError]...';
+	exec('CREATE PROCEDURE [dbo].[RethrowError]
+	AS
+	BEGIN
+		DECLARE @ErrorMessage NVARCHAR(4000);
+		DECLARE @ErrorSeverity INT;
+		DECLARE @ErrorState INT;
+
+		SELECT 
+			@ErrorMessage = ERROR_MESSAGE(),
+			@ErrorSeverity = ERROR_SEVERITY(),
+			@ErrorState = ERROR_STATE();
+
+		RAISERROR (@ErrorMessage, -- Message text.
+				   @ErrorSeverity, -- Severity.
+				   @ErrorState -- State.
+				   );
+	END
+	')
+END
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'uspPurgeMetrics' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+    -- purge metrics older than @noOfDays
+	PRINT N'Creating [dbo].[uspPurgeMetrics]...';
+	exec('CREATE PROCEDURE [dbo].[uspPurgeMetrics]
+			@noOfDays bigint
+	AS
+	BEGIN
+	
+		IF @noOfDays IS NULL OR @noOfDays < 1 
+		BEGIN
+			RAISERROR(''INVALID_ARGUMENT'', 15, 1)
+			RETURN
+		END;
+	
+		DECLARE @recordIDCutOff BIGINT
+		SELECT @recordIDCutoff = MAX(RecordID) FROM MetricRecord WHERE DateDiff(day, RecordDate, CURRENT_TIMESTAMP) >= @noOfDays
+	
+		IF @recordIDCutoff IS NOT NULL
+		BEGIN
+			BEGIN TRY
+				BEGIN TRANSACTION
+		
+				DELETE FROM MetricPair WHERE RecordID <= @recordIDCutoff
+
+				DELETE FROM MetricRecord WHERE RecordID <= @recordIDCutoff			
+		
+				IF @@TRANCOUNT > 0
+				BEGIN
+					COMMIT TRANSACTION
+				END
+			
+			END TRY
+			BEGIN CATCH
+				IF @@TRANCOUNT > 0
+				BEGIN
+					ROLLBACK TRANSACTION;
+				END
+
+				 -- get error infromation and raise error
+				EXECUTE [dbo].[RethrowError]
+				RETURN
+
+			END CATCH
+		END;
+	END');
+END
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'ufGetMetrics' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating [dbo].[ufGetMetrics]...';
+exec(	'CREATE FUNCTION dbo.ufGetMetrics
+		(@startTimeStamp bigint, 
+		 @endTimeStamp bigint, 
+		 @recordTypeContext NVARCHAR(256),
+		 @recordTypeName NVARCHAR(256), 
+		 @metricName NVARCHAR(256), 
+		 @serviceComponentName NVARCHAR(256),
+		 @nodeName NVARCHAR(256)
+		) 
+		RETURNS TABLE --(MetricTimeStamp bigint, MetricValue NVARCHAR(512))
+		AS
+		RETURN
+		(
+			SELECT  s.RecordTimeStamp AS RecordTimeStamp,
+					mp.MetricValue AS MetricValue 
+			FROM MetricPair mp
+			INNER JOIN (SELECT	mr.RecordID AS RecordID, 
+								mr.RecordTimeStamp AS RecordTimeStamp
+						FROM MetricRecord mr 
+						INNER JOIN RecordType rt ON (mr.RecordTypeId = rt.RecordTypeId) 
+						INNER JOIN Node nd ON (mr.NodeID = nd.NodeID)
+						INNER JOIN Service sr ON (mr.ServiceID = sr.ServiceID)
+						WHERE rt.Context = @recordTypeContext 
+						AND rt.Name = @recordTypeName
+						AND (nd.Name = @nodeName)
+						AND (sr.Name = @serviceComponentName)    
+						AND mr.RecordTimestamp >= @startTimeStamp 
+						AND mr.RecordTimestamp <= @endTimeStamp
+						) s ON (mp.RecordID = s.RecordID)
+			INNER JOIN MetricName mn ON (mp.MetricID = mn.MetricID)  
+			WHERE (mn.Name = @metricName)
+		)'
+)
+END
+
+GO
+
+IF NOT EXISTS(SELECT name FROM sys.objects WHERE name = N'ufGetAggregatedServiceMetrics' and type_desc = N'SQL_STORED_PROCEDURE')
+BEGIN
+	PRINT N'Creating [dbo].[ufGetAggregatedServiceMetrics]...';
+    exec( 'CREATE FUNCTION [dbo].[ufGetAggregatedServiceMetrics]
+		(@startTimeStamp bigint, 
+		 @endTimeStamp bigint, 
+		 @recordTypeContext NVARCHAR(256),
+		 @recordTypeName NVARCHAR(256), 
+		 @metricName NVARCHAR(256), 
+		 @serviceComponentName NVARCHAR(256),
+		 @period integer
+		)
+		RETURNS TABLE ----(TimeStampBlock integer, MetricTimeStamp bigint, MetricValue NVARCHAR(512))
+		AS
+		RETURN
+		(
+			SELECT FLOOR ((mr.RecordTimeStamp - @startTimeStamp) / @period) TimeStampBlock, MAX(mr.RecordTimeStamp) RecordTimeStamp,  SUM(CONVERT(NUMERIC(18,4), MetricValue)) AggMetricValue
+			FROM MetricPair mp
+			INNER JOIN MetricRecord mr ON (mp.RecordID = mr.RecordID)
+			INNER JOIN RecordType rt ON (rt.RecordTypeID = mr.RecordTypeID)
+			INNER JOIN MetricName mn ON (mn.MetricID = mp.MetricID)
+			INNER JOIN Service sr ON (sr.ServiceID = mr.ServiceID)
+			WHERE mr.RecordTimestamp >= @startTimeStamp 
+			AND mr.RecordTimestamp <= @endTimeStamp 
+			AND mn.Name = @metricName
+			AND rt.Context = @recordTypeContext
+			AND rt.Name = @recordTypeName
+			AND sr.Name = @serviceComponentName
+			GROUP BY FLOOR ((mr.RecordTimeStamp - @startTimeStamp) / @period)
+		)'
+	    )
+END
+GO

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/metrics-sink/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/metrics-sink/pom.xml b/contrib/ambari-scom/metrics-sink/pom.xml
new file mode 100644
index 0000000..7a3f3cc
--- /dev/null
+++ b/contrib/ambari-scom/metrics-sink/pom.xml
@@ -0,0 +1,80 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.apache.ambari</groupId>
+        <artifactId>ambari-scom-project</artifactId>
+        <version>0.9.0</version>
+    </parent>  
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>metrics-sink</artifactId>
+    <packaging>jar</packaging>
+    <name>Ambari SCOM Metrics Sink</name>
+    <url>http://maven.apache.org</url>
+    <dependencies>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.17</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>3.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-core</artifactId>
+            <version>[1.0,2.0)</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.12</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>rpm-maven-plugin</artifactId>
+                <version>2.0.1</version>
+                <executions>
+                    <execution>
+                        <phase>none</phase>
+                        <goals>
+                            <goal>rpm</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/metrics-sink/src/Test/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/metrics-sink/src/Test/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/contrib/ambari-scom/metrics-sink/src/Test/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
new file mode 100644
index 0000000..41db9b1
--- /dev/null
+++ b/contrib/ambari-scom/metrics-sink/src/Test/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.microsoft.sqlserver.jdbc;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+/**
+ * Test SQLServer driver class.
+ */
+public class SQLServerDriver implements Driver {
+
+  private static final SQLServerDriver singleton = new SQLServerDriver();
+
+  private static Connection connection;
+
+  static {
+    try {
+      DriverManager.registerDriver(singleton);
+    } catch (SQLException e) {
+      System.out.println("SQLServerDriver.static intializer : can't register driver with manager : " + e);
+    }
+  }
+
+  private SQLServerDriver() {
+  }
+
+  @Override
+  public Connection connect(String s, Properties properties) throws SQLException {
+    return connection;
+  }
+
+  @Override
+  public boolean acceptsURL(String s) throws SQLException {
+    return true;
+  }
+
+  @Override
+  public DriverPropertyInfo[] getPropertyInfo(String s, Properties properties) throws SQLException {
+    return new DriverPropertyInfo[0];
+  }
+
+  @Override
+  public int getMajorVersion() {
+    return 1;
+  }
+
+  @Override
+  public int getMinorVersion() {
+    return 0;
+  }
+
+  @Override
+  public boolean jdbcCompliant() {
+    return true;
+  }
+
+//  @Override
+  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+    throw new SQLFeatureNotSupportedException();
+  }
+
+  public static void setConnection(Connection conn) {
+    connection = conn;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/metrics-sink/src/Test/java/org/apache/hadoop/metrics2/sink/SqlServerSinkTest.java
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/metrics-sink/src/Test/java/org/apache/hadoop/metrics2/sink/SqlServerSinkTest.java b/contrib/ambari-scom/metrics-sink/src/Test/java/org/apache/hadoop/metrics2/sink/SqlServerSinkTest.java
new file mode 100644
index 0000000..4d4f6dd
--- /dev/null
+++ b/contrib/ambari-scom/metrics-sink/src/Test/java/org/apache/hadoop/metrics2/sink/SqlServerSinkTest.java
@@ -0,0 +1,284 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.metrics2.sink;
+
+import com.microsoft.sqlserver.jdbc.SQLServerDriver;
+import org.apache.commons.configuration.SubsetConfiguration;
+import org.apache.hadoop.metrics2.Metric;
+import org.apache.hadoop.metrics2.MetricsRecord;
+import org.apache.hadoop.metrics2.MetricsTag;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ * SqlServerSink Tests.
+ */
+public class SqlServerSinkTest {
+  @Test
+  public void testInit() throws Exception {
+
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    // replay
+    replay(configuration);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    verify(configuration);
+  }
+
+  @Test
+  public void testEnsureConnection() throws Exception {
+
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    // replay
+    replay(configuration, connection);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    Assert.assertFalse(sink.ensureConnection());
+
+    SQLServerDriver.setConnection(connection);
+    Assert.assertTrue(sink.ensureConnection());
+
+    verify(configuration, connection);
+  }
+
+  @Test
+  public void testFlush() throws Exception {
+
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+    connection.close();
+
+    // replay
+    replay(configuration, connection);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    SQLServerDriver.setConnection(connection);
+    sink.ensureConnection();
+    sink.flush();
+
+    verify(configuration, connection);
+  }
+
+  @Test
+  public void testGetMetricRecordID() throws Exception {
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+    CallableStatement cstmt = createNiceMock(CallableStatement.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    expect(connection.prepareCall("{call dbo.uspGetMetricRecord(?, ?, ?, ?, ?, ?, ?, ?, ?)}")).andReturn(cstmt);
+    cstmt.setNString(1, "context");
+    cstmt.setNString(2, "typeName");
+    cstmt.setNString(3, "nodeName");
+    cstmt.setNString(4, "ip");
+    cstmt.setNString(5, "clusterName");
+    cstmt.setNString(6, "serviceName");
+    cstmt.setNString(7, "tagPairs");
+    cstmt.setLong(8, 9999L);
+    cstmt.registerOutParameter(9, java.sql.Types.BIGINT);
+    expect(cstmt.execute()).andReturn(true);
+    expect(cstmt.getLong(9)).andReturn(99L);
+    expect(cstmt.wasNull()).andReturn(false);
+
+    // replay
+    replay(configuration, connection, cstmt);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    SQLServerDriver.setConnection(connection);
+
+    Assert.assertEquals(99,
+        sink.getMetricRecordID("context", "typeName", "nodeName", "ip", "clusterName", "serviceName", "tagPairs", 9999L));
+
+    verify(configuration, connection, cstmt);
+  }
+
+  @Test
+  public void testGetMetricRecordID_nullReturn() throws Exception {
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+    CallableStatement cstmt = createNiceMock(CallableStatement.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    expect(connection.prepareCall("{call dbo.uspGetMetricRecord(?, ?, ?, ?, ?, ?, ?, ?, ?)}")).andReturn(cstmt);
+    cstmt.setNString(1, "context");
+    cstmt.setNString(2, "typeName");
+    cstmt.setNString(3, "nodeName");
+    cstmt.setNString(4, "ip");
+    cstmt.setNString(5, "clusterName");
+    cstmt.setNString(6, "serviceName");
+    cstmt.setNString(7, "tagPairs");
+    cstmt.setLong(8, 9999L);
+    cstmt.registerOutParameter(9, java.sql.Types.BIGINT);
+    expect(cstmt.execute()).andReturn(true);
+    expect(cstmt.getLong(9)).andReturn(99L);
+    expect(cstmt.wasNull()).andReturn(true);
+
+    // replay
+    replay(configuration, connection, cstmt);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    SQLServerDriver.setConnection(connection);
+
+    Assert.assertEquals(-1,
+        sink.getMetricRecordID("context", "typeName", "nodeName", "ip", "clusterName", "serviceName", "tagPairs", 9999L));
+
+    verify(configuration, connection, cstmt);
+  }
+
+  @Test
+  public void testInsertMetricValue() throws Exception {
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+    CallableStatement cstmt = createNiceMock(CallableStatement.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    expect(connection.prepareCall("{call dbo.uspInsertMetricValue(?, ?, ?)}")).andReturn(cstmt);
+    cstmt.setLong(1, 9999L);
+    cstmt.setNString(2, "metricName");
+    cstmt.setNString(3, "metricValue");
+    expect(cstmt.execute()).andReturn(true);
+
+    // replay
+    replay(configuration, connection, cstmt);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    SQLServerDriver.setConnection(connection);
+
+    sink.insertMetricValue(9999L, "metricName", "metricValue");
+
+    verify(configuration, connection, cstmt);
+  }
+
+  @Test
+  public void testPutMetrics() throws Exception {
+    SubsetConfiguration configuration = createNiceMock(SubsetConfiguration.class);
+    Connection connection = createNiceMock(Connection.class);
+    CallableStatement cstmt = createNiceMock(CallableStatement.class);
+    MetricsRecord record = createNiceMock(MetricsRecord.class);
+    Metric metric = createNiceMock(Metric.class);
+
+    // set expectations
+    expect(configuration.getParent()).andReturn(null);
+    expect(configuration.getPrefix()).andReturn("prefix");
+    expect(configuration.getString("databaseUrl")).andReturn("url");
+
+    expect(record.context()).andReturn("context");
+    expect(record.name()).andReturn("typeName");
+    expect(record.tags()).andReturn(new HashSet<MetricsTag>());
+    expect(record.timestamp()).andReturn(9999L);
+
+    expect(record.metrics()).andReturn(Collections.singleton(metric));
+
+    expect(metric.name()).andReturn("name").anyTimes();
+    expect(metric.value()).andReturn(1234);
+
+    expect(connection.prepareCall("{call dbo.uspGetMetricRecord(?, ?, ?, ?, ?, ?, ?, ?, ?)}")).andReturn(cstmt);
+    cstmt.setNString(1, "context");
+    cstmt.setNString(2, "typeName");
+    cstmt.setNString(eq(3), (String) anyObject());
+    cstmt.setNString(eq(4), (String) anyObject());
+    cstmt.setNString(eq(5), (String) anyObject());
+    cstmt.setNString(6, "prefix");
+    cstmt.setNString(7, "sourceName:prefix");
+    cstmt.setLong(8, 9999L);
+    cstmt.registerOutParameter(9, java.sql.Types.BIGINT);
+    expect(cstmt.execute()).andReturn(true);
+    expect(cstmt.getLong(9)).andReturn(99L);
+    expect(cstmt.wasNull()).andReturn(false);
+
+    expect(connection.prepareCall("{call dbo.uspInsertMetricValue(?, ?, ?)}")).andReturn(cstmt);
+    cstmt.setLong(1, 99L);
+    cstmt.setNString(2, "name");
+    cstmt.setNString(3, "1234");
+    expect(cstmt.execute()).andReturn(true);
+
+    // replay
+    replay(configuration, connection, cstmt, record, metric);
+
+    SqlServerSink sink = new SqlServerSink();
+
+    sink.init(configuration);
+
+    SQLServerDriver.setConnection(connection);
+
+    sink.putMetrics(record);
+
+    verify(configuration, connection, cstmt, record, metric);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/metrics-sink/src/main/java/org/apache/hadoop/metrics2/sink/SqlServerSink.java
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/metrics-sink/src/main/java/org/apache/hadoop/metrics2/sink/SqlServerSink.java b/contrib/ambari-scom/metrics-sink/src/main/java/org/apache/hadoop/metrics2/sink/SqlServerSink.java
new file mode 100644
index 0000000..034876a
--- /dev/null
+++ b/contrib/ambari-scom/metrics-sink/src/main/java/org/apache/hadoop/metrics2/sink/SqlServerSink.java
@@ -0,0 +1,314 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.metrics2.sink;
+
+import java.lang.Exception;
+import java.net.InetAddress;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.configuration.SubsetConfiguration;
+import org.apache.hadoop.metrics2.Metric;
+import org.apache.hadoop.metrics2.MetricsException;
+import org.apache.hadoop.metrics2.MetricsRecord;
+import org.apache.hadoop.metrics2.MetricsSink;
+import org.apache.hadoop.metrics2.MetricsTag;
+import org.apache.log4j.Logger;
+
+/**
+ * This class stores published metrics to the SQL Server database.
+ */
+public class SqlServerSink implements MetricsSink {
+  private static final String DATABASE_URL_KEY = "databaseUrl";
+  private static final boolean DEBUG = true;
+  private static final String NAME_URL_KEY = "fs.default.name";
+  private static final Pattern NAME_URL_REGEX = Pattern.compile(
+      "hdfs://([^ :/]*)", Pattern.CASE_INSENSITIVE);
+  private static final String DFS_BLOCK_SIZE_KEY = "dfs.block.size";
+  private int blockSize = -1;
+  private String currentServiceName = "";
+  private String databaseUrl;
+  private Connection conn = null;
+  StringBuilder tagsListBuffer = new StringBuilder();
+  String nodeName = null;
+  String nodeIPAddress = null;
+  org.apache.hadoop.conf.Configuration hadoopConfig = null;
+  String clusterName = "localhost";
+
+  static Logger logger = Logger.getLogger(SqlServerSink.class);
+
+  @Override
+  public void init(SubsetConfiguration conf) {
+    String nameNodeUrl;
+    String blockSizeString;
+
+    logger.info("Entering init");
+
+    currentServiceName = getFirstConfigPrefix(conf);
+
+    databaseUrl = conf.getString(DATABASE_URL_KEY);
+
+    if (databaseUrl == null)
+      throw new MetricsException(
+          "databaseUrl required in the metrics2 configuration for SqlServerSink.");
+
+    try {
+      Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
+    } catch (ClassNotFoundException cnfe) {
+      throw new MetricsException(
+          "SqlServerSink requires the Microsoft JDBC driver for SQL Server.");
+    }
+
+    hadoopConfig = new org.apache.hadoop.conf.Configuration();
+    if (hadoopConfig != null) {
+      nameNodeUrl = hadoopConfig.get(NAME_URL_KEY);
+      if (nameNodeUrl != null) {
+        Matcher matcher = NAME_URL_REGEX.matcher(nameNodeUrl);
+        if (matcher.find()) {
+          clusterName = matcher.group(1);
+        }
+      }
+      blockSizeString = hadoopConfig.get(DFS_BLOCK_SIZE_KEY);
+      if (blockSizeString != null) {
+        try {
+          blockSize = Integer.parseInt(blockSizeString);
+        } catch (NumberFormatException nfe) {
+          // do nothing
+        }
+      }
+
+    }
+    logger.info("Exit init, cluster name = " + clusterName);
+  }
+
+  private String getFirstConfigPrefix(SubsetConfiguration conf) {
+    while (conf.getParent() instanceof SubsetConfiguration) {
+      conf = (SubsetConfiguration) conf.getParent();
+    }
+    return conf.getPrefix();
+  }
+
+  @Override
+  public void putMetrics(MetricsRecord record) {
+    long metricRecordID = getMetricRecordID(record.context(), record.name(),
+        getLocalNodeName(), getLocalNodeIPAddress(), getClusterNodeName(), currentServiceName,
+        getTagString(record.tags()), record.timestamp());
+    if (metricRecordID < 0)
+      return;
+
+    for (Metric metric : record.metrics()) {
+      insertMetricValue(metricRecordID, metric.name(), String.valueOf(metric
+          .value()));
+      if (metric.name().equals("BlockCapacity")) {
+        insertMetricValue(metricRecordID, "BlockSize", Integer
+            .toString(blockSize));
+      }
+    }
+  }
+
+  @Override
+  public void flush() {
+    try {
+      if (conn != null)
+        conn.close();
+    } catch (Exception e) {
+      // do nothing
+    }
+    conn = null;
+  }
+
+  public String getLocalNodeName() {
+    if (nodeName == null) {
+      try {
+        nodeName = InetAddress.getLocalHost().getCanonicalHostName();
+      } catch (Exception e) {
+        if (DEBUG)
+          logger.info("Error during getLocalHostName: " + e.toString());
+      }
+      if (nodeName == null)
+        nodeName = "Unknown";
+    }
+    return nodeName;
+  }
+
+  public String getClusterNodeName() {
+    if (clusterName.equalsIgnoreCase("localhost"))
+      return getLocalNodeName();
+    try {
+      return InetAddress.getByName(clusterName).getCanonicalHostName();
+    } catch (Exception e) {
+      if (DEBUG)
+        logger.info("Error during getClusterNodeName: " + e.toString());
+    }
+
+    return clusterName;
+  }
+
+  public String getLocalNodeIPAddress() {
+    if (nodeIPAddress == null) {
+      try {
+        nodeIPAddress = InetAddress.getLocalHost().getHostAddress();
+      } catch (Exception e) {
+        if (DEBUG)
+          logger.info("Error during getLocalNodeIPAddress: " + e.toString());
+      }
+    }
+    if (nodeIPAddress == null)
+      nodeIPAddress = "127.0.0.1";
+    return nodeIPAddress;
+  }
+
+  /*
+   *  TODO: Keep a cache of all tag strings, potentially caching the TagSetID.
+   *  Caching the TagSetID will require some new stored procedures and new DAL
+   *  methods.
+   */
+  public String getTagString(Iterable<MetricsTag> desiredTags) {
+    /*
+     * We don't return tags (even sourceName) if no tags available. Most likely,
+     * when tags are empty - we don't need to distinguish services
+     */
+    if (desiredTags == null)
+      return null;
+
+    tagsListBuffer.setLength(0);
+    tagsListBuffer.append("sourceName:").append(currentServiceName);
+    String separator = ",";
+    for (MetricsTag tag : desiredTags) {
+      tagsListBuffer.append(separator);
+      tagsListBuffer.append(tag.name());
+      tagsListBuffer.append(":");
+      tagsListBuffer.append(String.valueOf(tag.value()));
+    }
+
+    return tagsListBuffer.toString();
+  }
+
+  public boolean ensureConnection() {
+    if (conn == null) {
+      try {
+        if (databaseUrl != null) {
+          conn = DriverManager.getConnection(databaseUrl);
+        }
+      } catch (Exception e) {
+        if (DEBUG)
+          logger.info("Error during getConnection: " + e.toString());
+      }
+    }
+    return conn != null;
+  }
+
+  public long getMetricRecordID(String recordTypeContext,
+                                String recordTypeName, String nodeName, String sourceIP,
+                                String clusterName, String serviceName, String tagPairs, long recordTimestamp) {
+    CallableStatement cstmt = null;
+    long result;
+    if (recordTypeContext == null || recordTypeName == null || nodeName == null
+        || sourceIP == null || tagPairs == null)
+      return -1;
+
+    int colid = 1;
+    try {
+      if (ensureConnection()) {
+        cstmt = conn
+            .prepareCall("{call dbo.uspGetMetricRecord(?, ?, ?, ?, ?, ?, ?, ?, ?)}");
+        cstmt.setNString(colid++, recordTypeContext);
+        cstmt.setNString(colid++, recordTypeName);
+        cstmt.setNString(colid++, nodeName);
+        cstmt.setNString(colid++, sourceIP);
+        cstmt.setNString(colid++, clusterName);
+        cstmt.setNString(colid++, serviceName);
+        cstmt.setNString(colid++, tagPairs);
+        cstmt.setLong(colid++, recordTimestamp);
+        cstmt.registerOutParameter(colid, java.sql.Types.BIGINT);
+        cstmt.execute();
+        result = cstmt.getLong(colid);
+        if (cstmt.wasNull())
+          return -1;
+        return result;
+      }
+    } catch (Exception e) {
+      if (DEBUG)
+        logger.info("Error during getMetricRecordID call sproc: "
+            + e.toString());
+      flush();
+    } finally {
+      if (cstmt != null) {
+        try {
+          cstmt.close();
+        } catch (SQLException se) {
+          if (DEBUG)
+            logger.info("Error during getMetricRecordID close cstmt: "
+                + se.toString());
+        }
+        /*
+         * We don't close the connection here because we are likely to be
+         * writing
+         * metric values next and it is more efficient to share the connection.
+         */
+      }
+    }
+    return -1;
+  }
+
+  /* 
+   * TODO: Think about sending all of this in one SP call if JDBC supports table
+   * valued parameters.
+   */
+  public void insertMetricValue(long metricRecordID, String metricName,
+                                String metricValue) {
+    CallableStatement cstmt = null;
+    if (metricRecordID < 0 || metricName == null || metricValue == null)
+      return;
+    try {
+      if (ensureConnection()) {
+        cstmt = conn.prepareCall("{call dbo.uspInsertMetricValue(?, ?, ?)}");
+        cstmt.setLong(1, metricRecordID);
+        cstmt.setNString(2, metricName);
+        cstmt.setNString(3, metricValue);
+        cstmt.execute();
+      }
+    } catch (Exception e) {
+      if (DEBUG)
+        logger.info("Error during insertMetricValue call sproc: "
+            + e.toString());
+      flush();
+    } finally {
+      if (cstmt != null) {
+        try {
+          cstmt.close();
+        } catch (SQLException se) {
+          if (DEBUG)
+            logger.info("Error during insertMetricValue close cstmt: "
+                + se.toString());
+        }
+        /*
+         * We don't close the connection here because we are likely to be
+         * writing
+         * more metric values next and it is more efficient to share the
+         * connection.
+         */
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/873b3502/contrib/ambari-scom/msi/build.cmd
----------------------------------------------------------------------
diff --git a/contrib/ambari-scom/msi/build.cmd b/contrib/ambari-scom/msi/build.cmd
new file mode 100644
index 0000000..e5a28b8
--- /dev/null
+++ b/contrib/ambari-scom/msi/build.cmd
@@ -0,0 +1,58 @@
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements.  See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License.  You may obtain a copy of the License at
+rem
+rem     http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+
+@echo on
+echo Copying resources
+pushd ..
+copy /y "%cd%\ambari-scom-server\target\ambari-scom-*.*" "%cd%\msi\src\AmbariPackages\ambari-winpkg\resources\" || exit /b 1
+copy /y "%cd%\metrics-sink\target\metrics-sink-*.jar" "%cd%\msi\src\AmbariPackages\ambari-winpkg\resources\" || exit /b 1
+copy /y "%cd%\metrics-sink\db\Hadoop-Metrics-SQLServer-CREATE.ddl" "%cd%\msi\src\AmbariPackages\ambari-winpkg\resources\" || exit /b 1
+popd
+
+echo Compressing resources
+powershell.exe -NoProfile -InputFormat none -ExecutionPolicy unrestricted -command "%cd%\build\zip.ps1" "%cd%\src\AmbariPackages\ambari-winpkg" "%cd%\src\AmbariPackages\ambari-winpkg.zip" || exit /b 1
+
+echo Building GUI
+set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
+call %msBuildDir%\msbuild.exe "%cd%\src\GUI\GUI_Ambari.csproj"  || exit /b 1
+copy /y "%cd%\src\GUI\bin\Debug\GUI_Ambari.exe" "%cd%\src\bin\GUI_Ambari.exe" || exit /b 1
+
+echo Building Result Messagebox
+call %msBuildDir%\msbuild.exe "%cd%\src\Result\Ambari_Result.csproj"  || exit /b 1
+copy /y "%cd%\src\Result\bin\Debug\Ambari_Result.exe" "%cd%\src\bin\Ambari_Result.exe" || exit /b 1
+
+echo Building MSI
+pushd "%cd%\src" || exit /b 1
+start /wait /min candle "%cd%\ambari-scom.wxs"  || exit /b 1
+start /wait /min light "%cd%\ambari-scom.wixobj"  || exit /b 1
+popd || exit /b 1
+copy /y "%cd%\src\ambari-scom.msi" "%cd%\ambari-scom.msi" || exit /b 1
+
+echo Cleaning 
+del /f /q "%cd%\src\ambari-scom.wixobj"  || exit /b 1
+del /f /q "%cd%\src\ambari-scom.wixpdb"  || exit /b 1
+del /f /q "%cd%\src\ambari-scom.msi"  || exit /b 1
+del /f /q "%cd%\src\bin\GUI_Ambari.exe"  || exit /b 1
+del /f /q "%cd%\src\bin\Ambari_Result.exe"  || exit /b 1
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg.zip" || exit /b 1
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.jar"  || exit /b 1
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\*.zip"  || exit /b 1
+del /f /q "%cd%\src\AmbariPackages\ambari-winpkg\resources\Hadoop-Metrics-SQLServer-CREATE.ddl"  || exit /b 1
+rd /s /q "%cd%\src\GUI\bin"  || exit /b 1
+rd /s /q "%cd%\src\GUI\obj"  || exit /b 1
+rd /s /q "%cd%\src\Result\bin"  || exit /b 1
+rd /s /q "%cd%\src\Result\obj"  || exit /b 1
+echo Done


Mime
View raw message