changeset 99:d15927dab809

merge 9.1.x
author Evgeniy.Koshkin@unit-519.Labs.IntelliJ.Net
date Mon, 16 May 2016 14:49:19 +0300
parents cee56ab3c315 (current diff) 6d1877c10a3b (diff)
children d9cb6eec6f74
files .idea/runConfigurations/Server.xml agent/src/jetbrains/buildServer/symbols/tools/WinDbgToolsHelper.java idea-resolve-helper.iml server-tests/src/DownloadSymbolsControllerTest.java server-tests/src/MetadataStorageMock.java server/server.iml
diffstat 40 files changed, 878 insertions(+), 319 deletions(-) [+]
line wrap: on
line diff
--- a/.idea/artifacts/deploy.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/artifacts/deploy.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,6 +1,12 @@
 <component name="ArtifactManager">
   <artifact name="deploy">
-    <output-path>$teamcitydistribution/../PluginDev.Data/plugins</output-path>
+    <output-path>$TeamCityDistribution/../PluginDev.Data/plugins</output-path>
+    <properties id="ant-postprocessing">
+      <options enabled="true">
+        <file>file://$PROJECT_DIR$/build/ant.build.xml</file>
+        <target>replace-tokens-in-teamcity-plugin-xml</target>
+      </options>
+    </properties>
     <root id="root">
       <element id="artifact" artifact-name="plugin-zip" />
     </root>
--- a/.idea/libraries/Agent_Api.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Agent_Api.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Agent-Api">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/devPackage/agent-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/agent-api.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$teamcitydistribution$/devPackage/src/openApi-source.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
--- a/.idea/libraries/Common_Api.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Common_Api.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,12 +1,11 @@
 <component name="libraryTable">
   <library name="Common-Api">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/devPackage/common-api.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/common-api.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$teamcitydistribution$/devPackage/src/openApi-source.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
--- a/.idea/libraries/Idea_OpenApi.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Idea_OpenApi.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Idea-OpenApi">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/util.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/openapi.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/resources_en.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/jdom.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/util.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/openapi.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/trove4j.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/resources_en.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/jdom.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/libraries/Server_Api.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Server_Api.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,11 +1,11 @@
 <component name="libraryTable">
   <library name="Server-Api">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/devPackage/server-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/server-api.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
-      <root url="jar://$teamcitydistribution$/devPackage/src/openApi-source.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/src/openApi-source.jar!/" />
     </SOURCES>
   </library>
 </component>
\ No newline at end of file
--- a/.idea/libraries/Servlet_Api.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Servlet_Api.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="Servlet Api">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/lib/servlet-api.jar!/" />
+      <root url="jar://$TeamCityDistribution$/lib/servlet-api.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/libraries/TeamCity_agent_runtime.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/TeamCity_agent_runtime.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,10 +1,10 @@
 <component name="libraryTable">
   <library name="TeamCity agent runtime">
     <CLASSES>
-      <root url="file://$teamcitydistribution$/buildAgent/lib" />
+      <root url="file://$TeamCityDistribution$/buildAgent/lib" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
-    <jarDirectory url="file://$teamcitydistribution$/buildAgent/lib" recursive="false" />
+    <jarDirectory url="file://$TeamCityDistribution$/buildAgent/lib" recursive="false" />
   </library>
 </component>
\ No newline at end of file
--- a/.idea/libraries/TeamCity_server_runtime.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/TeamCity_server_runtime.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,10 +1,10 @@
 <component name="libraryTable">
   <library name="TeamCity server runtime">
     <CLASSES>
-      <root url="file://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib" />
+      <root url="file://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
-    <jarDirectory url="file://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib" recursive="false" />
+    <jarDirectory url="file://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib" recursive="false" />
   </library>
 </component>
\ No newline at end of file
--- a/.idea/libraries/Test_Api.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/Test_Api.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,8 +1,8 @@
 <component name="libraryTable">
   <library name="Test-Api">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/devPackage/tests/tests-support.jar!/" />
-      <root url="jar://$teamcitydistribution$/devPackage/tests/tests-integration.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/tests/tests-support.jar!/" />
+      <root url="jar://$TeamCityDistribution$/devPackage/tests/tests-integration.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/libraries/idea_annotations_jar.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/idea_annotations_jar.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="idea annotations.jar">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/annotations.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/libraries/log4j.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/log4j.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="log4j">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/log4j-1.2.12.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/libraries/spring.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/spring.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,9 +1,9 @@
 <component name="libraryTable">
   <library name="spring">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/spring.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/spring-webmvc.jar!/" />
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/spring-security.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/spring.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/spring-webmvc.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/spring-security.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.idea/libraries/spring_test.xml	Mon May 16 14:49:19 2016 +0300
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="spring-test">
+    <CLASSES>
+      <root url="jar://$TeamCityDistribution$/devPackage/tests/spring-test.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
--- a/.idea/libraries/standard_jar.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/libraries/standard_jar.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="standard.jar">
     <CLASSES>
-      <root url="jar://$teamcitydistribution$/webapps/ROOT/WEB-INF/lib/standard.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/standard.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/.idea/modules.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/modules.xml	Mon May 16 14:49:19 2016 +0300
@@ -3,6 +3,7 @@
   <component name="ProjectModuleManager">
     <modules>
       <module fileurl="file://$PROJECT_DIR$/agent/agent.iml" filepath="$PROJECT_DIR$/agent/agent.iml" />
+      <module fileurl="file://$PROJECT_DIR$/agent-tests/agent-tests.iml" filepath="$PROJECT_DIR$/agent-tests/agent-tests.iml" />
       <module fileurl="file://$PROJECT_DIR$/common/common.iml" filepath="$PROJECT_DIR$/common/common.iml" />
       <module fileurl="file://$PROJECT_DIR$/idea-resolve-helper.iml" filepath="$PROJECT_DIR$/idea-resolve-helper.iml" />
       <module fileurl="file://$PROJECT_DIR$/server/server.iml" filepath="$PROJECT_DIR$/server/server.iml" />
--- a/.idea/runConfigurations/Server.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/.idea/runConfigurations/Server.xml	Mon May 16 14:49:19 2016 +0300
@@ -1,11 +1,11 @@
 <component name="ProjectRunConfigurationManager">
-  <configuration default="false" name="Server" type="#com.intellij.j2ee.web.tomcat.TomcatRunConfigurationFactory" factoryName="Local" APPLICATION_SERVER_NAME="Tomcat 7" ALTERNATIVE_JRE_ENABLED="false">
+  <configuration default="false" name="Server" type="#com.intellij.j2ee.web.tomcat.TomcatRunConfigurationFactory" factoryName="Local" APPLICATION_SERVER_NAME="Tomcat TC 8.1.x" ALTERNATIVE_JRE_ENABLED="false" ALTERNATIVE_JRE_PATH="">
     <option name="OPEN_IN_BROWSER" value="false" />
     <option name="OPEN_IN_BROWSER_URL" value="http://localhost:8111" />
-    <option name="COMMON_VM_ARGUMENTS" value="-ea -Xmx384m -XX:MaxPermSize=200m -Ddebug=true -server -XX:+HeapDumpOnOutOfMemoryError -Djava.awt.headless -DTC.res.disableAll=true -Dteamcity.development.mode=true -Dteamcity.development.shadowCopyClasses=true -Dteamcity.data.path=$teamcitydistribution$/../PluginDev.Data -Dteamcity_logs=$teamcitydistribution$/logs -Dlog4j.configuration=file:$teamcitydistribution$/conf/teamcity-server-log4j.xml" />
+    <option name="COMMON_VM_ARGUMENTS" value="-ea -Xmx384m -XX:MaxPermSize=200m -Ddebug=true -server -XX:+HeapDumpOnOutOfMemoryError -Djava.awt.headless -DTC.res.disableAll=true -Dteamcity.development.mode=true -Dteamcity.development.shadowCopyClasses=true -Dteamcity.data.path=%IDEA_RUN:TOMCAT_HOME%/../PluginDev.Data -Dteamcity_logs=%IDEA_RUN:TOMCAT_HOME%/logs -Dlog4j.configuration=file:%IDEA_RUN:TOMCAT_HOME%/conf/teamcity-server-log4j.xml" />
     <option name="UPDATING_POLICY" value="restart-server" />
     <deployment>
-      <file path="C:/Program Files/Java/jdk1.7.0_21/jre/bin/$teamcitydistribution$/webapps/ROOT">
+      <file path="C:/Progra~1/Java/jdk1.8.0_65/jre/bin/%IDEA_RUN:TOMCAT_HOME%/webapps/ROOT">
         <settings>
           <option name="CONTEXT_PATH" value="/bs" />
         </settings>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent-tests/agent-tests.iml	Mon May 16 14:49:19 2016 +0300
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="agent" />
+    <orderEntry type="library" name="Test-Api" level="project" />
+    <orderEntry type="library" name="testng" level="project" />
+    <orderEntry type="library" name="jmock" level="project" />
+    <orderEntry type="library" name="Common-Api" level="project" />
+    <orderEntry type="library" name="Idea-OpenApi" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="TeamCity agent runtime" level="project" />
+  </component>
+</module>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent-tests/src/jetbrains/buildServer/symbols/JetSymbolsExeTest.java	Mon May 16 14:49:19 2016 +0300
@@ -0,0 +1,54 @@
+package jetbrains.buildServer.symbols;
+
+import jetbrains.buildServer.BaseTestCase;
+import jetbrains.buildServer.agent.NullBuildProgressLogger;
+import jetbrains.buildServer.symbols.tools.JetSymbolsExe;
+import jetbrains.buildServer.util.FileUtil;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * @author Evgeniy.Koshkin
+ */
+public class JetSymbolsExeTest extends BaseTestCase {
+
+  private JetSymbolsExe myExe;
+
+  @Override
+  @BeforeMethod
+  public void setUp() throws Exception {
+    super.setUp();
+    File homeDir = new File("tools\\JetSymbols").getAbsoluteFile();
+    assertTrue("Failed to find JetSymbolsExe home dir on path " + homeDir.getAbsolutePath(), homeDir.isDirectory());
+    myExe = new JetSymbolsExe(homeDir);
+  }
+
+  @Test
+  public void testCmdParametersLengthLimit() throws Exception {
+    final File output = FileUtil.createTempFile("testCmdParametersLengthLimit", ".out");
+    final int dumpExitCode = myExe.dumpGuidsToFile(getFilesCollection(500), output, new NullBuildProgressLogger());
+    assertEquals(0, dumpExitCode);
+  }
+
+  @Test
+  public void testSpacesInPaths() throws Exception {
+    final File output = FileUtil.createTempFile("test spaces in paths", ".out");
+    final File input = FileUtil.createTempFile("test spaces in paths", ".in");
+    final int exitCode = myExe.dumpGuidsToFile(Collections.singleton(input), output, new NullBuildProgressLogger());
+    assertEquals(0, exitCode);
+  }
+
+  private Collection<File> getFilesCollection(int count) throws IOException {
+    Collection<File> result = new HashSet<File>();
+    for (int i = 0; i < count; i++){
+      result.add(FileUtil.createTempFile("foo", "boo"));
+    }
+    return result;
+  }
+}
Binary file agent-tests/testData/TeamCityAPI.IDE.dll has changed
--- a/agent/agent.iml	Wed Feb 26 17:25:53 2014 +0400
+++ b/agent/agent.iml	Mon May 16 14:49:19 2016 +0300
@@ -5,8 +5,8 @@
       <configuration>
         <fileset id="fileset1" name="agent" removed="false">
           <file>file://$MODULE_DIR$/src/META-INF/build-agent-plugin-symbol-server.xml</file>
-          <file>jar://$teamcitydistribution$/buildAgent/lib/agent.jar!/META-INF/buildAgentSpring.xml</file>
-          <file>jar://$teamcitydistribution$/buildAgent/lib/agent.jar!/META-INF/buildAgentPlugins.xml</file>
+          <file>jar://$TeamCityDistribution$/buildAgent/lib/agent.jar!/META-INF/buildAgentSpring.xml</file>
+          <file>jar://$TeamCityDistribution$/buildAgent/lib/agent.jar!/META-INF/buildAgentPlugins.xml</file>
           <file>file://$MODULE_DIR$/fake-teamcity-agent-plugin-context.xml</file>
         </fileset>
       </configuration>
@@ -20,6 +20,7 @@
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Agent-Api" level="project" />
+    <orderEntry type="library" name="idea annotations.jar" level="project" />
     <orderEntry type="library" name="Common-Api" level="project" />
     <orderEntry type="library" name="log4j" level="project" />
     <orderEntry type="library" name="Idea-OpenApi" level="project" />
--- a/agent/src/META-INF/build-agent-plugin-symbol-server.xml	Wed Feb 26 17:25:53 2014 +0400
+++ b/agent/src/META-INF/build-agent-plugin-symbol-server.xml	Mon May 16 14:49:19 2016 +0300
@@ -7,5 +7,6 @@
         >
 
   <bean class="jetbrains.buildServer.symbols.SymbolsIndexer"/>
+  <bean class="jetbrains.buildServer.symbols.WinDbgToolsDetector"/>
 
 </beans>
\ No newline at end of file
--- a/agent/src/jetbrains/buildServer/symbols/SymbolsIndexer.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/agent/src/jetbrains/buildServer/symbols/SymbolsIndexer.java	Mon May 16 14:49:19 2016 +0300
@@ -6,7 +6,6 @@
 import jetbrains.buildServer.agent.impl.artifacts.ArtifactsCollection;
 import jetbrains.buildServer.agent.plugins.beans.PluginDescriptor;
 import jetbrains.buildServer.symbols.tools.JetSymbolsExe;
-import jetbrains.buildServer.symbols.tools.WinDbgToolsHelper;
 import jetbrains.buildServer.util.EventDispatcher;
 import jetbrains.buildServer.util.FileUtil;
 import org.apache.log4j.Logger;
@@ -18,6 +17,7 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -28,6 +28,8 @@
   private static final Logger LOG = Logger.getLogger(SymbolsIndexer.class);
 
   public static final String PDB_FILE_EXTENSION = "pdb";
+  private static final String X64_SRCSRV = "\\x64\\srcsrv";
+  private static final String X86_SRCSRV = "\\x86\\srcsrv";
 
   @NotNull private final ArtifactsWatcher myArtifactsWatcher;
   @NotNull private final JetSymbolsExe myJetSymbolsExe;
@@ -45,18 +47,19 @@
     agentDispatcher.addListener(new AgentLifeCycleAdapter() {
       @Override
       public void buildStarted(@NotNull final AgentRunningBuild runningBuild) {
+        final long buildId = runningBuild.getBuildId();
         if(runningBuild.getBuildFeaturesOfType(SymbolsConstants.BUILD_FEATURE_TYPE).isEmpty()){
-          LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature disabled. No indexing will be performed.");
+          LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature disabled. No indexing will be performed for build with id " + buildId);
           return;
         }
-        LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature enabled.");
+        LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature enabled for build with id " + buildId);
 
         myProgressLogger = runningBuild.getBuildLogger();
         myBuildTempDirectory = runningBuild.getBuildTempDirectory();
 
-        mySrcSrvHomeDir = WinDbgToolsHelper.getSrcSrvHomeDir(runningBuild);
+        mySrcSrvHomeDir = getSrcSrvHomeDir(runningBuild);
         if (mySrcSrvHomeDir == null) {
-          LOG.error("Failed to find Source Server tools home directory. No symbol and source indexing will be performed.");
+          LOG.error("Failed to find Source Server tools home directory. No symbol and source indexing will be performed for build with id " + buildId);
           myProgressLogger.error("Failed to find Source Server tools home directory. No symbol and source indexing will be performed.");
           return;
         }
@@ -72,7 +75,7 @@
         if(!isIndexingApplicable()) return;
         if (mySymbolsToProcess.isEmpty()) {
           myProgressLogger.warning("Symbols weren't found in artifacts to be published.");
-          LOG.debug("Symbols weren't found in artifacts to be published.");
+          LOG.debug("Symbols weren't found in artifacts to be published for build with id " + build.getBuildId());
         } else {
           myProgressLogger.message("Collecting symbol files signatures.");
           LOG.debug("Collecting symbol files signatures.");
@@ -84,7 +87,7 @@
               myArtifactsWatcher.addNewArtifactsPath(symbolSignaturesFile + "=>" + ".teamcity/symbols");
             }
           } catch (IOException e) {
-            LOG.error("Error while dumping symbols/binaries signatures.", e);
+            LOG.error("Error while dumping symbols/binaries signatures for build with id " + build.getBuildId(), e);
             myProgressLogger.error("Error while dumping symbols/binaries signatures.");
             myProgressLogger.exception(e);
           }
@@ -124,6 +127,22 @@
     }
   }
 
+  @Nullable
+  private File getSrcSrvHomeDir(@NotNull AgentRunningBuild build) {
+    final Map<String,String> agentConfigParameters = build.getAgentConfiguration().getConfigurationParameters();
+    String winDbgHomeDir = agentConfigParameters.get(WinDbgToolsDetector.WIN_DBG_PATH);
+    if(winDbgHomeDir == null){
+      LOG.debug("WinDbg tools are not mentioned in agent configuration.");
+      return null;
+    }
+    File srcSrvHomeDir = new File(winDbgHomeDir, X64_SRCSRV);
+    if (srcSrvHomeDir.isDirectory()) return srcSrvHomeDir;
+    srcSrvHomeDir = new File(winDbgHomeDir, X86_SRCSRV);
+    if (srcSrvHomeDir.isDirectory()) return srcSrvHomeDir;
+    LOG.debug("Failed to find Source Server tools home directory under WinDbg tools home directory detected on path " + winDbgHomeDir);
+    return null;
+  }
+
   private Collection<File> getArtifactPathsByFileExtension(List<ArtifactsCollection> artifactsCollections, String fileExtension){
     final Collection<File> result = new HashSet<File>();
     for(ArtifactsCollection artifactsCollection : artifactsCollections){
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/jetbrains/buildServer/symbols/WinDbgToolsDetector.java	Mon May 16 14:49:19 2016 +0300
@@ -0,0 +1,131 @@
+package jetbrains.buildServer.symbols;
+
+import jetbrains.buildServer.agent.AgentLifeCycleAdapter;
+import jetbrains.buildServer.agent.AgentLifeCycleListener;
+import jetbrains.buildServer.agent.BuildAgent;
+import jetbrains.buildServer.agent.BuildAgentConfiguration;
+import jetbrains.buildServer.dotNet.DotNetConstants;
+import jetbrains.buildServer.util.EventDispatcher;
+import jetbrains.buildServer.util.Win32RegistryAccessor;
+import org.apache.log4j.Logger;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.FileFilter;
+
+import static jetbrains.buildServer.util.Bitness.BIT32;
+import static jetbrains.buildServer.util.Win32RegistryAccessor.Hive.LOCAL_MACHINE;
+
+/**
+ * @author Evgeniy.Koshkin
+ */
+public class WinDbgToolsDetector extends AgentLifeCycleAdapter {
+
+  private static final Logger LOG = Logger.getLogger(WinDbgToolsDetector.class);
+
+  private static final String WINDOWS_KITS_INSTALLED_ROOTS_KEY_PATH = "Software/Microsoft/Windows Kits/Installed Roots";
+  private static final String WIN_DBG_81_ROOT_ENTRY_NAME = "WindowsDebuggersRoot81";
+  private static final String WIN_SDK_81_ROOT_ENTRY_NAME = "KitsRoot81";
+  private static final String WIN_DBG_8_ROOT_ENTRY_NAME = "WindowsDebuggersRoot8";
+  private static final String WIN_SDK_8_ROOT_ENTRY_NAME = "KitsRoot8";
+  private static final String WIN_DBG_HOME_DIR_RELATIVE_SDK8 = "\\Debuggers";
+
+  public static final String WIN_DBG_PATH = "WinDbg" + DotNetConstants.PATH;
+  private static final String DEBUGGING_TOOLS_FOR_WINDOWS = "Debugging Tools for Windows";
+
+  @NotNull private final Win32RegistryAccessor myRegistryAccessor;
+
+  public WinDbgToolsDetector(@NotNull final EventDispatcher<AgentLifeCycleListener> events,
+                             @NotNull final Win32RegistryAccessor registryAccessor) {
+    myRegistryAccessor = registryAccessor;
+    events.addListener(this);
+  }
+
+  @Override
+  public void agentInitialized(@NotNull BuildAgent agent) {
+    final BuildAgentConfiguration config = agent.getConfiguration();
+    if (!config.getSystemInfo().isWindows()) return;
+    LOG.info("Searching WinDbg installation...");
+
+    LOG.info("Searching the WinDbg as part of Windows 8.1 SDK");
+    File winDbgHomeDir = searchSDK8x(WIN_DBG_81_ROOT_ENTRY_NAME, WIN_SDK_81_ROOT_ENTRY_NAME, "8.1");
+    if(winDbgHomeDir == null) {
+      LOG.info("Searching the WinDbg as part of Windows 8 SDK");
+      winDbgHomeDir = searchSDK8x(WIN_DBG_8_ROOT_ENTRY_NAME, WIN_SDK_8_ROOT_ENTRY_NAME, "8");
+    } if(winDbgHomeDir == null) {
+      LOG.info("Searching the WinDbg as part of Windows 7 SDK");
+      winDbgHomeDir = searchSDK7x();
+    }
+
+    if(winDbgHomeDir == null) LOG.info("WinDbg tools were not found on this machine.");
+    else{
+      final String winDbgHomeDirAbsolutePath = winDbgHomeDir.getAbsolutePath();
+      LOG.info("WinDbg tools were found on path " + winDbgHomeDirAbsolutePath);
+      config.addConfigurationParameter(WIN_DBG_PATH, winDbgHomeDirAbsolutePath);
+    }
+  }
+
+  @Nullable
+  private File searchSDK8x(String winDbgRootEntryName, String winSdkRootEntryName, String sdkVersion) {
+    File winDbgHomeDir = myRegistryAccessor.readRegistryFile(LOCAL_MACHINE, BIT32, WINDOWS_KITS_INSTALLED_ROOTS_KEY_PATH, winDbgRootEntryName);
+    if (winDbgHomeDir != null) return winDbgHomeDir;
+    final File sdkHomeDir = myRegistryAccessor.readRegistryFile(LOCAL_MACHINE, BIT32, WINDOWS_KITS_INSTALLED_ROOTS_KEY_PATH, winSdkRootEntryName);
+    if(sdkHomeDir == null){
+      LOG.debug(String.format("Failed to locate Windows SDK %s home directory.", sdkVersion));
+      return null;
+    }
+    LOG.debug(String.format("Windows SDK %s found, searching WinDbg under its home directory.", sdkHomeDir));
+    winDbgHomeDir = new File(sdkHomeDir, WIN_DBG_HOME_DIR_RELATIVE_SDK8);
+    if(winDbgHomeDir.isDirectory()) return winDbgHomeDir;
+    LOG.debug("Failed to find WinDbg home directory under Windows SDK home directory detected on path " + sdkHomeDir.getAbsolutePath());
+    return null;
+  }
+
+  @Nullable
+  private File searchSDK7x() {
+    final String systemDrive = ensureSuffix(getEnv("SYSTEMDRIVE", "C:"), ":").toUpperCase();
+    final File programFilesDir = new File(systemDrive, "Program Files");
+    final File programFilesX86Dir = new File(systemDrive, "Program Files (x86)");
+    if(!programFilesDir.isDirectory() && !programFilesX86Dir.isDirectory()){
+      LOG.debug(String.format("Failed to locate 'Program Files' directory on the machine. Checked paths: %s, %s", programFilesDir, programFilesX86Dir));
+      return null;
+    }
+    File winDbgHome = findWinDbgHomeInDirectory(programFilesDir);
+    if(winDbgHome == null){
+      winDbgHome = findWinDbgHomeInDirectory(programFilesX86Dir);
+    }
+    return winDbgHome;
+  }
+
+  @Nullable
+  private File findWinDbgHomeInDirectory(File directory) {
+    if (!directory.isDirectory()) return null;
+
+    final String directoryAbsolutePath = directory.getAbsolutePath();
+    LOG.info("Searching for WinDbg home under " + directoryAbsolutePath);
+
+    final File[] matches = directory.listFiles(new FileFilter() {
+      public boolean accept(File pathname) {
+        return pathname.isDirectory() && pathname.getName().startsWith(DEBUGGING_TOOLS_FOR_WINDOWS);
+      }
+    });
+
+    if (matches == null || matches.length == 0) LOG.info("WinDbg home was NOT found under " + directoryAbsolutePath);
+    else return matches[0];
+    return null;
+  }
+
+  @NotNull
+  private static String ensureSuffix(final @NotNull String string, final @NotNull String suffix) {
+    int n = string.length(),
+            m = suffix.length();
+    return n >= m && string.endsWith(suffix) ? string : string + suffix;
+  }
+
+  @NotNull
+  private static String getEnv(final @NotNull String variableName, final @NotNull String defaultValue) {
+    String value = System.getenv(variableName);
+    return value != null ? value : defaultValue;
+  }
+}
--- a/agent/src/jetbrains/buildServer/symbols/tools/JetSymbolsExe.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/agent/src/jetbrains/buildServer/symbols/tools/JetSymbolsExe.java	Mon May 16 14:49:19 2016 +0300
@@ -4,8 +4,10 @@
 import jetbrains.buildServer.ExecResult;
 import jetbrains.buildServer.SimpleCommandLineProcessRunner;
 import jetbrains.buildServer.agent.BuildProgressLogger;
+import jetbrains.buildServer.util.FileUtil;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Collection;
 
 /**
@@ -21,24 +23,35 @@
     myExePath = new File(homeDir, SYMBOLS_EXE);
   }
 
-  public void dumpGuidsToFile(Collection<File> files, File output, BuildProgressLogger buildLogger){
+  public int dumpGuidsToFile(Collection<File> files, File output, BuildProgressLogger buildLogger) throws IOException {
     final GeneralCommandLine commandLine = new GeneralCommandLine();
     commandLine.setExePath(myExePath.getPath());
     commandLine.addParameter(DUMP_SYMBOL_SIGN_CMD);
-    commandLine.addParameter(String.format("/o=\"%s\"", output.getPath()));
-    for(File file : files){
-      commandLine.addParameter(file.getPath());
-    }
+    commandLine.addParameter(String.format("/o=%s", output.getPath()));
+    commandLine.addParameter(String.format("/i=%s", dumpPathsToFile(files).getPath()));
     buildLogger.message(String.format("Running command %s", commandLine.getCommandLineString()));
     final ExecResult execResult = SimpleCommandLineProcessRunner.runCommand(commandLine, null);
     final String stdout = execResult.getStdout();
     if(!stdout.isEmpty()){
       buildLogger.message("Stdout: " + stdout);
     }
-    if (execResult.getExitCode() == 0) return;
-    buildLogger.warning(String.format("%s ends with non-zero exit code.", SYMBOLS_EXE));
-    buildLogger.warning("Stdout: " + stdout);
-    buildLogger.warning("Stderr: " + execResult.getStderr());
-    buildLogger.exception(execResult.getException());
+    final int exitCode = execResult.getExitCode();
+    if (exitCode != 0) {
+      buildLogger.warning(String.format("%s ends with non-zero exit code.", SYMBOLS_EXE));
+      buildLogger.warning("Stdout: " + stdout);
+      buildLogger.warning("Stderr: " + execResult.getStderr());
+      buildLogger.exception(execResult.getException());
+    }
+    return exitCode;
+  }
+
+  private File dumpPathsToFile(Collection<File> files) throws IOException {
+    final File result = FileUtil.createTempFile(DUMP_SYMBOL_SIGN_CMD, ".input");
+    StringBuilder contentBuilder = new StringBuilder();
+    for(File file : files){
+      contentBuilder.append(file.getPath()).append("\n");
+    }
+    FileUtil.writeToFile(result, contentBuilder.toString().getBytes());
+    return result;
   }
 }
--- a/agent/src/jetbrains/buildServer/symbols/tools/WinDbgToolsHelper.java	Wed Feb 26 17:25:53 2014 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-package jetbrains.buildServer.symbols.tools;
-
-import jetbrains.buildServer.agent.AgentRunningBuild;
-import jetbrains.buildServer.dotNet.DotNetConstants;
-import jetbrains.buildServer.util.CollectionsUtil;
-import jetbrains.buildServer.util.filters.Filter;
-import org.apache.log4j.Logger;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Evgeniy.Koshkin
- */
-public class WinDbgToolsHelper {
-
-  private static final Logger LOG = Logger.getLogger(WinDbgToolsHelper.class);
-
-  private static final String SRCSRV_HOME_DIR_RELATIVE_X64 = "\\Debuggers\\x64\\srcsrv\\";
-  private static final String SRCSRV_HOME_DIR_RELATIVE_X86 = "\\Debuggers\\x86\\srcsrv\\";
-
-  @Nullable
-  public static File getSrcSrvHomeDir(@NotNull AgentRunningBuild build) {
-    final Map<String,String> agentConfigParameters = build.getAgentConfiguration().getConfigurationParameters();
-    final List<String> winSdkPathParams = CollectionsUtil.filterCollection(agentConfigParameters.keySet(), new Filter<String>() {
-      public boolean accept(@NotNull String paramName) {
-        return paramName.startsWith(DotNetConstants.WINDOWS_SDK) && paramName.endsWith(DotNetConstants.PATH);
-      }
-    });
-    if(winSdkPathParams.isEmpty()){
-      LOG.debug("None of Windows SDK versions are mentioned in agent configuration.");
-      return null;
-    }
-
-    for (String paramName : winSdkPathParams){
-      final File winSdkHomeDir = new File(agentConfigParameters.get(paramName));
-      if(!winSdkHomeDir.exists()) {
-        LOG.debug(String.format("Windows SDK home directory mentioned in parameter %s is not exist. Checked path %s.", paramName, winSdkHomeDir.getAbsolutePath()));
-        continue;
-      }
-      File dir = new File(winSdkHomeDir, SRCSRV_HOME_DIR_RELATIVE_X64);
-      if(dir.exists() && dir.isDirectory()) return dir;
-      dir = new File(winSdkHomeDir, SRCSRV_HOME_DIR_RELATIVE_X86);
-      if(dir.exists() && dir.isDirectory()) return dir;
-      LOG.debug("Failed to find Source Server tools home directory under Windows SDK home directory detected on path " + winSdkHomeDir.getAbsolutePath());
-    }
-    LOG.debug("None of detected Windows SDK installations contain Source Server tools.");
-    return null;
-  }
-}
--- a/idea-resolve-helper.iml	Wed Feb 26 17:25:53 2014 +0400
+++ b/idea-resolve-helper.iml	Mon May 16 14:49:19 2016 +0300
@@ -47,5 +47,4 @@
     <orderEntry type="library" name="standard.jar" level="project" />
     <orderEntry type="library" name="TeamCity server runtime" level="project" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
--- a/server-tests/server-tests.iml	Wed Feb 26 17:25:53 2014 +0400
+++ b/server-tests/server-tests.iml	Mon May 16 14:49:19 2016 +0300
@@ -13,6 +13,6 @@
     <orderEntry type="library" name="jmock" level="project" />
     <orderEntry type="library" name="Server-Api" level="project" />
     <orderEntry type="library" name="TeamCity server runtime" level="project" />
+    <orderEntry type="library" scope="TEST" name="spring-test" level="project" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
--- a/server-tests/src/DownloadSymbolsControllerTest.java	Wed Feb 26 17:25:53 2014 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed 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.
- */
-
-import jetbrains.buildServer.controllers.AuthorizationInterceptor;
-import jetbrains.buildServer.controllers.BaseController;
-import jetbrains.buildServer.controllers.BaseControllerTestCase;
-import jetbrains.buildServer.controllers.interceptors.auth.HttpAuthenticationManager;
-import jetbrains.buildServer.serverSide.RunningBuildEx;
-import jetbrains.buildServer.serverSide.auth.Permission;
-import jetbrains.buildServer.serverSide.auth.RoleScope;
-import jetbrains.buildServer.symbols.AuthHelper;
-import jetbrains.buildServer.symbols.DownloadSymbolsController;
-import jetbrains.buildServer.users.SUser;
-import org.apache.commons.httpclient.HttpStatus;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * @author Evgeniy.Koshkin
- */
-public class DownloadSymbolsControllerTest extends BaseControllerTestCase {
-
-  private MetadataStorageMock myBuildMetadataStorage;
-
-  @Override
-  @BeforeMethod
-  public void setUp() throws Exception {
-    myBuildMetadataStorage = new MetadataStorageMock();
-    super.setUp();
-    myFixture.getServerSettings().setGuestLoginAllowed(true);
-  }
-
-  @Override
-  protected BaseController createController() throws IOException {
-    AuthorizationInterceptor authInterceptor = myFixture.getSingletonService(AuthorizationInterceptor.class);
-    AuthHelper authHelper = new AuthHelper(myFixture.getServerSettings(), myFixture.getUserModel(), myFixture.getSingletonService(HttpAuthenticationManager.class));
-    return new DownloadSymbolsController(myServer, myWebManager, authInterceptor,  myFixture.getSecurityContext(), myBuildMetadataStorage, authHelper);
-  }
-
-  @Test
-  public void request_pdb_simple() throws Throwable {
-    myFixture.getServerSettings().setPerProjectPermissionsEnabled(true);
-    SUser user = myFixture.getUserModel().getGuestUser();
-    user.addRole(RoleScope.projectScope(myProject.getProjectId()), getProjectDevRole());
-    assertTrue(user.isPermissionGrantedForProject(myProject.getProjectId(), Permission.VIEW_BUILD_RUNTIME_DATA));
-
-    myRequest.setRequestURI("mock", getRegisterPdbUrl("secur32.pdb", "8EF4E863187C45E78F4632152CC82FEB"));
-    doGet();
-    assertEquals(HttpStatus.SC_OK, myResponse.getStatus());
-  }
-
-  @Test
-  public void request_pdb_two_slashes_in_url() throws Exception {
-    myRequest.setRequestURI("mock", "/app/symbols//index2.txt'");
-    doGet();
-    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
-  }
-
-  @Test
-  public void request_pdb_invalid_url() throws Exception {
-    myRequest.setRequestURI("mock", "/app/symbols/foo");
-    doGet();
-    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
-  }
-
-  @Test
-  public void request_not_existent_pdb() throws Exception {
-    myRequest.setRequestURI("mock", "/app/symbols/fileName/FileId2/fileName");
-    doGet();
-    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
-  }
-
-  @Test
-  public void request_pdb_unauthorized() throws Exception {
-    myFixture.getServerSettings().setGuestLoginAllowed(false);
-    myRequest.setRequestURI("mock", getRegisterPdbUrl("secur32.pdb", "8EF4E863187C45E78F4632152CC82FEB"));
-    doGet();
-    assertEquals(HttpStatus.SC_UNAUTHORIZED, myResponse.getStatus());
-  }
-
-  @Test
-  public void request_pdb_no_permissions_granted() throws Exception {
-    myRequest.setRequestURI("mock", getRegisterPdbUrl("secur32.pdb", "8EF4E863187C45E78F4632152CC82FEB"));
-    doGet();
-    assertEquals(HttpStatus.SC_UNAUTHORIZED, myResponse.getStatus());
-  }
-
-  private String getRegisterPdbUrl(String fileName, String fileSignature) throws IOException {
-    final File artDirectory = createTempDir();
-    new File(artDirectory, "foo").createNewFile();
-    myBuildType.setArtifactPaths(artDirectory.getAbsolutePath());
-    RunningBuildEx build = startBuild();
-    myBuildMetadataStorage.addEntry(build.getBuildId(), fileName, fileSignature);
-    return String.format("/app/symbols/%s/%s/%s", fileName, fileSignature, fileName);
-  }
-}
--- a/server-tests/src/MetadataStorageMock.java	Wed Feb 26 17:25:53 2014 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-import jetbrains.buildServer.serverSide.metadata.BuildMetadataEntry;
-import jetbrains.buildServer.serverSide.metadata.MetadataStorage;
-import jetbrains.buildServer.symbols.BuildSymbolsIndexProvider;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-class MetadataStorageMock implements MetadataStorage {
-
-  private List<BuildMetadataEntry> myEntries = new ArrayList<BuildMetadataEntry>();
-
-  public void addEntry(final long buildId, final String fileName, final String fileSignature) {
-    myEntries.add(new BuildMetadataEntry() {
-      public long getBuildId() {
-        return buildId;
-      }
-
-      @NotNull
-      public String getKey() {
-        return fileSignature;
-      }
-
-      @NotNull
-      public Map<String, String> getMetadata() {
-        HashMap<String, String> map = new HashMap<String, String>();
-        map.put(BuildSymbolsIndexProvider.ARTIFACT_PATH_KEY, "foo");
-        map.put(BuildSymbolsIndexProvider.FILE_NAME_KEY, fileName);
-        return map;
-      }
-    });
-  }
-
-  @NotNull
-  public Iterator<BuildMetadataEntry> getAllEntries(@NotNull String s) {
-    return myEntries.iterator();
-  }
-
-  @NotNull
-  public Iterator<BuildMetadataEntry> getEntriesByKey(@NotNull String s, @NotNull String s2) {
-    return myEntries.iterator();
-  }
-
-  @NotNull
-  public Iterator<BuildMetadataEntry> getBuildEntry(long l, @NotNull String s) {
-    return myEntries.iterator();
-  }
-}
\ No newline at end of file
--- a/server-tests/src/jetbrains/buildServer/symbols/DownloadSymbolsControllerTest.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/server-tests/src/jetbrains/buildServer/symbols/DownloadSymbolsControllerTest.java	Mon May 16 14:49:19 2016 +0300
@@ -1,4 +1,18 @@
-package jetbrains.buildServer.symbols;
+package jetbrains.buildServer.symbols;/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed 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.
+ */
 
 import jetbrains.buildServer.controllers.AuthorizationInterceptor;
 import jetbrains.buildServer.controllers.BaseController;
@@ -45,8 +59,18 @@
     assertTrue(user.isPermissionGrantedForProject(myProject.getProjectId(), Permission.VIEW_BUILD_RUNTIME_DATA));
 
     myRequest.setRequestURI("mock", getRegisterPdbUrl("secur32.pdb", "8EF4E863187C45E78F4632152CC82FEB"));
+
     doGet();
-    assertEquals(HttpStatus.SC_OK, myResponse.getStatus());
+
+    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
+    assertEquals("Symbol file not found", myResponse.getStatusText());
+  }
+
+  @Test
+  public void request_pdb_two_slashes_in_url() throws Exception {
+    myRequest.setRequestURI("mock", "/app/symbols//index2.txt'");
+    doGet();
+    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
   }
 
   @Test
@@ -78,12 +102,39 @@
     assertEquals(HttpStatus.SC_UNAUTHORIZED, myResponse.getStatus());
   }
 
+  @Test
+  public void request_pdb_guid_toLowerCase() throws Exception{
+    myFixture.getServerSettings().setPerProjectPermissionsEnabled(true);
+    SUser user = myFixture.getUserModel().getGuestUser();
+    user.addRole(RoleScope.projectScope(myProject.getProjectId()), getProjectDevRole());
+    assertTrue(user.isPermissionGrantedForProject(myProject.getProjectId(), Permission.VIEW_BUILD_RUNTIME_DATA));
+
+    final File artDirectory = createTempDir();
+    assertTrue(new File(artDirectory, "foo").createNewFile());;
+
+    myBuildType.setArtifactPaths(artDirectory.getAbsolutePath());
+    RunningBuildEx build = startBuild();
+    finishBuild(build, false);
+
+    final String fileSignature = "8EF4E863187C45E78F4632152CC82FEB";
+    final String guid = "8EF4E863187C45E78F4632152CC82FE";
+    final String fileName = "secur32.pdb";
+
+    myBuildMetadataStorage.addEntry(build.getBuildId(), fileName, guid.toLowerCase());
+    myRequest.setRequestURI("mock", String.format("/app/symbols/%s/%s/%s", fileName, fileSignature, fileName));
+
+    doGet();
+
+    assertEquals(HttpStatus.SC_NOT_FOUND, myResponse.getStatus());
+    assertEquals("Symbol file not found", myResponse.getStatusText());
+  }
+
   private String getRegisterPdbUrl(String fileName, String fileSignature) throws IOException {
     final File artDirectory = createTempDir();
     new File(artDirectory, "foo").createNewFile();
     myBuildType.setArtifactPaths(artDirectory.getAbsolutePath());
     RunningBuildEx build = startBuild();
-    myBuildMetadataStorage.addEntry(build.getBuildId(), fileName, fileSignature);
+    myBuildMetadataStorage.addEntry(build.getBuildId(), fileName, fileSignature.substring(0, fileSignature.length() - 1).toLowerCase());
     return String.format("/app/symbols/%s/%s/%s", fileName, fileSignature, fileName);
   }
 }
--- a/server-tests/src/jetbrains/buildServer/symbols/MetadataStorageMock.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/server-tests/src/jetbrains/buildServer/symbols/MetadataStorageMock.java	Mon May 16 14:49:19 2016 +0300
@@ -2,6 +2,9 @@
 
 import jetbrains.buildServer.serverSide.metadata.BuildMetadataEntry;
 import jetbrains.buildServer.serverSide.metadata.MetadataStorage;
+import jetbrains.buildServer.serverSide.metadata.MetadataStorageWriter;
+import jetbrains.buildServer.serverSide.metadata.impl.MetadataStorageException;
+import jetbrains.buildServer.util.Action;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
@@ -36,6 +39,10 @@
     return myEntries.iterator();
   }
 
+  public int getNumberOfEntries(@NotNull String s) {
+    return 0;
+  }
+
   @NotNull
   public Iterator<BuildMetadataEntry> getEntriesByKey(@NotNull String s, @NotNull String s2) {
     return myEntries.iterator();
@@ -45,4 +52,13 @@
   public Iterator<BuildMetadataEntry> getBuildEntry(long l, @NotNull String s) {
     return myEntries.iterator();
   }
+
+  public boolean updateCache(long l, boolean b, @NotNull String s, @NotNull Action<MetadataStorageWriter> action) throws MetadataStorageException {
+    return false;
+  }
+
+  @NotNull
+  public Iterator<BuildMetadataEntry> findEntriesWithValue(@NotNull String s, @NotNull String s1, Collection<String> collection) {
+    return myEntries.iterator();
+  }
 }
\ No newline at end of file
--- a/server/server.iml	Wed Feb 26 17:25:53 2014 +0400
+++ b/server/server.iml	Mon May 16 14:49:19 2016 +0300
@@ -46,5 +46,4 @@
     <orderEntry type="module" module-name="common" />
     <orderEntry type="library" name="TeamCity server runtime" level="project" />
   </component>
-</module>
-
+</module>
\ No newline at end of file
--- a/server/src/jetbrains/buildServer/symbols/AuthHelper.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/server/src/jetbrains/buildServer/symbols/AuthHelper.java	Mon May 16 14:49:19 2016 +0300
@@ -3,10 +3,11 @@
 import jetbrains.buildServer.controllers.interceptors.auth.HttpAuthenticationManager;
 import jetbrains.buildServer.controllers.interceptors.auth.HttpAuthenticationResult;
 import jetbrains.buildServer.serverSide.auth.ServerPrincipal;
-import jetbrains.buildServer.serverSide.impl.ServerSettings;
+import jetbrains.buildServer.serverSide.ServerSettings;
 import jetbrains.buildServer.users.SUser;
 import jetbrains.buildServer.users.UserModel;
 import jetbrains.buildServer.util.Predicate;
+import org.apache.log4j.Logger;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -19,6 +20,8 @@
  */
 public class AuthHelper {
 
+  private static final Logger LOG = Logger.getLogger(AuthHelper.class);
+
   @NotNull private final ServerSettings myServerSettings;
   @NotNull private final UserModel myUserModel;
   @NotNull private final HttpAuthenticationManager myAuthManager;
@@ -36,23 +39,47 @@
                                     @NotNull HttpServletResponse response,
                                     @NotNull Predicate<SUser> hasPermissions) throws IOException {
     if(myServerSettings.isGuestLoginAllowed()) {
+      LOG.debug("Guest access enabled on the server. Trying to check permissions of Guest.");
       final SUser guestUser = myUserModel.getGuestUser();
-      if(hasPermissions.apply(guestUser)) return guestUser;
+      if (hasPermissions.apply(guestUser)) {
+        LOG.debug("Guest user has enough permissions to process request.");
+        return guestUser;
+      }
+      LOG.debug("Guest user has NO permissions to process request. Will try to authenticate incoming request.");
+    } else {
+      LOG.debug("Guest access disabled on the server. Will try to authenticate incoming request.");
     }
-    final HttpAuthenticationResult authResult = myAuthManager.processAuthenticationRequest(request, response);
+    LOG.debug("Trying to authenticate incoming request.");
+    final HttpAuthenticationResult authResult = myAuthManager.processAuthenticationRequest(request, response, false);
     switch (authResult.getType()) {
       case NOT_APPLICABLE:
-        myAuthManager.processUnauthenticatedRequest(request, response);
+        //TODO
+        LOG.debug("NOT_APPLICABLE");
+        myAuthManager.processUnauthenticatedRequest(request, response, "", false);
         return null;
       case UNAUTHENTICATED:
+        //TODO
+        LOG.debug("UNAUTHENTICATED");
         return null;
     }
+    LOG.debug("Incoming request was authenticated successfully.");
     final ServerPrincipal principal = authResult.getPrincipal();
-    final SUser user = myUserModel.findUserAccount(principal.getRealm(), principal.getName());
+    final String realm = principal.getRealm();
+    final String name = principal.getName();
+    final SUser user = myUserModel.findUserAccount(realm, name);
     if(user == null){
+      LOG.warn(String.format("Failed to find user account by realm (%s) and name (%s)", realm, name));
       response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied");
       return null;
     }
-    return hasPermissions.apply(user) ? user : null;
+    LOG.debug(String.format("Found user account (id %s) by realm (%s) and name (%s)", user.getId(), realm, name));
+    final boolean hasAccess = hasPermissions.apply(user);
+    if (hasAccess) {
+      LOG.debug(String.format("Located user (name %s) has enough permissions to process the request.", name));
+      return user;
+    }
+    LOG.warn(String.format("Located user (name %s) has NO permissions to process the request.", name));
+    response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied");
+    return null;
   }
 }
--- a/server/src/jetbrains/buildServer/symbols/BuildSymbolsIndexProvider.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/server/src/jetbrains/buildServer/symbols/BuildSymbolsIndexProvider.java	Mon May 16 14:49:19 2016 +0300
@@ -6,6 +6,8 @@
 import jetbrains.buildServer.serverSide.artifacts.BuildArtifactsViewMode;
 import jetbrains.buildServer.serverSide.metadata.BuildMetadataProvider;
 import jetbrains.buildServer.serverSide.metadata.MetadataStorageWriter;
+import jetbrains.buildServer.util.CollectionsUtil;
+import jetbrains.buildServer.util.filters.Filter;
 import org.apache.log4j.Logger;
 import org.jdom.Document;
 import org.jdom.Element;
@@ -38,52 +40,58 @@
 
   public void generateMedatadata(@NotNull SBuild sBuild, @NotNull MetadataStorageWriter metadataStorageWriter) {
     final long buildId = sBuild.getBuildId();
+
     final BuildArtifact symbols = sBuild.getArtifacts(BuildArtifactsViewMode.VIEW_HIDDEN_ONLY).getArtifact(".teamcity/symbols");
-    if(symbols == null){
+    final BuildArtifact symbolSignaturesSource = symbols == null ? null : CollectionsUtil.findFirst(symbols.getChildren(), new Filter<BuildArtifact>() {
+      public boolean accept(@NotNull BuildArtifact data) {
+        return data.getName().startsWith("symbol-signatures");
+      }
+    });
+    if(symbolSignaturesSource == null) {
       LOG.debug("Build with id " + buildId + " doesn't provide symbols index data.");
       return;
     }
-    for(BuildArtifact childArtifact : symbols.getChildren()){
-      if (!childArtifact.getName().startsWith("symbol-signatures")) continue;
-      Map<String, String> indexData = Collections.emptyMap();
-      try {
-        indexData = readIndex(childArtifact.getInputStream());
-      } catch (IOException e) {
-        LOG.debug("Failed to read symbols index data from artifact " + childArtifact.getRelativePath(), e);
+
+    Map<String, String> indexData = Collections.emptyMap();
+    try {
+      indexData = readIndex(symbolSignaturesSource.getInputStream());
+    } catch (IOException e) {
+      LOG.debug("Failed to read symbols index data from artifact " + symbolSignaturesSource.getRelativePath(), e);
+    } catch (JDOMException e) {
+      LOG.debug("Failed to read symbols index data from artifact " + symbolSignaturesSource.getRelativePath(), e);
+    }
+
+    LOG.debug(String.format("Build with id %d provides %d symbol file signatures.", buildId, indexData.size()));
+
+    for (String signature : indexData.keySet()) {
+      final String fileName = indexData.get(signature);
+      final String artifactPath = locateArtifact(sBuild, fileName);
+      if (artifactPath == null) {
+        LOG.debug(String.format("Failed to find artifact by name %s and build id %d.", fileName, buildId));
+        continue;
       }
-      for (String sign : indexData.keySet()){
-        final String fileName = indexData.get(sign);
-        final String artifactPath = locateArtifact(sBuild, fileName);
-        if(artifactPath == null){
-          LOG.debug(String.format("Failed to find artifact by name. BuildId - %d. Artifact name - %s.", buildId, fileName));
-          continue;
-        }
-        final HashMap<String, String> data = new HashMap<String, String>();
-        data.put(ARTIFACT_PATH_KEY, artifactPath);
-        data.put(FILE_NAME_KEY, fileName);
-        metadataStorageWriter.addParameters(sign, data);
-      }
+      final HashMap<String, String> data = new HashMap<String, String>();
+      data.put(ARTIFACT_PATH_KEY, artifactPath);
+      data.put(FILE_NAME_KEY, fileName);
+      metadataStorageWriter.addParameters(signature, data);
+      LOG.debug("Stored symbol file signature " + signature + " for file name " + fileName + " build id " + buildId);
     }
   }
 
-  private Map<String, String> readIndex(InputStream inputStream) throws IOException {
+  @NotNull
+  private Map<String, String> readIndex(InputStream inputStream) throws JDOMException, IOException {
     SAXBuilder builder = new SAXBuilder();
-    try {
-      Document document = builder.build(inputStream);
-      Map<String, String> result = new HashMap<String, String>();
-      for (Object signElementObject : document.getRootElement().getChildren()){
-        final Element signElement = (Element) signElementObject;
-        result.put(extractGuid(signElement.getAttributeValue("sign")), signElement.getAttributeValue("file"));
-      }
-      return result;
-    } catch (JDOMException e) {
-      LOG.debug(e);
-      return null;
+    Document document = builder.build(inputStream);
+    Map<String, String> result = new HashMap<String, String>();
+    for (Object signElementObject : document.getRootElement().getChildren()){
+      final Element signElement = (Element) signElementObject;
+      result.put(extractGuid(signElement.getAttributeValue("sign")), signElement.getAttributeValue("file"));
     }
+    return result;
   }
 
   private String extractGuid(String sign) {
-    return sign.substring(0, sign.length() - 1); //last symbol is PEDebugType
+    return sign.substring(0, sign.length() - 1).toLowerCase(); //last symbol is PEDebugType
   }
 
   private String locateArtifact(SBuild build, final String fileName) {
--- a/server/src/jetbrains/buildServer/symbols/DownloadSymbolsController.java	Wed Feb 26 17:25:53 2014 +0400
+++ b/server/src/jetbrains/buildServer/symbols/DownloadSymbolsController.java	Mon May 16 14:49:19 2016 +0300
@@ -23,7 +23,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.BufferedOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
 import java.util.Map;
@@ -86,7 +85,7 @@
 
     final String fileName = valuableUriPart.substring(0, firstDelimiterPosition);
     final String signature = valuableUriPart.substring(firstDelimiterPosition + 1, valuableUriPart.indexOf('/', firstDelimiterPosition + 1));
-    final String guid = signature.substring(0, signature.length() - 1); //last symbol is PEDebugType
+    final String guid = signature.substring(0, signature.length() - 1).toLowerCase(); //last symbol is PEDebugType
     LOG.debug(String.format("Symbol file requested. File name: %s. Guid: %s.", fileName, guid));
 
     final String projectId = findRelatedProjectId(guid);
@@ -97,14 +96,7 @@
 
     final SUser user = myAuthHelper.getAuthenticatedUser(request, response, new Predicate<SUser>() {
       public boolean apply(SUser user) {
-        try{
-          boolean hasPermissions = user.isPermissionGrantedForProject(projectId, Permission.VIEW_BUILD_RUNTIME_DATA);
-          if(!hasPermissions) response.sendError(HttpServletResponse.SC_FORBIDDEN, String.format("You have no access to PDB files in the project with id %s.", projectId));
-          return hasPermissions;
-        } catch (IOException e) {
-          LOG.debug(e);
-          return false;
-        }
+        return user.isPermissionGrantedForProject(projectId, Permission.VIEW_BUILD_RUNTIME_DATA);
       }
     });
     if (user == null) return null;
@@ -153,7 +145,7 @@
       LOG.debug(String.format("Metadata stored for guid '%s' is invalid.", guid));
       return null;
     }
-    if(!storedFileName.equals(fileName)){
+    if(!storedFileName.equalsIgnoreCase(fileName)){
       LOG.debug(String.format("File name '%s' stored for guid '%s' differs from requested '%s'.", storedFileName, guid, fileName));
       return null;
     }
Binary file tools/JetSymbols/JetBrains.CommandLine.Symbols.exe has changed
Binary file tools/JetSymbols/JetBrains.Platform.Symbols.Interop.WinApi.dll has changed
Binary file tools/JetSymbols/JetBrains.Platform.Symbols.Metadata.dll has changed
Binary file tools/JetSymbols/JetBrains.Platform.Symbols.Util.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/debug-symbols.xml	Mon May 16 14:49:19 2016 +0300
@@ -0,0 +1,426 @@
+<?xml version='1.0' encoding='ISO-8859-1' ?>
+<!DOCTYPE log4j:configuration SYSTEM "./log4j.dtd">
+
+<log4j:configuration>
+  <appender name="CONSOLE-WARN" class="org.apache.log4j.ConsoleAppender">
+    <param name="target" value="System.err"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+    <filter class="jetbrains.buildServer.util.SpringErrorsFilter">
+      <param name="LevelMin" value="WARN"/>
+    </filter>
+  </appender>
+
+  <appender name="CONSOLE-ERROR" class="org.apache.log4j.ConsoleAppender">
+    <param name="target" value="System.err"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+    <filter class="jetbrains.buildServer.util.SpringErrorsFilter">
+      <param name="LevelMin" value="ERROR"/>
+    </filter>
+  </appender>
+
+  <appender name="ROLL" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-server.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="javasvn.output"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.plugins.spring.SpringPluginLoader$TeamCityPlugin*"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.vcs.impl.VcsContentCache"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.LDAP"/>
+      <param name="MaxDenyLevel" value="DEBUG"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.maintenance.WebDispatcherServlet"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.CLEANUP"/>
+      <param name="MaxDenyLevel" value="DEBUG"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.AUTH"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.nuget.*"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+    <filter class="jetbrains.buildServer.log.CategoryFilter">
+      <param name="DenyCategory" value="jetbrains.buildServer.symbols.*"/>
+      <param name="MaxDenyLevel" value="INFO"/>
+    </filter>
+  </appender>
+
+  <appender name="ROLL.VCS" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-vcs.log"/>
+    <param name="maxBackupIndex" value="3"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%15.15t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="ROOL.VCS.REMOTE.RUN" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-remote-run.log"/>
+    <param name="maxBackupIndex" value="5"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%15.15t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="ROLL.WS" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-ws.log"/>
+    <param name="maxBackupIndex" value="3"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%15.15t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="ACTIVITIES.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-activities.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="CLOUDS.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-clouds.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%15.15t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="SQL.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-sql.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="CLEANUP.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-cleanup.log"/>
+    <param name="maxBackupIndex" value="3"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="SVN.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-svn.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="TFS.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-tfs.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="STARTEAM.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-starteam.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="CLEARCASE.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-clearcase.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="AUTH.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-auth.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%30.30t] - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="SYMBOLS.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-symbolserver.log"/>
+    <param name="maxBackupIndex" value="10"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%30.30t] - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="AGENT_STATISTICS.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-agent-statistics.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="XMLRPC.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-xmlrpc.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="LDAP.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-ldap.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="VCS-CONTENT-CACHE" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}vcs-content-cache.log"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] [%t] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="REST.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-rest.log"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p [%15.15t] - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="FREEMARKER.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-freemarker.log"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="NOTIFICATIONS.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-notifications.log"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="AGENTPUSH.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-agentPush.log"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="NUGET.LOG" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-nuget.log"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <appender name="ROLL.VERSIONED_SETTINGS" class="jetbrains.buildServer.util.TCRollingFileAppender">
+    <param name="file" value="${teamcity_logs}teamcity-versioned-settings.log"/>
+    <param name="maxBackupIndex" value="3"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d] %6p - %30.30c - %m %n"/>
+    </layout>
+  </appender>
+
+  <!-- categories -->
+
+  <category name="jetbrains.buildServer.symbols" additivity="false">
+    <priority value="DEBUG"/>
+    <appender-ref ref="ROLL"/>
+    <appender-ref ref="SYMBOLS.LOG"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.nuget" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="NUGET.LOG"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+    <appender-ref ref="ROLL"/>
+  </category>
+
+  <category name="jetbrains.buildServer.agentpush" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="AGENTPUSH.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.AUTH" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL"/>
+    <appender-ref ref="AUTH.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.buildTriggers.vcs.clearcase" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="CLEARCASE.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.buildTriggers.vcs.starteam" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="STARTEAM.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.buildTriggers.vcs.tfs" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="TFS.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.XMLRPC" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="XMLRPC.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.AGENTSSTATISTICS" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="AGENT_STATISTICS.LOG"/>
+  </category>
+
+  <category name="javasvn.output" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="SVN.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.SQL" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="SQL.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.CLEANUP" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL"/>
+    <appender-ref ref="CLEANUP.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.LDAP" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="LDAP.LOG"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.vcs.impl.VcsContentCache" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="VCS-CONTENT-CACHE"/>
+  </category>
+
+  <category name="jetbrains.buildServer.server.rest" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="REST.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.clouds.jetbrains.buildServer.serverSide.impl.FlushQueueVirtualAction" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="CLOUDS.LOG"/>
+  </category>
+
+  <category name="com.xerox.amazonws" additivity="false">
+    <priority value="ERROR"/>
+    <appender-ref ref="CLOUDS.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.clouds" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="CLOUDS.LOG"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.ACTIVITIES">
+    <priority value="INFO"/>
+    <appender-ref ref="ACTIVITIES.LOG"/>
+  </category>
+
+  <category name="jetbrains.buildServer.VCS" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.VCS"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.buildTriggers.vcs" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.VCS"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.buildTriggers.vcs.remoteRun" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROOL.VCS.REMOTE.RUN"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="jetbrains.buildServer.notification" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="NOTIFICATIONS.LOG"/>
+    <appender-ref ref="CONSOLE-ERROR"/>
+  </category>
+
+  <category name="freemarker.runtime" additivity="false">
+    <priority value="OFF"/>
+    <appender-ref ref="FREEMARKER.LOG"/>
+  </category>
+
+  <category name="org.atmosphere" additivity="false" >
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.WS"/>
+  </category>
+
+  <category name="jetbrains.buildServer.WEBSOCKET" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.WS"/>
+  </category>
+
+  <category name="net.sf.packtag.implementation.yui.JavaScriptErrorReporter">
+    <priority value="OFF"/>
+  </category>
+
+  <category name="jetbrains.buildServer.VERSIONED_SETTINGS" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.VERSIONED_SETTINGS"/>
+  </category>
+
+  <category name="jetbrains.buildServer.serverSide.impl.versionedSettings" additivity="false">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL.VERSIONED_SETTINGS"/>
+  </category>
+
+  <category name="jetbrains.buildServer">
+    <priority value="INFO"/>
+    <appender-ref ref="ROLL"/>
+  </category>
+
+  <root>
+    <priority value="INFO"/>
+    <appender-ref ref="CONSOLE-WARN"/>
+  </root>
+
+</log4j:configuration>