Fix variable bounds check for parallel output

The following code is in nc4hdf.c, function `nc4_put_vara`.

```
  /* Check dimension bounds. Remember that unlimited dimnsions can
   * put data beyond their current length. */
  for (d2 = 0; d2 < var->ndims; d2++)
    {
      dim = var->dim[d2];
      assert(dim && dim->dimid == var->dimids[d2]);
      if (!dim->unlimited)
        {
          if (start[d2] >= (hssize_t)fdims[d2])
            BAIL_QUIET(NC_EINVALCOORDS);
          if (start[d2] + count[d2] > fdims[d2])
            BAIL_QUIET(NC_EEDGE);
        }
    }
```

There is an issue when the process with the highest rank has zero items to output.  As an example, if I have 4 mpi processes which are each writing the following amount of data:
 * rank 0: 0 items
 * rank 1: 2548 items
 * rank 2: 4352 items
 * rank 3: 0 items.

I will define the variable to have a length of 6900 items (0 + 2548 + 4352 + 0).  When I am outputting data to the variable, each rank will call nc_put_vara_longlong with the following start and count values:
 * rank 0: start = 0, count = 0
 * rank 1: start = 0, count = 2548
 * rank 2: start = 2548, count = 4352
 * rank 3: start = 6900, count = 0.

In each case, the `start` for rank N is equal to `start` for rank N-1 + `count` for rank N-1.  This all works ok until the highest rank is writing 0 items.  In that case, the `start` value for that rank is equal to the total size of the variable and the check in the code fragment shown above fails since `start[] == fdims[]`.

This could be fixed in the application code by checking whether the `count` is zero and if so, then set `start` to 0 also, but I think that is a kluge that should not be required.

Note that this test appears three times in this file.  In one case, the check for non-zero count already exists, but not in the other two.  This pull request adds the check to the other two tests.
This commit is contained in:
Greg Sjaardema 2016-03-31 11:31:31 -06:00 committed by Ward Fisher
parent fa6d64d018
commit 9290b31c9d

View File

@ -617,7 +617,7 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
log_dim_info(var, fdims, fmaxdims, start, count);
#endif
/* Check dimension bounds. Remember that unlimited dimnsions can
/* Check dimension bounds. Remember that unlimited dimensions can
* put data beyond their current length. */
for (d2 = 0; d2 < var->ndims; d2++)
{
@ -625,7 +625,7 @@ nc4_put_vara(NC *nc, int ncid, int varid, const size_t *startp,
assert(dim && dim->dimid == var->dimids[d2]);
if (!dim->unlimited)
{
if (start[d2] >= (hssize_t)fdims[d2])
if (start[d2] >= (hssize_t)fdims[d2] && count[d2] > 0)
BAIL_QUIET(NC_EINVALCOORDS);
if (start[d2] + count[d2] > fdims[d2])
BAIL_QUIET(NC_EEDGE);
@ -979,7 +979,7 @@ nc4_get_vara(NC *nc, int ncid, int varid, const size_t *startp,
else
{
/* Check for out of bound requests. */
if (start[d2] >= (hssize_t)fdims[d2])
if (start[d2] >= (hssize_t)fdims[d2] && count[d2] > 0)
BAIL_QUIET(NC_EINVALCOORDS);
if (start[d2] + count[d2] > fdims[d2])
BAIL_QUIET(NC_EEDGE);