From 0a8606780ddbb0bd871f228f26f6639943664463 Mon Sep 17 00:00:00 2001 From: Matthew Larson Date: Mon, 16 Oct 2023 11:00:05 -0500 Subject: [PATCH] Allow decreasing extent, fail on non-chunked --- src/rest_vol_dataset.c | 62 +++++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/rest_vol_dataset.c b/src/rest_vol_dataset.c index 6908b6f2..716e6482 100644 --- a/src/rest_vol_dataset.c +++ b/src/rest_vol_dataset.c @@ -16,6 +16,7 @@ */ #include "rest_vol_dataset.h" +#include /* Set of callbacks for RV_parse_response() */ static herr_t RV_parse_dataset_creation_properties_callback(char *HTTP_response, void *callback_data_in, @@ -1405,6 +1406,7 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id int url_len = 0; hid_t dspace_id = H5I_INVALID_HID; hid_t new_dspace_id = H5I_INVALID_HID; + hid_t dcpl_id = H5I_INVALID_HID; hsize_t *old_extent = NULL; hsize_t *maxdims = NULL; upload_info uinfo; @@ -1423,8 +1425,9 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id switch (args->op_type) { /* H5Dset_extent */ case H5VL_DATASET_SET_EXTENT: - size_t ndims = 0; - hsize_t *new_extent = NULL; + int ndims = 0; + const hsize_t *new_extent = NULL; + H5D_layout_t layout = H5D_LAYOUT_ERROR; /* Check for write access */ if (!(dset->domain->u.file.intent & H5F_ACC_RDWR)) @@ -1463,7 +1466,7 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); - /* First, make a GET request for the dataset's shape to do some checks */ + /* First, make a GET request for the dataset's dataspace to do some checks */ if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPGET, 1)) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP GET request: %s", curl_err_buf); @@ -1492,11 +1495,33 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id FUNC_GOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "new dataset dimensions exceed maximum dimensions"); - /* HSDS limitation */ - for (size_t i = 0; i < (size_t)ndims; i++) - if (new_extent[i] < old_extent[i]) - FUNC_GOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, - "using H5Dset_extent to decrease dataset size is unsupported"); + /* Make request to dataset to check layout in DCPL */ + + memset(request_url, 0, URL_MAX_LENGTH); + + if ((url_len = snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s", base_URL, dset->URI)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, + "H5Dset_extent request URL size exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + + CURL_PERFORM(curl, H5E_DATASET, H5E_CANTGET, FAIL); + + if ((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0) + FUNC_GOTO_ERROR(H5E_PLIST, H5E_CANTCREATE, NULL, "can't create DCPL for dataset"); + + if (RV_parse_dataset_creation_properties_callback(response_buffer.buffer, NULL, &dcpl_id) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_PARSEERROR, FAIL, "can't parse DCPL of dataset"); + + if ((layout = H5Pget_layout(dcpl_id)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_PLIST, FAIL, "can't get layout from DCPL"); + + if (layout != H5D_CHUNKED) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "non-chunked datasets cannot be resized"); /* Construct JSON containing new dataset extent */ const char *fmt_string = "{" @@ -1510,7 +1535,7 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id /* N bytes needed to store an N digit number, * floor(log10) + 1 of an N digit number is >= N, * plus two bytes for space and comma characters in the list */ - size_t num_digits = 0; + double num_digits = 0; if (new_extent[i] == 0) { num_digits = 1; @@ -1519,7 +1544,7 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id num_digits = floor(log10((double)new_extent[i])); } - request_body_shape_size += num_digits + 1 + 2; + request_body_shape_size += (size_t)num_digits + 1 + 2; } if ((request_body = RV_malloc(request_body_shape_size + strlen(fmt_string) + 1)) == NULL) @@ -1553,6 +1578,20 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id uinfo.buffer_size = (size_t)strlen(request_body); uinfo.bytes_sent = 0; + /* Target dataset's shape URL */ + memset(request_url, 0, URL_MAX_LENGTH); + + if ((url_len = + snprintf(request_url, URL_MAX_LENGTH, "%s/datasets/%s/shape", base_URL, dset->URI)) < 0) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, "snprintf error"); + + if (url_len >= URL_MAX_LENGTH) + FUNC_GOTO_ERROR(H5E_DATASET, H5E_SYSERRSTR, FAIL, + "H5Dset_extent request URL size exceeded maximum URL size"); + + if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, request_url)) + FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set cURL request URL: %s", curl_err_buf); + /* Make PUT request to change dataset extent */ if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L)) FUNC_GOTO_ERROR(H5E_SYM, H5E_CANTSET, FAIL, "can't set up cURL to make HTTP PUT request: %s", @@ -1609,6 +1648,9 @@ RV_dataset_specific(void *obj, H5VL_dataset_specific_args_t *args, hid_t dxpl_id if ((ret_value < 0) && (new_dspace_id != H5I_INVALID_HID)) H5Sclose(new_dspace_id); + if (dcpl_id > 0) + H5Pclose(dcpl_id); + RV_free(old_extent); RV_free(request_body); RV_free(request_body_shape);