From d63fabc85d1f82ccd8cb03c7f75b3910c5325f03 Mon Sep 17 00:00:00 2001 From: ahr Date: Fri, 15 Dec 2017 17:20:12 +0100 Subject: [PATCH] prevent parallel plot requests Plotting can take a long time and use a lot of resources. Multiple plot requests can cause the machine to run OOM. We are now allowing plots for 500k files again. This is mainly to prevent unwanted plots of everything. --- .../java/org/lucares/pdbui/PdbController.java | 35 +++++++++++++------ .../pdbui/ServiceUnavailableException.java | 14 ++++++++ .../lucares/performance/db/TagsToFile.java | 2 +- 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 pdb-ui/src/main/java/org/lucares/pdbui/ServiceUnavailableException.java diff --git a/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java b/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java index 52101a7..328753f 100644 --- a/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java +++ b/pdb-ui/src/main/java/org/lucares/pdbui/PdbController.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedSet; +import java.util.concurrent.locks.ReentrantLock; import org.lucares.pdb.datastore.Proposal; import org.lucares.pdb.plot.api.PlotSettings; @@ -50,6 +51,8 @@ public class PdbController implements HardcodedValues { private final Plotter plotter; private final PerformanceDb db; + + private final ReentrantLock plotterLock = new ReentrantLock(); public PdbController(final PerformanceDb db, final Plotter plotter) { this.db = db; @@ -71,20 +74,32 @@ public class PdbController implements HardcodedValues { produces = MediaType.APPLICATION_JSON_UTF8_VALUE // ) @ResponseBody - PlotResponse createPlot(@RequestBody final PlotRequest request) throws InternalPlottingException { + PlotResponse createPlot(@RequestBody final PlotRequest request) + throws InternalPlottingException, InterruptedException { - final PlotSettings plotSettings = PlotSettingsTransformer.toSettings(request); + final PlotSettings plotSettings = PlotSettingsTransformer + .toSettings(request); - try { - final PlotResult result = plotter.plot(plotSettings); + // TODO the UI should cancel requests that are in flight before sending a plot request + if (plotterLock.tryLock()) { + try { + final PlotResult result = plotter.plot(plotSettings); - final String imageUrl = WEB_IMAGE_OUTPUT_PATH + "/" + result.getImageName(); - LOGGER.trace("image url: {}", imageUrl); - System.gc(); + final String imageUrl = WEB_IMAGE_OUTPUT_PATH + "/" + + result.getImageName(); + LOGGER.trace("image url: {}", imageUrl); + System.gc(); - return new PlotResponse(DataSeries.toMap(result.getDataSeries()), imageUrl); - } catch (final NoDataPointsException e) { - throw new NotFoundException(e); + return new PlotResponse( + DataSeries.toMap(result.getDataSeries()), imageUrl); + } catch (final NoDataPointsException e) { + throw new NotFoundException(e); + } finally { + plotterLock.unlock(); + } + + } else { + throw new ServiceUnavailableException("Too many parallel requests!"); } } diff --git a/pdb-ui/src/main/java/org/lucares/pdbui/ServiceUnavailableException.java b/pdb-ui/src/main/java/org/lucares/pdbui/ServiceUnavailableException.java new file mode 100644 index 0000000..d8d67f0 --- /dev/null +++ b/pdb-ui/src/main/java/org/lucares/pdbui/ServiceUnavailableException.java @@ -0,0 +1,14 @@ +package org.lucares.pdbui; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE, reason = "Service Unavailable") +public class ServiceUnavailableException extends RuntimeException { + + private static final long serialVersionUID = -4512668277873760500L; + + public ServiceUnavailableException(String message) { + super(message); + } +} diff --git a/performanceDb/src/main/java/org/lucares/performance/db/TagsToFile.java b/performanceDb/src/main/java/org/lucares/performance/db/TagsToFile.java index 2c4e400..dc1cd1c 100644 --- a/performanceDb/src/main/java/org/lucares/performance/db/TagsToFile.java +++ b/performanceDb/src/main/java/org/lucares/performance/db/TagsToFile.java @@ -80,7 +80,7 @@ public class TagsToFile implements AutoCloseable { final List result = new ArrayList<>(); final List searchResult = db.search(query); - if (searchResult.size() > 100_000){ + if (searchResult.size() > 500_000){ throw new IllegalStateException("Too many results."); }