sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/02: Apply `ErrorHandler` during sequential operations too, not only during parallel operations.
Date Wed, 10 Feb 2021 15:11:51 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 7538f73be1dc48aa3a0933fa92d9b6c1899699c1
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Wed Feb 10 12:47:42 2021 +0100

    Apply `ErrorHandler` during sequential operations too, not only during parallel operations.
---
 .../java/org/apache/sis/image/ImageProcessor.java  |  6 ---
 .../sis/internal/coverage/j2d/TileOpExecutor.java  | 48 +++++++++-------------
 2 files changed, 20 insertions(+), 34 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
index 146ba81..808a425 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
@@ -867,12 +867,6 @@ public class ImageProcessor implements Cloneable {
      *   <li>{@linkplain #getErrorHandler() Error handler} (whether to fail if an exception
is thrown).</li>
      * </ul>
      *
-     * <h4>Limitation</h4>
-     * Current implementation ignores the {@linkplain #getErrorHandler() error handler} in
sequential execution
-     * (i.e. error handler is used only during parallel execution). In addition, there is
not yet a mechanism
-     * for specifying which tile to produce in replacement of tiles that can not be computed.
-     * Those limitations may be addressed in a future version.
-     *
      * @param  source          the image to compute immediately (may be {@code null}).
      * @param  areaOfInterest  pixel coordinates of the region to prefetch, or {@code null}
for the whole image.
      * @return image with all tiles intersecting the AOI computed, or {@code null} if the
given image was null.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TileOpExecutor.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TileOpExecutor.java
index 46e563d..7a7e27b 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TileOpExecutor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TileOpExecutor.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.coverage.j2d;
 
+import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.util.stream.Collector;
 import java.util.function.BiConsumer;
@@ -198,9 +199,9 @@ public class TileOpExecutor {
      * Only tiles intersecting the area of interest will be processed.
      * For each tile, the {@link #readFrom(Raster)} method will be invoked in current thread.
      *
-     * <p>If a tile processing throws an exception, then this method stops immediately;
-     * remaining tiles are not processed. This policy is suited to the cases where the
-     * caller will not return any result in case of error.</p>
+     * <p>If a tile processing throws an exception and the {@link #errorHandler} is
{@link TileErrorHandler#THROW},
+     * then this method stops immediately; remaining tiles are not processed. This policy
is suited to the cases
+     * where the caller will not return any result in case of error.</p>
      *
      * <p>This method does not parallelize tile operations, because it is invoked
      * in contexts where it should apply on exactly one tile most of the times.</p>
@@ -212,17 +213,16 @@ public class TileOpExecutor {
      *         {@linkplain ImagingOpException#getCause() cause}.
      */
     public final void readFrom(final RenderedImage source) {
+        final ErrorHandler.Report errors = new ErrorHandler.Report();
         for (int ty = minTileY; ty <= maxTileY; ty++) {
             for (int tx = minTileX; tx <= maxTileX; tx++) try {
                 readFrom(source.getTile(tx, ty));
             } catch (Exception ex) {
-                Throwable e = trimImagingWrapper(ex);
-                if (!(e instanceof ImagingOpException)) {
-                    e = new ImagingOpException(Resources.format(Resources.Keys.CanNotProcessTile_2,
tx, ty)).initCause(ex);
-                }
-                throw (ImagingOpException) e;
+                errors.add(new Point(tx, ty), trimImagingWrapper(ex), null);
+                if (errorHandler == TileErrorHandler.THROW) break;
             }
         }
+        errorHandler.publish(errors);
     }
 
     /**
@@ -232,9 +232,9 @@ public class TileOpExecutor {
      * For each tile, the {@link #writeTo(WritableRaster)} method will be invoked in current
thread.
      *
      * <p>If a tile processing throws an exception, then this method continues processing
other tiles
-     * and will throw the wrapper exception only after all tiles have been processed. This
policy is
+     * and will log or throw the exception only after all tiles have been processed. This
policy is
      * suited to the cases where the target image will continue to exist after this method
call and
-     * we want to have a relatively consistent state.</p>
+     * we want to have as much valid values as possible.</p>
      *
      * <p>This method does not parallelize tile operations, because it is invoked
      * in contexts where it should apply on exactly one tile most of the times.</p>
@@ -246,7 +246,7 @@ public class TileOpExecutor {
      *         This exception wraps the original exception as its {@linkplain ImagingOpException#getCause()
cause}.
      */
     public final void writeTo(final WritableRenderedImage target) {
-        ImagingOpException error = null;
+        final ErrorHandler.Report errors = new ErrorHandler.Report();
         for (int ty = minTileY; ty <= maxTileY; ty++) {
             for (int tx = minTileX; tx <= maxTileX; tx++) try {
                 final WritableRaster tile = target.getWritableTile(tx, ty);
@@ -256,20 +256,12 @@ public class TileOpExecutor {
                     target.releaseWritableTile(tx, ty);
                 }
             } catch (Exception ex) {
-                final Throwable e = trimImagingWrapper(ex);
-                if (error != null) {
-                    error.addSuppressed(e);
-                } else if (e instanceof ImagingOpException) {
-                    error = (ImagingOpException) e;
-                } else {
-                    error = new ImagingOpException(Resources.format(Resources.Keys.CanNotUpdateTile_2,
tx, ty));
-                    error.initCause(e);
-                }
+                final Point tile = new Point(tx, ty);
+                errors.add(tile, trimImagingWrapper(ex), () -> Resources.forLocale(null)
+                            .getLogRecord(Level.WARNING, Resources.Keys.CanNotUpdateTile_2,
tile.x, tile.y));
             }
         }
-        if (error != null) {
-            throw error;
-        }
+        errorHandler.publish(errors);
     }
 
     /**
@@ -280,9 +272,9 @@ public class TileOpExecutor {
      * in an arbitrary thread (may be the current one).
      *
      * <h4>Errors management</h4>
-     * If a tile processing throws an exception, then the other threads will finish computing
-     * their current tile but no other tiles will be fetched; remaining tiles are not processed.
-     * This policy is suited to the cases where the caller will not return any result in
case of error.
+     * If a tile processing throws an exception and the {@link #errorHandler} is {@link TileErrorHandler#THROW},
+     * then this method stops immediately; remaining tiles are not processed. This policy
is suited to the cases
+     * where the caller will not return any result in case of error.
      *
      * <h4>Concurrency requirements</h4>
      * Subclasses must override {@link #readFrom(Raster)} with a concurrent implementation.
@@ -318,9 +310,9 @@ public class TileOpExecutor {
      *
      * <h4>Errors management</h4>
      * If a tile processing throws an exception, then this method continues processing other
tiles
-     * and will throw the wrapper exception only after all tiles have been processed. This
policy is
+     * and will log or throw the exception only after all tiles have been processed. This
policy is
      * suited to the cases where the target image will continue to exist after this method
call and
-     * we want to have a relatively consistent state.
+     * we want to have as much valid values as possible.
      *
      * <h4>Concurrency requirements</h4>
      * Subclasses must override {@link #writeTo(WritableRaster)} with a concurrent implementation.


Mime
View raw message