Skip to content

Commit 1c6c571

Browse files
committed
xml.config: Delete supplementary files when deleting xml analysis config
Fixes #267 [Fixed] Delete supplementary files when deleting xml analysis config Signed-off-by: Bernd Hufmann <[email protected]>
1 parent 2f4bb18 commit 1c6c571

File tree

5 files changed

+332
-3
lines changed

5 files changed

+332
-3
lines changed

tmf/org.eclipse.tracecompass.tmf.analysis.xml.core.tests/plugin.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,14 @@
1616
class="org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs.XmlSchemaParserStub">
1717
</schemaParser>
1818
</extension>
19-
19+
<!-- Define tracing nature here to be able to use it in tests -->
20+
<extension
21+
id="org.eclipse.linuxtools.tmf.project.nature"
22+
point="org.eclipse.core.resources.natures">
23+
<runtime>
24+
<run
25+
class="org.eclipse.tracecompass.tmf.core.TmfProjectNature">
26+
</run>
27+
</runtime>
28+
</extension>
2029
</plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Ericsson
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License 2.0 which
6+
* accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
12+
package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.module;
13+
14+
import static org.junit.Assert.assertFalse;
15+
import static org.junit.Assert.assertNotNull;
16+
import static org.junit.Assert.assertTrue;
17+
import static org.junit.Assert.fail;
18+
19+
import org.eclipse.core.resources.IFolder;
20+
import org.eclipse.core.resources.IProject;
21+
import org.eclipse.core.resources.IProjectDescription;
22+
import org.eclipse.core.resources.IResource;
23+
import org.eclipse.core.resources.IWorkspaceRoot;
24+
import org.eclipse.core.resources.ResourcesPlugin;
25+
import org.eclipse.core.runtime.CoreException;
26+
import org.eclipse.core.runtime.IPath;
27+
import org.eclipse.core.runtime.IStatus;
28+
import org.eclipse.core.runtime.Path;
29+
import org.eclipse.jdt.annotation.NonNull;
30+
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource;
31+
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
32+
import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.Activator;
33+
import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common.TmfXmlTestFiles;
34+
import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
35+
import org.eclipse.tracecompass.tmf.core.TmfProjectNature;
36+
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
37+
import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
38+
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
39+
import org.eclipse.tracecompass.tmf.core.io.ResourceUtil;
40+
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
41+
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
42+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
43+
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
44+
import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStubNs;
45+
import org.junit.After;
46+
import org.junit.AfterClass;
47+
import org.junit.Before;
48+
import org.junit.BeforeClass;
49+
import org.junit.Test;
50+
51+
import com.google.common.collect.ImmutableList;
52+
53+
/**
54+
* Test the XML Utils delete supplementary directory
55+
*
56+
* @author Geneviève Bastien
57+
*/
58+
public class XmlUtilsWithTraceTest {
59+
60+
private static final @NonNull String TEST_TRACE_NAME = "testTrace4.xml";
61+
62+
private static final @NonNull String TEST_TRACE = "test_traces/" + TEST_TRACE_NAME;
63+
64+
private static final @NonNull String ANALYSIS_ID = "xml.core.tests.simple.pattern";
65+
66+
private static IProject sfProject;
67+
68+
/**
69+
* Class setup
70+
*
71+
* @throws CoreException
72+
* if an error occurs
73+
*/
74+
@BeforeClass
75+
public static void startUp() throws CoreException {
76+
IProject project = ResourcesPlugin.getWorkspace().getRoot()
77+
.getProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME);
78+
if (!project.exists()) {
79+
project.create(null);
80+
if (!project.isOpen()) {
81+
project.open(null);
82+
}
83+
IProjectDescription description = project.getDescription();
84+
description.setNatureIds(new String[] { TmfProjectNature.ID });
85+
project.setDescription(description, null);
86+
}
87+
if (!project.isOpen()) {
88+
project.open(null);
89+
}
90+
91+
IFolder tracesFolder = project.getFolder("Traces"); //$NON-NLS-1$
92+
if (!tracesFolder.exists()) {
93+
tracesFolder.create(true, true, null);
94+
}
95+
96+
IFolder supplRootFolder = project.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
97+
if (!supplRootFolder.exists()) {
98+
supplRootFolder.create(true, true, null);
99+
}
100+
sfProject = project;
101+
}
102+
103+
/**
104+
* Class tear down
105+
*
106+
* @throws CoreException
107+
* if an error occurs
108+
*/
109+
@AfterClass
110+
public static void tearDown() throws CoreException {
111+
if (sfProject != null) {
112+
sfProject.delete(true, null);
113+
}
114+
}
115+
116+
/**
117+
* Load the XML files for the current test
118+
*/
119+
@Before
120+
public void setUp() {
121+
XmlUtils.addXmlFile(TmfXmlTestFiles.VALID_PATTERN_SIMPLE_FILE.getFile());
122+
XmlAnalysisModuleSource.notifyModuleChange();
123+
}
124+
125+
/**
126+
* Clean
127+
*/
128+
@After
129+
public void cleanUp() {
130+
XmlUtils.deleteFiles(ImmutableList.of(
131+
TmfXmlTestFiles.VALID_PATTERN_SIMPLE_FILE.getFile().getName()));
132+
XmlAnalysisModuleSource.notifyModuleChange();
133+
}
134+
135+
private ITmfTrace getTrace() throws CoreException {
136+
TmfXmlTraceStubNs trace = new TmfXmlTraceStubNs();
137+
String absolutePath = Activator.getAbsolutePath(new Path(TEST_TRACE)).toOSString();
138+
IStatus status = trace.validate(null, absolutePath);
139+
if (!status.isOK()) {
140+
fail(status.getException().getMessage());
141+
}
142+
143+
IResource resource = createResource(absolutePath);
144+
try {
145+
trace.initTrace(resource, absolutePath, TmfEvent.class);
146+
} catch (TmfTraceException e) {
147+
trace.dispose();
148+
fail(e.getMessage());
149+
}
150+
151+
// Initialize the trace and module
152+
TmfTraceOpenedSignal signal = new TmfTraceOpenedSignal(this, trace, null);
153+
trace.traceOpened(signal);
154+
// The data provider manager uses opened traces from the manager
155+
TmfTraceManager.getInstance().traceOpened(signal);
156+
return trace;
157+
}
158+
159+
@SuppressWarnings("null")
160+
private static IResource createResource(String path) throws CoreException {
161+
IPath targetLocation = new Path(path);
162+
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
163+
IProject project = root.getProject(TmfCommonConstants.DEFAULT_TRACE_PROJECT_NAME);
164+
project.refreshLocal(IResource.DEPTH_INFINITE, null);
165+
IFolder tracesFolder = project.getFolder("Traces");
166+
IResource resource = tracesFolder.getFile(TEST_TRACE_NAME);
167+
ResourceUtil.createSymbolicLink(resource, targetLocation, true, null);
168+
169+
IFolder supplRootFolder = project.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
170+
IFolder supplFolder = supplRootFolder.getFolder(resource.getProjectRelativePath().removeFirstSegments(1));
171+
if (!supplFolder.exists()) {
172+
supplFolder.create(true, true, null);
173+
}
174+
resource.setPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, supplFolder.getLocation().toOSString());
175+
176+
return resource;
177+
}
178+
179+
private static void runModule(ITmfTrace trace) {
180+
IAnalysisModule module = trace.getAnalysisModule(ANALYSIS_ID);
181+
assertNotNull(module);
182+
module.schedule();
183+
assertTrue(module.waitForCompletion());
184+
}
185+
186+
/**
187+
* Test delete supplementary dir when trace is open
188+
*
189+
* @throws CoreException
190+
* if an error occurs
191+
*/
192+
@Test
193+
public void testDeleteSupplDirWithTraceOpen() throws CoreException {
194+
ITmfTrace trace = getTrace();
195+
assertNotNull(trace);
196+
try {
197+
runModule(trace);
198+
String supplPathString = TmfTraceManager.getSupplementaryFileDir(trace);
199+
IPath path = new Path(supplPathString);
200+
IPath ssFile = path.addTrailingSeparator().append(ANALYSIS_ID).addFileExtension("ht");
201+
IPath segFile = path.addTrailingSeparator().append(ANALYSIS_ID).addFileExtension("dat");
202+
assertTrue(ssFile.toFile().exists());
203+
assertTrue(segFile.toFile().exists());
204+
XmlUtils.deleteSupplementaryResources(TmfXmlTestFiles.VALID_PATTERN_SIMPLE_FILE.getFile().getName(), null);
205+
assertFalse(ssFile.toFile().exists());
206+
assertFalse(segFile.toFile().exists());
207+
} finally {
208+
trace.dispose();
209+
TmfTraceManager.getInstance().traceClosed(new TmfTraceClosedSignal(this, trace));
210+
}
211+
}
212+
213+
/**
214+
* Test delete supplementary dir when trace is open
215+
*
216+
* @throws CoreException
217+
* Exception thrown by analyses
218+
*/
219+
@Test
220+
public void testDeleteSupplDirWithTraceClosed() throws CoreException {
221+
ITmfTrace trace = getTrace();
222+
assertNotNull(trace);
223+
try {
224+
runModule(trace);
225+
String supplPathString = TmfTraceManager.getSupplementaryFileDir(trace);
226+
IPath path = new Path(supplPathString);
227+
IPath ssFile = path.addTrailingSeparator().append(ANALYSIS_ID).addFileExtension("ht");
228+
IPath segFile = path.addTrailingSeparator().append(ANALYSIS_ID).addFileExtension("dat");
229+
assertTrue(ssFile.toFile().exists());
230+
assertTrue(segFile.toFile().exists());
231+
232+
TmfTraceClosedSignal signal = new TmfTraceClosedSignal(this, trace);
233+
TmfTraceManager.getInstance().traceClosed(signal);
234+
trace.dispose();
235+
236+
XmlUtils.deleteSupplementaryResources(TmfXmlTestFiles.VALID_PATTERN_SIMPLE_FILE.getFile().getName(), null);
237+
assertFalse(ssFile.toFile().exists());
238+
assertFalse(segFile.toFile().exists());
239+
} finally {
240+
trace.dispose();
241+
TmfTraceManager.getInstance().traceClosed(new TmfTraceClosedSignal(this, trace));
242+
}
243+
}
244+
245+
}

tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Require-Bundle: org.eclipse.core.runtime,
1717
org.eclipse.tracecompass.analysis.profiling.core,
1818
org.eclipse.core.commands,
1919
com.google.guava,
20-
org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional
20+
org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional,
21+
org.eclipse.core.resources
2122
Export-Package: org.eclipse.tracecompass.internal.tmf.analysis.xml.core;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests",
2223
org.eclipse.tracecompass.internal.tmf.analysis.xml.core.callstack;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests",
2324
org.eclipse.tracecompass.internal.tmf.analysis.xml.core.config;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests",

tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/config/XmlConfigurationSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public ITmfConfiguration update(String id, Map<String, Object> parameters) throw
108108
if (!XmlUtils.listFiles().containsKey(id)) {
109109
return null;
110110
}
111-
111+
XmlUtils.deleteSupplementaryResources(id, null);
112112
XmlUtils.deleteFiles(ImmutableList.of(id));
113113
XmlUtils.saveFilesStatus();
114114
XmlAnalysisModuleSource.notifyModuleChange();

tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/module/XmlUtils.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,20 @@
4242
import javax.xml.validation.SchemaFactory;
4343

4444
import org.apache.commons.io.FilenameUtils;
45+
import org.eclipse.core.resources.IFile;
46+
import org.eclipse.core.resources.IFolder;
47+
import org.eclipse.core.resources.IProject;
48+
import org.eclipse.core.resources.IResource;
49+
import org.eclipse.core.resources.IResourceVisitor;
50+
import org.eclipse.core.resources.ResourcesPlugin;
4551
import org.eclipse.core.runtime.CoreException;
4652
import org.eclipse.core.runtime.FileLocator;
4753
import org.eclipse.core.runtime.IConfigurationElement;
4854
import org.eclipse.core.runtime.IPath;
55+
import org.eclipse.core.runtime.IProgressMonitor;
4956
import org.eclipse.core.runtime.ISafeRunnable;
5057
import org.eclipse.core.runtime.IStatus;
58+
import org.eclipse.core.runtime.NullProgressMonitor;
5159
import org.eclipse.core.runtime.Path;
5260
import org.eclipse.core.runtime.Platform;
5361
import org.eclipse.core.runtime.SafeRunner;
@@ -61,6 +69,11 @@
6169
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser;
6270
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlStrings;
6371
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlUtils;
72+
import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
73+
import org.eclipse.tracecompass.tmf.core.TmfProjectNature;
74+
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
75+
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
76+
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
6477
import org.osgi.framework.Bundle;
6578
import org.osgi.service.prefs.BackingStoreException;
6679
import org.w3c.dom.Document;
@@ -722,4 +735,65 @@ public static String createXmlFileString(String baseName) {
722735
});
723736
return enabledFiles;
724737
}
738+
739+
/**
740+
* Deletes all supplementary resources created by an XML analysis file
741+
*
742+
* @param xmlFileName
743+
* the file name of xml analysis
744+
* @param monitor
745+
* a progress monitor
746+
*/
747+
public static void deleteSupplementaryResources(String xmlFileName, @Nullable IProgressMonitor monitor) {
748+
final IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor);
749+
// Get unique list of analysis IDs
750+
Set<String> analysisIds = new HashSet<>();
751+
analysisIds.addAll(XmlUtils.getAnalysisIdsFromFile(xmlFileName));
752+
753+
// Delete persistent data of all open traces (this will close the file before deleting it)
754+
for (ITmfTrace trace : TmfTraceManager.getInstance().getOpenedTraces()) {
755+
for (ITmfTrace tr : TmfTraceManager.getTraceSetWithExperiment(trace)) {
756+
analysisIds.forEach(analysisId -> {
757+
IAnalysisModule module = tr.getAnalysisModule(analysisId);
758+
if (module != null) {
759+
module.clearPersistentData();
760+
}
761+
});
762+
}
763+
if (mon.isCanceled()) {
764+
return;
765+
}
766+
}
767+
// Delete applicable persistent data of non-opened traces
768+
for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
769+
try {
770+
if (project.hasNature(TmfProjectNature.ID)) {
771+
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
772+
IFolder supplFolder = project.getFolder(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER_NAME);
773+
if (supplFolder != null && supplFolder.exists()) {
774+
supplFolder.accept((IResourceVisitor) resource -> {
775+
if (mon.isCanceled()) {
776+
return false;
777+
}
778+
if (resource instanceof IFile) {
779+
analysisIds.forEach(analysisId -> {
780+
if (resource.getName().startsWith(analysisId)) {
781+
try {
782+
resource.delete(true, null);
783+
} catch (CoreException e) {
784+
Activator.logError("Can't delete supplementary resource " + resource.getName(), e); //$NON-NLS-1$
785+
}
786+
}
787+
});
788+
}
789+
return true;
790+
}, IResource.DEPTH_INFINITE, IResource.NONE);
791+
}
792+
}
793+
} catch (CoreException e) {
794+
Activator.logError("Can't delete supplementary resources for XML analyses", e); //$NON-NLS-1$
795+
}
796+
}
797+
}
798+
725799
}

0 commit comments

Comments
 (0)