sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Add synchronization on netCDF reader for multi-threading.
Date Thu, 21 Mar 2019 10:16:24 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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 825bb78  Add synchronization on netCDF reader for multi-threading.
825bb78 is described below

commit 825bb78f00575c8b2b71d557f6855f45f66c8fe3
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Mar 21 11:15:47 2019 +0100

    Add synchronization on netCDF reader for multi-threading.
---
 .../apache/sis/internal/netcdf/RasterResource.java | 73 +++++++++++++---------
 .../org/apache/sis/storage/netcdf/NetcdfStore.java |  2 +-
 2 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
index b176279..0b3e6b8 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
@@ -129,15 +129,22 @@ public final class RasterResource extends AbstractGridResource implements
Resour
     private final Path location;
 
     /**
+     * The object to use for synchronization. For now we use a {@code synchronized} statement,
+     * but it may be changed to {@link java.util.concurrent.locks.Lock} in a future version.
+     */
+    private final Object lock;
+
+    /**
      * Creates a new resource. All variables in the {@code data} list shall have the same
domain and the same grid geometry.
      *
      * @param  decoder  the implementation used for decoding the netCDF file.
      * @param  name     the name for the resource.
      * @param  grid     the grid geometry (size, CRS…) of the {@linkplain #data} cube.
      * @param  bands    the variables providing actual data. Shall contain at least one variable.
+     * @param  lock     the lock to use in {@code synchronized(lock)} statements.
      */
-    private RasterResource(final Decoder decoder, final String name, final GridGeometry grid,
final List<Variable> bands)
-            throws IOException, DataStoreException
+    private RasterResource(final Decoder decoder, final String name, final GridGeometry grid,
final List<Variable> bands,
+            final Object lock) throws IOException, DataStoreException
     {
         super(decoder.listeners);
         data         = bands.toArray(new Variable[bands.size()]);
@@ -145,6 +152,7 @@ public final class RasterResource extends AbstractGridResource implements
Resour
         identifier   = decoder.nameFactory.createLocalName(decoder.namespace, name);
         location     = decoder.location;
         gridGeometry = grid;
+        this.lock    = lock;
         switch (data[0].getDimension() - grid.getDimension()) {
             case 0: {
                 // All dimensions are in the CRS. This is the usual case.
@@ -165,13 +173,16 @@ public final class RasterResource extends AbstractGridResource implements
Resour
 
     /**
      * Creates all grid coverage resources from the given decoder.
+     * This method shall be invoked in a method synchronized on {@link #lock}.
      *
      * @param  decoder  the implementation used for decoding the netCDF file.
+     * @param  lock     the lock to use in {@code synchronized(lock)} statements.
      * @return all grid coverage resources.
      * @throws IOException if an I/O operation was required and failed.
      * @throws DataStoreException if a logical error occurred.
      */
-    public static List<Resource> create(final Decoder decoder) throws IOException,
DataStoreException {
+    public static List<Resource> create(final Decoder decoder, final Object lock) throws
IOException, DataStoreException {
+        assert Thread.holdsLock(lock);
         final Variable[]     variables = decoder.getVariables().clone();        // Needs
a clone because may be modified.
         final List<Variable> siblings  = new ArrayList<>(4);
         final List<Resource> resources = new ArrayList<>();
@@ -244,7 +255,7 @@ public final class RasterResource extends AbstractGridResource implements
Resour
                     }
                 }
             }
-            resources.add(new RasterResource(decoder, name.trim(), grid, siblings));
+            resources.add(new RasterResource(decoder, name.trim(), grid, siblings, lock));
             siblings.clear();
         }
         return resources;
@@ -279,11 +290,13 @@ public final class RasterResource extends AbstractGridResource implements
Resour
     public List<SampleDimension> getSampleDimensions() throws DataStoreException {
         SampleDimension.Builder builder = null;
         try {
-            for (int i=0; i<ranges.length; i++) {
-                if (ranges[i] == null) {
-                    if (builder == null) builder = new SampleDimension.Builder();
-                    ranges[i] = createSampleDimension(builder, data[i]);
-                    builder.clear();
+            synchronized (lock) {
+                for (int i=0; i<ranges.length; i++) {
+                    if (ranges[i] == null) {
+                        if (builder == null) builder = new SampleDimension.Builder();
+                        ranges[i] = createSampleDimension(builder, data[i]);
+                        builder.clear();
+                    }
                 }
             }
         } catch (TransformException e) {
@@ -439,27 +452,29 @@ public final class RasterResource extends AbstractGridResource implements
Resour
              * seeking backward.
              */
             Buffer values = null;
-            for (int i=0; i<bands.length; i++) {
-                final int r = rangeIndices.getSourceIndex(i);                   // In strictly
increasing order.
-                final Variable variable = data[bandDimension >= 0 ? 0 : r];     // Only
one variable if bandDimension ≧ 0.
-                SampleDimension sd = ranges[r];
-                if (sd == null) {
-                    ranges[r] = sd = createSampleDimension(rangeIndices.builder(), variable);
-                }
-                if (bandDimension > 0) {
-                    // TODO: adjust 'areaOfInterest'.
-                    throw new UnsupportedOperationException();
-                }
-                if (bandDimension != 0 || values == null) {
-                    // Optional.orElseThrow() below should never fail since Variable.read(…)
wraps primitive array.
-                    values = variable.read(areaOfInterest, subsamplings).buffer().get();
-                }
-                if (bandDimension == 0) {
-                    values.position(r);
+            synchronized (lock) {
+                for (int i=0; i<bands.length; i++) {
+                    final int r = rangeIndices.getSourceIndex(i);                   // In
strictly increasing order.
+                    final Variable variable = data[bandDimension >= 0 ? 0 : r];     //
Only one variable if bandDimension ≧ 0.
+                    SampleDimension sd = ranges[r];
+                    if (sd == null) {
+                        ranges[r] = sd = createSampleDimension(rangeIndices.builder(), variable);
+                    }
+                    if (bandDimension > 0) {
+                        // TODO: adjust 'areaOfInterest'.
+                        throw new UnsupportedOperationException();
+                    }
+                    if (bandDimension != 0 || values == null) {
+                        // Optional.orElseThrow() below should never fail since Variable.read(…)
wraps primitive array.
+                        values = variable.read(areaOfInterest, subsamplings).buffer().get();
+                    }
+                    if (bandDimension == 0) {
+                        values.position(r);
+                    }
+                    final int p = rangeIndices.getTargetIndex(i);
+                    sampleValues[p] = values;
+                    bands[p] = sd;
                 }
-                final int p = rangeIndices.getTargetIndex(i);
-                sampleValues[p] = values;
-                bands[p] = sd;
             }
             domain = targetGeometry.subsample(scales).build();
             imageBuffer = RasterFactory.wrap(dataType.rasterDataType, sampleValues);
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
index f67c977..b01ed54 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStore.java
@@ -201,7 +201,7 @@ public class NetcdfStore extends DataStore implements Aggregate {
     public synchronized Collection<Resource> components() throws DataStoreException
{
         if (components == null) try {
             Resource[] resources = decoder.getDiscreteSampling();
-            final List<Resource> grids = RasterResource.create(decoder);
+            final List<Resource> grids = RasterResource.create(decoder, this);
             if (!grids.isEmpty()) {
                 grids.addAll(UnmodifiableArrayList.wrap(resources));
                 resources = grids.toArray(new Resource[grids.size()]);


Mime
View raw message