Mercurial > hg > tc-symbol-server
changeset 2:c6ca0a26d93e
initial implementation of agent-side symbol indexer
author | Evgeniy.Koshkin |
---|---|
date | Thu, 18 Jul 2013 15:34:28 +0400 |
parents | 33e8cf5b2d57 |
children | 53028ba390e0 |
files | agent/agent.iml agent/src/META-INF/build-agent-plugin-symbol-server.xml agent/src/jetbrains/buildServer/symbols/SymbolsIndexer.java common/src/jetbrains/buildServer/symbols/SymbolsConstants.java server/server.iml server/src/META-INF/build-server-plugin-symbol-server.xml server/src/jetbrains/buildServer/symbols/IndexSymbolsBuildFeature.java |
diffstat | 7 files changed, 172 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/agent/agent.iml Tue Jul 16 20:17:11 2013 +0400 +++ b/agent/agent.iml Thu Jul 18 15:34:28 2013 +0400 @@ -8,6 +8,7 @@ <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> + <file>file://$MODULE_DIR$/src/META-INF/build-agent-plugin-symbol-server.xml</file> </fileset> </configuration> </facet> @@ -24,6 +25,7 @@ <orderEntry type="library" name="log4j" level="project" /> <orderEntry type="library" name="Idea-OpenApi" level="project" /> <orderEntry type="module" module-name="common" /> + <orderEntry type="library" name="TeamCity agent runtime" level="project" /> </component> </module>
--- a/agent/src/META-INF/build-agent-plugin-symbol-server.xml Tue Jul 16 20:17:11 2013 +0400 +++ b/agent/src/META-INF/build-agent-plugin-symbol-server.xml Thu Jul 18 15:34:28 2013 +0400 @@ -6,12 +6,6 @@ default-autowire="constructor" > - <!-- declare all beans you like Spring Dependency Injection to create --> - <!-- see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html --> - - <!-- sample: - <bean class="bean class fully qualified name"/> - --> - + <bean class="jetbrains.buildServer.symbols.SymbolsIndexer"/> </beans> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/jetbrains/buildServer/symbols/SymbolsIndexer.java Thu Jul 18 15:34:28 2013 +0400 @@ -0,0 +1,130 @@ +package jetbrains.buildServer.symbols; + +import com.intellij.execution.configurations.GeneralCommandLine; +import jetbrains.buildServer.ExecResult; +import jetbrains.buildServer.SimpleCommandLineProcessRunner; +import jetbrains.buildServer.agent.AgentLifeCycleAdapter; +import jetbrains.buildServer.agent.AgentLifeCycleListener; +import jetbrains.buildServer.agent.AgentRunningBuild; +import jetbrains.buildServer.agent.BuildFinishedStatus; +import jetbrains.buildServer.agent.artifacts.ArtifactsWatcher; +import jetbrains.buildServer.agent.impl.artifacts.ArtifactsBuilderAdapter; +import jetbrains.buildServer.agent.impl.artifacts.ArtifactsCollection; +import jetbrains.buildServer.agent.plugins.beans.PluginDescriptor; +import jetbrains.buildServer.util.EventDispatcher; +import jetbrains.buildServer.util.FileUtil; +import org.apache.log4j.Logger; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +/** + * @author Evgeniy.Koshkin + */ +public class SymbolsIndexer extends ArtifactsBuilderAdapter { + + public static final Logger LOG = Logger.getLogger(SymbolsIndexer.class); + + public static final String PDB_FILE_EXTENSION = "pdb"; + public static final String EXE_FILE_EXTENSION = "exe"; + public static final String DLL_FILE_EXTENSION = "dll"; + + public static final String SYMBOLS_EXE = "symbols.exe"; + public static final String DUMP_SYMBOL_SIGN_CMD = "dumpSymbolSign"; + public static final String DUMP_BIN_SIGN_CMD = "dumpBinSign"; + + @NotNull private final ArtifactsWatcher myArtifactsWatcher; + @NotNull private final File myNativeToolPath; + @Nullable private AgentRunningBuild myBuild; + @Nullable private Collection<File> myBinariesToProcess; + @Nullable private Collection<File> mySymbolsToProcess; + + public SymbolsIndexer(@NotNull final PluginDescriptor pluginDescriptor, @NotNull final EventDispatcher<AgentLifeCycleListener> agentDispatcher, @NotNull final ArtifactsWatcher artifactsWatcher) { + myNativeToolPath = new File(new File(pluginDescriptor.getPluginRoot(), "bin"), SYMBOLS_EXE); + myArtifactsWatcher = artifactsWatcher; + agentDispatcher.addListener(new AgentLifeCycleAdapter() { + @Override + public void buildStarted(@NotNull final AgentRunningBuild runningBuild) { + myBuild = runningBuild; + myBinariesToProcess = new HashSet<File>(); + mySymbolsToProcess = new HashSet<File>(); + } + + @Override + public void beforeBuildFinish(@NotNull AgentRunningBuild build, @NotNull BuildFinishedStatus buildStatus) { + super.beforeBuildFinish(build, buildStatus); + if (myBuild == null || mySymbolsToProcess == null || myBinariesToProcess == null) return; + if (mySymbolsToProcess.isEmpty()) { + LOG.debug("Symbols weren't found in artifacts to be published."); + } else { + final File targetDir = myBuild.getBuildTempDirectory(); + try { + final File symbolSignaturesFile = dumpSymbolSignatures(mySymbolsToProcess, targetDir); + myArtifactsWatcher.addNewArtifactsPath(symbolSignaturesFile + "=>" + ".teamcity/symbols/symbol-signatures.xml"); + final File binariesSignaturesFile = dumpBinarySignatures(myBinariesToProcess, targetDir); + myArtifactsWatcher.addNewArtifactsPath(binariesSignaturesFile + "=>" + ".teamcity/symbols/binary-signatures.xml"); + } catch (IOException e) { + LOG.error("Error while dumping symbols/binaries signatures.", e); + } + } + mySymbolsToProcess = null; + myBinariesToProcess = null; + myBuild = null; + } + }); + } + + @Override + public void afterCollectingFiles(@NotNull List<ArtifactsCollection> artifacts) { + super.afterCollectingFiles(artifacts); + if(myBuild == null || mySymbolsToProcess == null || myBinariesToProcess == null) return; + if(myBuild.getBuildFeaturesOfType(SymbolsConstants.BUILD_FEATURE_TYPE).isEmpty()){ + LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature disabled. No indexing performed."); + return; + } + LOG.debug(SymbolsConstants.BUILD_FEATURE_TYPE + " build feature enabled. Searching for symbol files."); + mySymbolsToProcess.addAll(getArtifactPathsByFileExtension(artifacts, PDB_FILE_EXTENSION)); + myBinariesToProcess.addAll(getArtifactPathsByFileExtension(artifacts, EXE_FILE_EXTENSION)); + myBinariesToProcess.addAll(getArtifactPathsByFileExtension(artifacts, DLL_FILE_EXTENSION)); + } + + private Collection<File> getArtifactPathsByFileExtension(List<ArtifactsCollection> artifactsCollections, String fileExtension){ + final Collection<File> result = new HashSet<File>(); + for(ArtifactsCollection artifactsCollection : artifactsCollections){ + if(artifactsCollection.isEmpty()) continue; + for (File artifact : artifactsCollection.getFilePathMap().keySet()){ + if(FileUtil.getExtension(artifact.getPath()).equalsIgnoreCase(fileExtension)) + result.add(artifact); + } + } + return result; + } + + private File dumpSymbolSignatures(Collection<File> files, File targetDir) throws IOException { + final File tempFile = FileUtil.createTempFile(targetDir, "symbol-signatures-", ".xml", false); + runTool(DUMP_SYMBOL_SIGN_CMD, files, tempFile); + return tempFile; + } + + private File dumpBinarySignatures(Collection<File> files, File targetDir) throws IOException { + final File tempFile = FileUtil.createTempFile(targetDir, "binary-signatures-", ".xml", false); + runTool(DUMP_BIN_SIGN_CMD, files, tempFile); + return tempFile; + } + + private void runTool(String cmd, Collection<File> files, File output){ + final GeneralCommandLine commandLine = new GeneralCommandLine(); + commandLine.setExePath(myNativeToolPath.getPath()); + commandLine.addParameter(cmd); + commandLine.addParameter(String.format("/o=\"%s\"", output.getPath())); + for(File file : files){ + commandLine.addParameter(file.getPath()); + } + final ExecResult execResult = SimpleCommandLineProcessRunner.runCommand(commandLine, null); + if (execResult.getExitCode() == 0) return; + LOG.warn(String.format("%s ends with non-zero exit code.", SYMBOLS_EXE)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/src/jetbrains/buildServer/symbols/SymbolsConstants.java Thu Jul 18 15:34:28 2013 +0400 @@ -0,0 +1,8 @@ +package jetbrains.buildServer.symbols; + +/** + * @author Evgeniy.Koshkin + */ +public class SymbolsConstants { + public static final String BUILD_FEATURE_TYPE = "symbol-indexer"; +}
--- a/server/server.iml Tue Jul 16 20:17:11 2013 +0400 +++ b/server/server.iml Thu Jul 18 15:34:28 2013 +0400 @@ -18,6 +18,7 @@ <file>jar://$TeamCityDistribution$/buildAgent/lib/common-impl.jar!/META-INF/per-plugin-shared-spring.xml</file> <file>jar://$TeamCityDistribution$/buildAgent/lib/common-impl.jar!/META-INF/plugin-model-shared-spring.xml</file> <file>jar://$TeamCityDistribution$/buildAgent/lib/common-impl.jar!/META-INF/shared-spring-sub-container.xml</file> + <file>file://$MODULE_DIR$/src/META-INF/build-server-plugin-symbol-server.xml</file> </fileset> </configuration> </facet>
--- a/server/src/META-INF/build-server-plugin-symbol-server.xml Tue Jul 16 20:17:11 2013 +0400 +++ b/server/src/META-INF/build-server-plugin-symbol-server.xml Thu Jul 18 15:34:28 2013 +0400 @@ -5,11 +5,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-autowire="constructor" > - <!-- declare all beans you like Spring Dependency Injection to create --> - <!-- see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html --> - <!-- sample: - <bean class="bean class fully qualified name"/> - --> + <bean class="jetbrains.buildServer.symbols.IndexSymbolsBuildFeature"/> </beans>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/jetbrains/buildServer/symbols/IndexSymbolsBuildFeature.java Thu Jul 18 15:34:28 2013 +0400 @@ -0,0 +1,29 @@ +package jetbrains.buildServer.symbols; + +import jetbrains.buildServer.serverSide.BuildFeature; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Evgeniy.Koshkin + */ +public class IndexSymbolsBuildFeature extends BuildFeature { + + @NotNull + @Override + public String getType() { + return SymbolsConstants.BUILD_FEATURE_TYPE; + } + + @NotNull + @Override + public String getDisplayName() { + return "Symbol files (.pdb) indexer"; + } + + @Nullable + @Override + public String getEditParametersUrl() { + return null; + } +}