mirror of
https://github.com/apache/activemq-artemis.git
synced 2025-03-08 10:19:30 +00:00
ARTEMIS-5023 web temp directory cleaner now moot
Before the changes in 15dd24754ae8c6c2dd646fbd214f7a76b33b1197 temporary web resources could proliferate and consume inordinate amounts of disk space because their directory names were generated uniquely every time Jetty was started. However, now that they are deterministic no proliferation is possible. Jetty will create the directories when it starts, remove them when it stops, and if it fails to clean-up on shutdown (e.g. crash from OOME) it will clean-up and recreate them when it starts. Therefore, our own house-keeping of those directories is no longer needed and, in fact, causes problems. For example, when executing the `restartEmbeddedWebServer` management operation the temp web resources will actually be removed inadvertently causing the web console to fail. This commit removes the web temp house-keeping logic as well as the related tests. It also modifies & adds tests to ensure Jetty does this house-keeping on its own.
This commit is contained in:
parent
eef3ea9eb3
commit
5db043da0f
@ -242,7 +242,6 @@ public class WebServerComponent implements ExternalComponent, WebServerComponent
|
||||
|
||||
server.setHandler(handlers);
|
||||
|
||||
cleanupTmp();
|
||||
server.start();
|
||||
|
||||
printStatus(bindings);
|
||||
@ -459,42 +458,6 @@ public class WebServerComponent implements ExternalComponent, WebServerComponent
|
||||
return requestLog;
|
||||
}
|
||||
|
||||
private File getLibFolder() {
|
||||
Path lib = artemisHomePath.resolve("lib");
|
||||
File libFolder = new File(lib.toUri());
|
||||
return libFolder;
|
||||
}
|
||||
|
||||
private void cleanupTmp() {
|
||||
if (webContextData.size() == 0) {
|
||||
//there is no webapp to be deployed (as in some tests)
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<File> temporaryFiles = new ArrayList<>();
|
||||
Files.newDirectoryStream(temporaryWarDir).forEach(path -> temporaryFiles.add(path.toFile()));
|
||||
|
||||
if (temporaryFiles.size() > 0) {
|
||||
WebTmpCleaner.cleanupTmpFiles(getLibFolder(), temporaryFiles, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to get base dir for tmp web files", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupWebTemporaryFiles(List<Pair<WebAppContext, String>> webContextData) throws Exception {
|
||||
List<File> temporaryFiles = new ArrayList<>();
|
||||
for (Pair<WebAppContext, String> data : webContextData) {
|
||||
File tmpdir = data.getA().getTempDirectory();
|
||||
temporaryFiles.add(tmpdir);
|
||||
}
|
||||
|
||||
if (!temporaryFiles.isEmpty()) {
|
||||
WebTmpCleaner.cleanupTmpFiles(getLibFolder(), temporaryFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStarted() {
|
||||
return server != null && server.isStarted();
|
||||
@ -555,7 +518,6 @@ public class WebServerComponent implements ExternalComponent, WebServerComponent
|
||||
scanner = null;
|
||||
scannerScheduler = null;
|
||||
scannerTasks.clear();
|
||||
cleanupWebTemporaryFiles(webContextData);
|
||||
webContextData.clear();
|
||||
jolokiaUrls.clear();
|
||||
consoleUrls.clear();
|
||||
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.artemis.component;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
/**
|
||||
* This class is used to remove the jar files
|
||||
* in temp web dir on Windows platform where
|
||||
* handles of the jar files are never released
|
||||
* by URLClassLoader until the whole VM exits.
|
||||
*/
|
||||
public class WebTmpCleaner {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public static void main(String[] filesToClean) throws Exception {
|
||||
//It needs to retry a bit as we are not sure
|
||||
//when the main VM exists.
|
||||
cleanupFilesWithRetry(filesToClean, 100);
|
||||
}
|
||||
|
||||
private static boolean cleanupFilesWithRetry(String[] filesToClean, int maxRetries) throws Exception {
|
||||
boolean allCleaned = false;
|
||||
while (!allCleaned && maxRetries-- > 0) {
|
||||
allCleaned = true;
|
||||
for (String f : filesToClean) {
|
||||
if (!f.trim().isEmpty()) {
|
||||
URI url = new URI(f);
|
||||
File file = new File(url);
|
||||
if (file.exists()) {
|
||||
deleteFolder(file);
|
||||
allCleaned = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Thread.sleep(200);
|
||||
}
|
||||
if (!allCleaned) {
|
||||
logger.warn("Some files in web temp dir are not cleaned up after {} retries.", maxRetries);
|
||||
}
|
||||
return allCleaned;
|
||||
}
|
||||
|
||||
public static Process cleanupTmpFiles(File libFolder, List<File> temporaryFiles) throws Exception {
|
||||
return cleanupTmpFiles(libFolder, temporaryFiles, false);
|
||||
}
|
||||
|
||||
public static Process cleanupTmpFiles(File libFolder, List<File> temporaryFiles, boolean invm) throws Exception {
|
||||
ArrayList<String> files = new ArrayList<>(temporaryFiles.size());
|
||||
for (File f : temporaryFiles) {
|
||||
files.add(f.toURI().toString());
|
||||
}
|
||||
|
||||
if (!invm) {
|
||||
String classPath = SpawnedVMSupport.getClassPath(libFolder);
|
||||
return SpawnedVMSupport.spawnVM(classPath, WebTmpCleaner.class.getName(), false, (String[]) files.toArray(new String[files.size()]));
|
||||
}
|
||||
cleanupFilesWithRetry(files.toArray(new String[files.size()]), 2);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final void deleteFolder(final File file) {
|
||||
if (file.isDirectory()) {
|
||||
String[] files = file.list();
|
||||
if (files != null) {
|
||||
for (String path : files) {
|
||||
File f = new File(file, path);
|
||||
deleteFolder(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
}
|
@ -16,15 +16,7 @@
|
||||
*/
|
||||
package org.apache.activemq.cli.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -33,7 +25,6 @@ import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.cli.Artemis;
|
||||
import org.apache.activemq.artemis.cli.commands.Run;
|
||||
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
|
||||
import org.apache.activemq.artemis.component.WebTmpCleaner;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
|
||||
@ -48,6 +39,9 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class WebServerCLITest extends ArtemisTestCase {
|
||||
|
||||
// Temp folder at ./target/tmp/<TestClassName>/<generated>
|
||||
@ -101,43 +95,9 @@ public class WebServerCLITest extends ArtemisTestCase {
|
||||
stopServer();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCleanupFolder() throws Exception {
|
||||
List<File> fileList = new ArrayList<>();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
File directory = newFolder(temporaryFolder, "test & output " + i);
|
||||
fillup(directory);
|
||||
}
|
||||
Process process = WebTmpCleaner.cleanupTmpFiles(null, fileList);
|
||||
assertEquals(0, process.waitFor());
|
||||
for (File f : fileList) {
|
||||
assertFalse(f.exists());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void fillup(File file) throws Exception {
|
||||
file.mkdirs();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
File fi = new File(file, "file" + i + ".txt");
|
||||
PrintStream str = new PrintStream(new FileOutputStream(fi));
|
||||
str.println("hello");
|
||||
str.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopServer() throws Exception {
|
||||
Artemis.internalExecute("stop");
|
||||
assertTrue(Run.latchRunning.await(5, TimeUnit.SECONDS));
|
||||
assertEquals(0, LibaioContext.getTotalMaxIO());
|
||||
}
|
||||
|
||||
private static File newFolder(File root, String subFolder) throws IOException {
|
||||
File result = new File(root, subFolder);
|
||||
if (!result.mkdirs()) {
|
||||
throw new IOException("Couldn't create folders " + root);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,6 @@
|
||||
*/
|
||||
package org.apache.activemq.cli.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SNIHostName;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@ -110,6 +104,12 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class WebServerComponentTest extends ArtemisTestCase {
|
||||
|
||||
@TempDir
|
||||
@ -703,7 +703,7 @@ public class WebServerComponentTest extends ArtemisTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerCleanupBeforeStart() throws Exception {
|
||||
public void testWebServerCleanupAfterStop() throws Exception {
|
||||
final String warName = "simple-app.war";
|
||||
createTestWar(warName);
|
||||
final String url = "simple-app/";
|
||||
@ -718,30 +718,44 @@ public class WebServerComponentTest extends ArtemisTestCase {
|
||||
webServerComponent.getWebContextData().add(new Pair(ctxt, null));
|
||||
|
||||
WebInfConfiguration cfg = new WebInfConfiguration();
|
||||
List<File> garbage = new ArrayList<>();
|
||||
|
||||
cfg.resolveTempDirectory(ctxt);
|
||||
|
||||
File tmpdir = ctxt.getTempDirectory();
|
||||
File testDir = tmpdir.getParentFile();
|
||||
|
||||
createGarbagesInDir(testDir, garbage);
|
||||
|
||||
assertTrue(garbage.size() > 0);
|
||||
|
||||
for (File file : garbage) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
|
||||
webServerComponent.start();
|
||||
|
||||
//make sure those garbage are gone
|
||||
for (File file : garbage) {
|
||||
assertFalse(file.exists(), "file exist: " + file.getAbsolutePath());
|
||||
}
|
||||
assertTrue(webServerComponent.isStarted());
|
||||
File warTempDir = new File(ctxt.getTempDirectory().getAbsolutePath());
|
||||
assertTrue(warTempDir.exists(), warTempDir + " doesn't exist!");
|
||||
webServerComponent.stop(true);
|
||||
assertFalse(webServerComponent.isStarted());
|
||||
|
||||
assertFalse(warTempDir.exists(), warTempDir + " exists!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWebServerCleanupBeforeStart() throws Exception {
|
||||
final String warName = "simple-app.war";
|
||||
createTestWar(warName);
|
||||
final String url = "simple-app/";
|
||||
|
||||
WebServerDTO webServerDTO = createDefaultWebServerDTO(warName, url);
|
||||
|
||||
WebServerComponent webServerComponent = new WebServerComponent();
|
||||
assertFalse(webServerComponent.isStarted());
|
||||
testedComponents.add(webServerComponent);
|
||||
webServerComponent.configure(webServerDTO, "./target", "./target");
|
||||
WebAppContext ctxt = WebServerComponentTestAccessor.createWebAppContext(webServerComponent, url, warName, Paths.get(".").resolve("target").toAbsolutePath(), null);
|
||||
webServerComponent.getWebContextData().add(new Pair(ctxt, null));
|
||||
|
||||
if (!Files.exists(Paths.get(ctxt.getTempDirectory().getAbsolutePath()))) {
|
||||
Files.createDirectory(Paths.get(ctxt.getTempDirectory().getAbsolutePath()));
|
||||
}
|
||||
long originalLastModified = Files.getLastModifiedTime(Paths.get(ctxt.getTempDirectory().getAbsolutePath())).toMillis();
|
||||
Thread.sleep(5);
|
||||
webServerComponent.start();
|
||||
assertTrue(webServerComponent.isStarted());
|
||||
assertFalse(originalLastModified == Files.getLastModifiedTime(Paths.get(ctxt.getTempDirectory().getAbsolutePath())).toMillis());
|
||||
webServerComponent.stop(true);
|
||||
assertFalse(webServerComponent.isStarted());
|
||||
assertFalse(Files.exists(Paths.get(ctxt.getTempDirectory().getAbsolutePath())), ctxt.getTempDirectory().getAbsolutePath() + " exists!");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user