diff options
Diffstat (limited to 'systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java')
-rw-r--r-- | systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java | 230 |
1 files changed, 168 insertions, 62 deletions
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java index c096d6f6a1..d2ab9fc06f 100644 --- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java +++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/structures/ProbeParser.java @@ -12,6 +12,9 @@ package org.eclipse.linuxtools.internal.systemtap.ui.ide.structures; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; import java.util.StringTokenizer; import java.util.regex.Matcher; @@ -36,6 +39,7 @@ public final class ProbeParser extends TreeTapsetParser { public static final String PROBE_REGEX = "(?s)(?<!\\w)probe\\s+{0}\\s*\\+?="; //$NON-NLS-1$ private static final String TAPSET_PROBE_REGEX = "probe {0} \\+?="; //$NON-NLS-1$ + private static final Pattern PROBE_GROUP_PATTERN = Pattern.compile("[^\\.\\( ]+"); //$NON-NLS-1$ private static ProbeParser parser = null; public static ProbeParser getInstance(){ @@ -47,7 +51,7 @@ public final class ProbeParser extends TreeTapsetParser { } private ProbeParser() { - super("Probe Parser"); //$NON-NLS-1$ + super(Messages.ProbeParser_name); } /** @@ -67,33 +71,34 @@ public final class ProbeParser extends TreeTapsetParser { * Root->Named Groups->ProbePoints->Variables */ @Override - protected IStatus runAction(IProgressMonitor monitor) { - addStaticProbes(monitor); - addProbeAliases(monitor, tree.getChildAt(0)); - return super.runAction(monitor); + protected int runAction(IProgressMonitor monitor) { + int result = addStaticProbes(monitor); + if (result == IStatus.OK) { + result = addProbeAliases(monitor); + } + return result; } /** * Runs stap to obtain a log of all static probes, and populate the probe tree with them. - * - * @return <code>false</code> if a cancelation prevented all probes from being added; - * <code>true</code> otherwise. + * @return An {@link IStatus} severity level for the result of the operation. */ - private boolean addStaticProbes(IProgressMonitor monitor) { + private int addStaticProbes(IProgressMonitor monitor) { TreeNode statics = new TreeNode(Messages.ProbeParser_staticProbes, false); tree.add(statics); if (monitor.isCanceled()) { - return false; + return IStatus.CANCEL; } String probeDump = runStap(new String[]{"--dump-probe-types"}, null, false); //$NON-NLS-1$ - if (probeDump == null) { - return false; + int result = verifyRunResult(probeDump); + if (result != IStatus.OK) { + return result; } boolean canceled = false; try (Scanner st = new Scanner(probeDump)) { - TreeNode group = null; + TreeNode groupNode = null; while (st.hasNextLine()) { if (monitor.isCanceled()) { canceled = true; @@ -101,36 +106,39 @@ public final class ProbeParser extends TreeTapsetParser { } String tokenString = st.nextLine(); String probeName = (new StringTokenizer(tokenString)).nextToken(); - group = addOrFindProbeGroup(extractProbeGroupName(probeName), group, statics); - group.add(makeStaticProbeNode(probeName)); + groupNode = addOrFindProbeGroup(extractProbeGroupName(probeName), groupNode, statics); + groupNode.add(makeStaticProbeNode(probeName)); } } statics.sortTree(); - return !canceled; + return !canceled ? IStatus.OK : IStatus.CANCEL; } /** * Runs stap to obtain a log of all probe aliases & their variables, * and populate the probe tree with them. - * - * @return <code>false</code> if a cancelation prevented all probes from being added; - * <code>true</code> otherwise. + * @return An {@link IStatus} severity level for the result of the operation. */ - private boolean addProbeAliases(IProgressMonitor monitor, TreeNode statics) { + private int addProbeAliases(IProgressMonitor monitor) { + TreeNode statics = tree.getChildByName(Messages.ProbeParser_staticProbes); + if (statics == null) { + return IStatus.ERROR; + } TreeNode aliases = new TreeNode(Messages.ProbeParser_aliasProbes, false); tree.add(aliases); - if (statics == null || monitor.isCanceled()) { - return false; + if (monitor.isCanceled()) { + return IStatus.CANCEL; } String probeDump = runStap(new String[]{"-L"}, "**", false); //$NON-NLS-1$ //$NON-NLS-2$ - if (probeDump == null) { - return false; + int result = verifyRunResult(probeDump); + if (result != IStatus.OK) { + return result; } boolean canceled = false; try (Scanner st = new Scanner(probeDump)) { - TreeNode group = null; + TreeNode groupNode = null; while (st.hasNextLine()) { if (monitor.isCanceled()) { canceled = false; @@ -142,35 +150,56 @@ public final class ProbeParser extends TreeTapsetParser { if (tokenString.startsWith("_")) { //$NON-NLS-1$ continue; } - - StringTokenizer probeTokenizer = new StringTokenizer(tokenString); - String probeName = probeTokenizer.nextToken(); - - String groupName = extractProbeGroupName(tokenString); // Only add this group if it is not a static probe group - if (statics.getChildByName(groupName) == null) { - TreeNode probeNode = makeProbeAliasNode(probeName); - group = addOrFindProbeGroup(groupName, group, aliases); - group.add(probeNode); - addAllVarNodesToProbeNode(probeTokenizer, probeNode); + String groupName = extractProbeGroupName(tokenString); + if (statics.getChildByName(groupName) != null) { + continue; } + groupNode = addSingleProbeAlias(tokenString, aliases, groupNode, groupName, null); } } aliases.sortTree(); - return !canceled; + return !canceled ? IStatus.OK : IStatus.CANCEL; + } + + /** + * Adds a single probe alias to the collection. + * @param probeLine A line of probe information printed by a call to "stap -L". + * @param aliases The tree of probe aliases. The probe will be added to this tree. + * @param groupNode For optimization, pass an existing group node here, as it will be used if the + * probe belongs in it. Otherwise, or if <code>null</code> is passed, a new one will be created. + * @param groupName The name of the probe group, or <code>null</code> if it is unknown at the time + * this method is called. + * @param definition The path of the file in which this probe is defined, or <code>null</code> if it + * is unknown at the time this method is called. + */ + private TreeNode addSingleProbeAlias(String probeLine, TreeNode aliases, TreeNode groupNode, + String groupName, String definition) { + StringTokenizer probeTokenizer = new StringTokenizer(probeLine); + String probeName = probeTokenizer.nextToken(); + + TreeNode probeNode = makeProbeAliasNode(probeName, + definition == null ? findDefinitionOf(probeName) : definition); + + groupNode = addOrFindProbeGroup( + groupName == null ? extractProbeGroupName(probeName) : groupName, + groupNode, aliases); + + groupNode.add(probeNode); + addAllVarNodesToProbeNode(probeTokenizer, probeNode); + return groupNode; } /** - * Find the appropriate parent group node for a probe alias to group probes by name. + * Finds the appropriate parent group node for a probe alias to group probes by name. * If it doesn't yet exist, create it and add it to the view's tree. - * @param probeLine The name of the probe group. + * @param groupName The name of the probe group. * @param groupNode For optimization, pass an existing group node here, as it will be * used if the probe belongs in it. Otherwise, or if <code>null</code> is passed, a new one will be created. * @param category The parent tree node in which to put the group node. * @return The found or created group node that will be the parent of the probe's entry item in the view. */ private TreeNode addOrFindProbeGroup(String groupName, TreeNode groupNode, TreeNode category) { - // If the current probe belongs to a group other than // the most recent group. This should rarely be needed because the // probe list is sorted... mostly. @@ -190,50 +219,38 @@ public final class ProbeParser extends TreeTapsetParser { * @return the name of the group a probe belongs to, based on the probe's name. */ private String extractProbeGroupName(String probeName) { - int dotIndex = probeName.indexOf('.'); - int parenIndex = probeName.indexOf('('); - if (dotIndex > 0 && parenIndex > 0) { - return probeName.substring(0, Math.min(dotIndex, parenIndex)); - } - if (dotIndex > 0) { - return probeName.substring(0, dotIndex); - } - if (parenIndex > 0) { - return probeName.substring(0, parenIndex); - } - return probeName; + Matcher m = PROBE_GROUP_PATTERN.matcher(probeName); + return m.find() ? m.group() : probeName; } private TreeNode makeStaticProbeNode(String probeName) { return new TreeNode(new ProbeNodeData(probeName), probeName, true); } - private TreeNode makeProbeAliasNode(String probeName) { - return new TreeDefinitionNode(new ProbeNodeData(probeName), probeName, findDefinitionOf(probeName), true); + private TreeNode makeProbeAliasNode(String probeName, String definition) { + return new TreeDefinitionNode(new ProbeNodeData(probeName), probeName, definition, true); } /** - * Search the tapset content dump for the path of the file which defines the provided probe alias. + * Searches the tapset content dump for the path of the file which defines the provided probe alias. * @param probeName The alias of the probe to find the definition file of. * @return The path of the probe's definition file, or <code>null</code> if a definition * file can't be found (which is the case for static probes). */ private String findDefinitionOf(String probeName) { - SharedParser sparser = SharedParser.getInstance(); - String tapsetContents = sparser.getTapsetContents(); + String tapsetContents = SharedParser.getInstance().getTapsetContents(); if (tapsetContents == null) { return null; } - Matcher probeMatcher = Pattern.compile(MessageFormat.format(TAPSET_PROBE_REGEX, Pattern.quote(probeName))).matcher(tapsetContents); + Matcher probeMatcher = Pattern.compile(MessageFormat.format( + TAPSET_PROBE_REGEX, Pattern.quote(probeName))).matcher(tapsetContents); if (!probeMatcher.find()) { return null; } - int fileLocIndex = tapsetContents.substring(0, probeMatcher.start()).lastIndexOf(SharedParser.TAG_FILE); + int fileLocIndex = tapsetContents.substring(0, probeMatcher.start()) + .lastIndexOf(SharedParser.TAG_FILE); try (Scanner scanner = new Scanner(tapsetContents.substring(fileLocIndex))) { - Matcher fileMatcher = sparser.filePattern.matcher(scanner.nextLine()); - return fileMatcher.matches() - ? fileMatcher.group(1) - : null; + return SharedParser.findFileNameInTag(scanner.nextLine()); } } @@ -264,10 +281,99 @@ public final class ProbeParser extends TreeTapsetParser { prev.setLength(prev.length() - 1); // Remove the trailing space. addVarNodeToProbeNode(prev.toString(), probeNode); } + probeNode.sortLevel(); } private void addVarNodeToProbeNode(String info, TreeNode probeNode) { probeNode.add(new TreeNode(new ProbevarNodeData(info), info, false)); } + @Override + protected int delTapsets(String[] tapsets, IProgressMonitor monitor) { + TreeNode aliases = tree.getChildByName(Messages.ProbeParser_aliasProbes); + + // Search through alias groups for probes whose definition files + // come from removed directories, and remove them from the group. + for (int i = 0; i < tapsets.length; i++) { + for (int g = 0, gn = aliases.getChildCount(); g < gn; g++) { + if (monitor.isCanceled()) { + return IStatus.CANCEL; + } + TreeNode group = aliases.getChildAt(g); + for (int p = 0, pn = group.getChildCount(); p < pn; p++) { + String definition = ((TreeDefinitionNode) group.getChildAt(p)).getDefinition(); + if (definition != null && definition.startsWith(tapsets[i])) { + group.remove(p--); + pn--; + } + } + // If removing the only probe left in a probe group, remove the group. + if (group.getChildCount() == 0) { + aliases.remove(g--); + gn--; + } + } + } + return IStatus.OK; + } + + @Override + protected int addTapsets(String[] additions, IProgressMonitor monitor) { + String tapsetContents = SharedParser.getInstance().getTapsetContents(); + boolean canceled = false; + TreeNode aliases = tree.getChildByName(Messages.ProbeParser_aliasProbes); + Map<String, ArrayList<String>> fileToItemMap = new HashMap<>(); + + // Search tapset contents for all files provided by each added directory. + for (int i = 0; i < additions.length; i++) { + int firstTagIndex = 0; + while (true) { + // Get the contents of each file provided by the directory additions[i]. + firstTagIndex = tapsetContents.indexOf( + SharedParser.makeFileTag(additions[i]), firstTagIndex); + if (firstTagIndex == -1) { + break; + } + int nextTagIndex = tapsetContents.indexOf(SharedParser.TAG_FILE, firstTagIndex + 1); + String fileContents = nextTagIndex != -1 + ? tapsetContents.substring(firstTagIndex, nextTagIndex) + : tapsetContents.substring(firstTagIndex); + + String filename; + try (Scanner st = new Scanner(fileContents)) { + filename = SharedParser.findFileNameInTag(st.nextLine()); + } + + // Search file contents for the probes the file provides. + ArrayList<String> newItems = new ArrayList<>(); + Matcher matcher = Pattern.compile(MessageFormat.format( + TAPSET_PROBE_REGEX, "(\\S+)")) //$NON-NLS-1$ + .matcher(fileContents); + while (matcher.find()) { + newItems.add(matcher.group(1)); + } + if (!newItems.isEmpty()) { + fileToItemMap.put(filename, newItems); + } + // Remove the contents of the file that was just examined from the total contents. + tapsetContents = tapsetContents.substring(0, firstTagIndex).concat( + tapsetContents.substring(firstTagIndex + fileContents.length())); + } + } + // Run stap on each discovered probe to obtain their variable information. + for (String file : fileToItemMap.keySet()) { + for (String newitem : fileToItemMap.get(file)) { + if (canceled || monitor.isCanceled()) { + canceled = true; + break; + } + addSingleProbeAlias(runStap(new String[]{"-L"}, newitem, false), //$NON-NLS-1$ + aliases, null, null, file); + } + } + + aliases.sortTree(); + return !canceled ? IStatus.OK : IStatus.CANCEL; + } + } |