static int builtin_posix_module_element_write_strided_nb (hio_element_t element, hio_request_t *request,
                                                          off_t offset, const void *ptr, size_t count,
                                                          size_t size, size_t stride) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  builtin_posix_module_t *posix_module = (builtin_posix_module_t *) posix_dataset->base.ds_module;
  hio_context_t context = hioi_object_context (&element->e_object);
  ssize_t bytes_written;
  hio_request_t new_request;

  pthread_mutex_lock (&posix_dataset->lock);
  bytes_written = builtin_posix_module_element_write_strided_internal (posix_module, element, offset, ptr, count, size,
                                                                       stride);
  pthread_mutex_unlock (&posix_dataset->lock);

  if (request) {
    new_request = hioi_request_alloc (context);
    if (NULL == new_request) {
      return HIO_ERR_OUT_OF_RESOURCE;
    }

    *request = new_request;
    new_request->req_transferred = bytes_written;
    new_request->req_complete = true;
    new_request->req_status = posix_dataset->base.ds_status;
  }

  return posix_dataset->base.ds_status;
}
static int builtin_posix_module_element_flush (hio_element_t element, hio_flush_mode_t mode) {
  builtin_posix_module_dataset_t *posix_dataset =
    (builtin_posix_module_dataset_t *) hioi_element_dataset (element);

  if (!(posix_dataset->base.ds_flags & HIO_FLAG_WRITE)) {
    return HIO_ERR_PERM;
  }

  if (HIO_FILE_MODE_OPTIMIZED == posix_dataset->base.ds_fmode) {
    for (int i = 0 ; i < HIO_POSIX_MAX_OPEN_FILES ; ++i) {
      if (posix_dataset->files[i].f_file.f_hndl) {
        fflush (posix_dataset->files[i].f_file.f_hndl);
        if (HIO_FLUSH_MODE_COMPLETE == mode) {
          fsync (fileno (posix_dataset->files[i].f_file.f_hndl));
        }
      }
    }
  } else {
    if (NULL != element->e_file.f_hndl) {
      fflush (element->e_file.f_hndl);
      if (HIO_FLUSH_MODE_COMPLETE == mode) {
        fsync (fileno (element->e_file.f_hndl));
      }
    }
  }

  return HIO_SUCCESS;
}
static int builtin_posix_element_translate_strided (builtin_posix_module_t *posix_module, hio_element_t element,
                                                    uint64_t offset, size_t *size, hio_file_t **file_out) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  size_t block_id, block_base, block_bound, block_offset, file_id, file_block;
  hio_context_t context = hioi_object_context (&element->e_object);
  hio_file_t *file;
  int32_t file_index;
  char *path;
  int rc;

  block_id = offset / posix_dataset->ds_bs;

  file_id = block_id % posix_dataset->ds_fcount;
  file_block = block_id / posix_dataset->ds_fcount;

  block_base = block_id * posix_dataset->ds_bs;
  block_bound = block_base + posix_dataset->ds_bs;
  block_offset = file_block * posix_dataset->ds_bs + offset - block_base;

  hioi_log (context, HIO_VERBOSE_DEBUG_LOW, "builtin_posix_element_translate_strided: element: %s, offset: %"
            PRIu64 ", file_id: %lu, file_block: %lu, block_offset: %lu, block_size: %" PRIu64,
            hioi_object_identifier(element), offset, file_id, file_id, block_offset, posix_dataset->ds_bs);

  if (offset + *size > block_bound) {
    *size = block_bound - offset;
  }

  rc = asprintf (&path, "%s/data/%s_block.%08lu", posix_dataset->base_path, hioi_object_identifier(element),
                 (unsigned long) file_id);
  if (0 > rc) {
    return HIO_ERR_OUT_OF_RESOURCE;
  }

  /* use crc as a hash to pick a file index to use */
  file_index = file_id % HIO_POSIX_MAX_OPEN_FILES;
  file = posix_dataset->files + file_index;

  if (file_id != file->f_bid || file->f_element != element) {
    if (file->f_bid >= 0) {
      POSIX_TRACE_CALL(posix_dataset, hioi_file_close (file), "file_close", file->f_bid, 0);
    }
    file->f_bid = -1;

    file->f_element = element;

    POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_open_file (posix_module, posix_dataset, path, file),
                     "file_open", file_id, 0);
    if (HIO_SUCCESS != rc) {
      return rc;
    }

    file->f_bid = file_id;
  }

  POSIX_TRACE_CALL(posix_dataset, hioi_file_seek (file, block_offset, SEEK_SET), "file_seek", file->f_bid, block_offset);

  *file_out = file;

  return HIO_SUCCESS;
}
static int builtin_posix_module_element_complete (hio_element_t element) {
  hio_dataset_t dataset = hioi_element_dataset (element);

  /* reads in this module are always blocking. need to update this code if
   * that ever changes */
  if (!(dataset->ds_flags & HIO_FLAG_READ)) {
    return HIO_ERR_PERM;
  }

  return HIO_SUCCESS;
}
static int builtin_posix_element_translate (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset,
                                            size_t *size, hio_file_t **file_out, bool reading) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);

  if (HIO_FILE_MODE_BASIC == posix_dataset->base.ds_fmode) {
    *file_out = &element->e_file;
    if (offset != element->e_file.f_offset) {
      fseek (element->e_file.f_hndl, offset, SEEK_SET);
      element->e_file.f_offset = offset;
    }

    return HIO_SUCCESS;
  }

  if (reading && 0 == element->e_scount) {
    return builtin_posix_element_translate_opt_old (posix_module, element, offset, size, file_out);
  }

  return builtin_posix_element_translate_opt (posix_module, element, offset, size, file_out, reading);
}
static int builtin_posix_element_translate (builtin_posix_module_t *posix_module, hio_element_t element,
                                            uint64_t offset, size_t *size, hio_file_t **file_out, bool reading) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  int rc = HIO_SUCCESS;

  switch (posix_dataset->ds_fmode) {
  case HIO_FILE_MODE_BASIC:
    *file_out = &element->e_file;
    hioi_file_seek (&element->e_file, offset, SEEK_SET);
    break;
  case HIO_FILE_MODE_STRIDED:
    rc = builtin_posix_element_translate_strided (posix_module, element, offset, size, file_out);
    break;
  case HIO_FILE_MODE_OPTIMIZED:
    rc = builtin_posix_element_translate_opt (posix_module, element, offset, size, file_out, reading);
    break;
  }

  return rc;
}
static int builtin_posix_module_element_read_strided_nb (hio_element_t element, hio_request_t *request, off_t offset,
                                                         void *ptr, size_t count, size_t size, size_t stride) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  builtin_posix_module_t *posix_module = (builtin_posix_module_t *) posix_dataset->base.ds_module;
  hio_context_t context = hioi_object_context (&element->e_object);
  ssize_t bytes_read;
  hio_request_t new_request;
  int rc = HIO_SUCCESS;

  if (!(posix_dataset->base.ds_flags & HIO_FLAG_READ)) {
    return HIO_ERR_PERM;
  }

  if (stride == 0) {
    size *= count;
    count = 1;
  }

  hioi_object_lock (&posix_dataset->base.ds_object);
  bytes_read = builtin_posix_module_element_read_strided_internal (posix_module, element, offset, ptr, count, size, stride);
  hioi_object_unlock (&posix_dataset->base.ds_object);

  if (0 > bytes_read) {
    rc = (int) bytes_read;
  }

  /* see if a request was requested */
  if (request) {
    new_request = hioi_request_alloc (context);
    if (NULL == new_request) {
      return HIO_ERR_OUT_OF_RESOURCE;
    }

    *request = new_request;
    new_request->req_transferred = bytes_read;
    new_request->req_complete = true;
  }

  return rc;
}
static int builtin_posix_module_element_flush (hio_element_t element, hio_flush_mode_t mode) {
  builtin_posix_module_dataset_t *posix_dataset =
    (builtin_posix_module_dataset_t *) hioi_element_dataset (element);

  if (!(posix_dataset->base.ds_flags & HIO_FLAG_WRITE)) {
    return HIO_ERR_PERM;
  }

  if (HIO_FLUSH_MODE_COMPLETE != mode) {
    /* nothing to do at this time */
    return HIO_SUCCESS;
  }

  if (HIO_FILE_MODE_BASIC != posix_dataset->ds_fmode) {
    for (int i = 0 ; i < HIO_POSIX_MAX_OPEN_FILES ; ++i) {
      hioi_file_flush (posix_dataset->files + i);
    }
  } else {
    hioi_file_flush (&element->e_file);
  }

  return HIO_SUCCESS;
}
static ssize_t builtin_posix_module_element_read_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element,
                                                                   off_t offset, void *ptr, size_t count, size_t size,
                                                                   size_t stride) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  size_t bytes_read = 0, ret;
  hio_file_t *file;
  uint64_t start, stop;
  int rc;

  if (!(count * size)) {
    return 0;
  }

  errno = 0;

  start = hioi_gettime ();

  for (size_t i = 0 ; i < count ; ++i) {
    size_t req = size, actual;

    do {
      actual = req;

      rc = builtin_posix_element_translate (posix_module, element, offset, &actual,
                                            &file, true);
      if (HIO_SUCCESS != rc) {
        break;
      }

      ret = fread (ptr, 1, actual, file->f_hndl);
      if (ret > 0) {
        bytes_read += ret;
        file->f_offset += ret;
      }

      if (ret < actual) {
        /* short read */
        break;
      }

      req -= actual;
      offset += actual;
      ptr = (void *) ((intptr_t) ptr + actual);
    } while (req);

    if (req || HIO_SUCCESS != rc) {
      break;
    }

    ptr = (void *) ((intptr_t) ptr + stride);
  }

  if (0 == bytes_read || HIO_SUCCESS != rc) {
    if (0 == bytes_read) {
      rc = hioi_err_errno (errno);
    }
    return rc;
  }

  stop = hioi_gettime ();
  posix_dataset->base.ds_stat.s_rtime += stop - start;
  posix_dataset->base.ds_stat.s_bread += bytes_read;

  return bytes_read;
}
Beispiel #10
0
static ssize_t builtin_posix_module_element_write_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element,
                                                                    off_t offset, const void *ptr, size_t count, size_t size,
                                                                    size_t stride) {
  hio_dataset_t dataset = hioi_element_dataset (element);
  size_t bytes_written = 0, ret;
  hio_file_t *file;
  uint64_t stop, start;
  int rc;

  assert (dataset->ds_flags & HIO_FLAG_WRITE);

  if (!(count * size)) {
    return 0;
  }

  if (0 == stride) {
    size *= count;
    count = 1;
  }

  start = hioi_gettime ();

  errno = 0;

  for (size_t i = 0 ; i < count ; ++i) {
    size_t req = size, actual;

    do {
      actual = req;

      rc = builtin_posix_element_translate (posix_module, element, offset, &actual,
                                            &file, false);
      assert (file);
      if (HIO_SUCCESS != rc) {
        break;
      }

      ret = fwrite (ptr, 1, actual, file->f_hndl);
      if (ret > 0) {
        bytes_written += ret;
        file->f_offset += ret;
      }

      if (ret < actual) {
        /* short write */
        break;
      }

      req -= actual;
      offset += actual;
      ptr = (void *) ((intptr_t) ptr + actual);
    } while (req);

    if (HIO_SUCCESS != rc || req) {
      break;
    }

    ptr = (void *) ((intptr_t) ptr + stride);
  }

  if (0 == bytes_written || HIO_SUCCESS != rc) {
    if (0 == bytes_written) {
      rc = hioi_err_errno (errno);
    }

    dataset->ds_status = rc;
    return rc;
  }

  if (offset + bytes_written > element->e_size) {
    element->e_size = offset + bytes_written;
  }

  stop = hioi_gettime ();

  dataset->ds_stat.s_wtime += stop - start;

  if (0 < bytes_written) {
    dataset->ds_stat.s_bwritten += bytes_written;
  }

  hioi_log (hioi_object_context (&element->e_object), HIO_VERBOSE_DEBUG_LOW, "posix: finished write. bytes written: "
            "%lu, time: %llu usec", bytes_written, stop - start);

  return bytes_written;
}
Beispiel #11
0
static int builtin_posix_element_translate_opt (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset,
                                                size_t *size, hio_file_t **file_out, bool reading) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  hio_context_t context = hioi_object_context (&element->e_object);
  builtin_posix_file_t *file;
  uint64_t file_offset;
  int file_index;
  char *path;
  int rc;

  hioi_log (context, HIO_VERBOSE_DEBUG_MED, "translating element %s offset %ld size %lu",
            hioi_object_identifier (&element->e_object), offset, *size);
  rc = hioi_element_translate_offset (element, offset, &file_index, &file_offset, size);
  if (HIO_SUCCESS != rc) {
    if (reading) {
      hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset not found");
      /* not found */
      return rc;
    }

    if (hioi_context_using_mpi (context)) {
      rc = asprintf (&path, "%s/data.%x", posix_dataset->base_path, posix_dataset->base.ds_shared_control->s_master);
      if (0 > rc) {
        return HIO_ERR_OUT_OF_RESOURCE;
      }
    } else {
      rc = asprintf (&path, "%s/data", posix_dataset->base_path);
      if (0 > rc) {
        return HIO_ERR_OUT_OF_RESOURCE;
      }
    }

    file_offset = builtin_posix_reserve (posix_dataset, size);

    file_index = hioi_dataset_add_file (&posix_dataset->base, strrchr (path, '/') + 1);
    hioi_element_add_segment (element, file_index, file_offset, offset, *size);
  } else {
    hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset found in file @ index %d, offset %lu, size %lu", file_index,
              file_offset, *size);
    rc = asprintf (&path, "%s/%s", posix_dataset->base_path, posix_dataset->base.ds_flist[file_index].f_name);
    if (0 > rc) {
      return HIO_ERR_OUT_OF_RESOURCE;
    }
  }

  /* use crc as a hash to pick a file index to use */
  int internal_index = file_index % HIO_POSIX_MAX_OPEN_FILES;
  file = posix_dataset->files + internal_index;

  if (internal_index != file->f_bid) {
    if (NULL != file->f_file.f_hndl) {
      fclose (file->f_file.f_hndl);
      file->f_file.f_hndl = NULL;
      file->f_bid = -1;
    }

    rc = builtin_posix_open_file (posix_module, posix_dataset, path, &file->f_file);
    if (HIO_SUCCESS != rc) {
      free (path);
      return rc;
    }

    file->f_bid = file_index;
  }

  free (path);

  if (file_offset != file->f_file.f_offset) {
    fseek (file->f_file.f_hndl, file_offset, SEEK_SET);
    file->f_file.f_offset = file_offset;
  }

  *file_out = &file->f_file;

  return HIO_SUCCESS;
}
Beispiel #12
0
static int builtin_posix_element_translate_opt_old (builtin_posix_module_t *posix_module, hio_element_t element, off_t offset,
                                                    size_t *size, hio_file_t **file_out) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  hio_context_t context = hioi_object_context (&element->e_object);
  size_t block_id, block_base, block_bound, block_offset;
  builtin_posix_file_t *file;
  int32_t file_index;
  char *path;
  int rc, foo;

  block_id = offset / posix_dataset->base.ds_bs;
  block_base = block_id * posix_dataset->base.ds_bs;
  block_bound = block_base + posix_dataset->base.ds_bs;
  block_offset = offset - block_base;

  hioi_log (context, HIO_VERBOSE_DEBUG_LOW, "builtin_posix_element_translate: element: %s, offset: %lu, block_id: %lu, "
            "block_offset: %lu, block_size: %lu", hioi_object_identifier(element), (unsigned long) offset,
            block_id, block_offset, posix_dataset->base.ds_bs);

  if (offset + *size > block_bound) {
    *size = block_bound - offset;
  }

  rc = asprintf (&path, "%s_block.%lu", hioi_object_identifier(element), (unsigned long) block_id);
  if (0 > rc) {
    return HIO_ERR_OUT_OF_RESOURCE;
  }

  if (HIO_FLAG_WRITE & posix_dataset->base.ds_flags) {
    foo = hioi_dataset_add_file (&posix_dataset->base, path);
  }
  char *tmp = path;
  rc = asprintf (&path, "%s/%s", posix_dataset->base_path, tmp);
  free (tmp);
  if (0 > rc) {
    return HIO_ERR_OUT_OF_RESOURCE;
  }

  /* use crc as a hash to pick a file index to use */
  file_index = hioi_crc32 ((uint8_t *) path, strlen (path)) % HIO_POSIX_MAX_OPEN_FILES;
  file = posix_dataset->files + file_index;

  if (block_id != file->f_bid || file->f_element != element) {
    if (file->f_file.f_hndl != NULL) {
      fclose (file->f_file.f_hndl);
      file->f_file.f_hndl = NULL;
      file->f_bid = -1;
    }

    file->f_element = element;

    rc = builtin_posix_open_file (posix_module, posix_dataset, path, &file->f_file);
    if (HIO_SUCCESS != rc) {
      return rc;
    }

    file->f_bid = block_id;
  }

  if (block_offset != file->f_file.f_offset) {
    fseek (file->f_file.f_hndl, block_offset, SEEK_SET);
    file->f_file.f_offset = block_offset;
  }

  if (HIO_FLAG_WRITE & posix_dataset->base.ds_flags) {
    hioi_element_add_segment (element, foo, block_offset, offset, *size);
  }

  *file_out = &file->f_file;

  return HIO_SUCCESS;
}
static ssize_t builtin_posix_module_element_read_strided_internal (builtin_posix_module_t *posix_module, hio_element_t element,
                                                                   uint64_t offset, void *ptr, size_t count, size_t size,
                                                                   size_t stride) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  size_t bytes_read = 0, ret;
  hio_file_t *file;
  uint64_t start, stop;
  int rc;

  if (0 == count || 0 == size) {
    return 0;
  }

  errno = 0;

  start = hioi_gettime ();

  for (size_t i = 0 ; i < count ; ++i) {
    size_t req = size, actual;

    do {
      actual = req;

      /* find out where the data lives */
      POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_element_translate (posix_module, element, offset, &actual,
                                                                            &file, true),
                       "element_translate", offset, req);
      if (HIO_SUCCESS != rc) {
        break;
      }

      POSIX_TRACE_CALL(posix_dataset, ret = hioi_file_read (file, ptr, actual), "file_read", offset, actual);
      if (ret > 0) {
        bytes_read += ret;
      }

      if (ret < actual) {
        /* short read */
        break;
      }

      req -= actual;
      offset += actual;
      ptr = (void *) ((intptr_t) ptr + actual);
    } while (req);

    if (req || HIO_SUCCESS != rc) {
      break;
    }

    ptr = (void *) ((intptr_t) ptr + stride);
  }

  if (0 == bytes_read || HIO_SUCCESS != rc) {
    if (0 == bytes_read && HIO_SUCCESS == rc) {
      rc = hioi_err_errno (errno);
    }

    return rc;
  }

  stop = hioi_gettime ();
  posix_dataset->base.ds_stat.s_rtime += stop - start;
  posix_dataset->base.ds_stat.s_bread += bytes_read;

  return bytes_read;
}
static int builtin_posix_element_translate_opt (builtin_posix_module_t *posix_module, hio_element_t element,
                                                uint64_t offset, size_t *size, hio_file_t **file_out,
                                                bool reading) {
  builtin_posix_module_dataset_t *posix_dataset = (builtin_posix_module_dataset_t *) hioi_element_dataset (element);
  hio_context_t context = hioi_object_context (&element->e_object);
  hio_file_t *file;
  uint64_t file_offset;
  int file_index = 0;
  char *path;
  int rc;

  hioi_log (context, HIO_VERBOSE_DEBUG_MED, "translating element %s offset %" PRIu64 " size %lu",
            hioi_object_identifier (&element->e_object), offset, *size);
  POSIX_TRACE_CALL(posix_dataset, rc = hioi_element_translate_offset (element, offset, &file_index, &file_offset, size),
                   "translate_offset", offset, *size);
#if HIO_MPI_HAVE(3)
  if (HIO_SUCCESS != rc && reading) {
    POSIX_TRACE_CALL(posix_dataset, rc = hioi_dataset_map_translate_offset (element, offset, &file_index, &file_offset, size),
                     "map_translate_offset", offset, *size);
  }
#endif

  if (HIO_SUCCESS != rc) {
    if (reading) {
      hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset %" PRIu64 " not found", offset);
      /* not found */
      return rc;
    }

    file_offset = builtin_posix_reserve (posix_dataset, size);

    if (hioi_context_using_mpi (context)) {
      file_index = posix_dataset->base.ds_shared_control->s_master;
    } else {
      file_index = 0;
    }

    rc = asprintf (&path, "%s/data/data.%x", posix_dataset->base_path, file_index);
    if (0 > rc) {
      return HIO_ERR_OUT_OF_RESOURCE;
    }

    hioi_element_add_segment (element, file_index, file_offset, offset, *size);
  } else {
    hioi_log (context, HIO_VERBOSE_DEBUG_MED, "offset found in file @ rank %d, offset %" PRIu64
              ", size %lu", file_index, file_offset, *size);
    rc = asprintf (&path, "%s/data/data.%x", posix_dataset->base_path, file_index);
    if (0 > rc) {
      return HIO_ERR_OUT_OF_RESOURCE;
    }

    if (access (path, R_OK)) {
      free (path);
      rc = asprintf (&path, "%s/data.%x", posix_dataset->base_path, file_index);
      if (0 > rc) {
        return HIO_ERR_OUT_OF_RESOURCE;
      }
    }
  }

  /* use crc as a hash to pick a file index to use */
  int internal_index = file_index % HIO_POSIX_MAX_OPEN_FILES;
  file = posix_dataset->files + internal_index;

  if (file_index != file->f_bid) {
    if (file->f_bid >= 0) {
      POSIX_TRACE_CALL(posix_dataset, hioi_file_close (file), "file_close", file->f_bid, 0);
    }

    file->f_bid = -1;

    POSIX_TRACE_CALL(posix_dataset, rc = builtin_posix_open_file (posix_module, posix_dataset, path, file),
                     "file_open", file_index, 0);
    if (HIO_SUCCESS != rc) {
      free (path);
      return rc;
    }

    file->f_bid = file_index;
  }

  free (path);

  POSIX_TRACE_CALL(posix_dataset, hioi_file_seek (file, file_offset, SEEK_SET), "file_seek", file->f_bid, file_offset);

  *file_out = file;

  return HIO_SUCCESS;
}