#include "H5FDdrvr_module.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5FDprivate.h"
#include "H5FDros3.h"
#include "H5FLprivate.h"
#include "H5Iprivate.h"
#include "H5MMprivate.h"
#include "H5FDs3comms.h"
#ifdef H5_HAVE_ROS3_VFD
#define ROS3_DEBUG 0
#define ROS3_STATS 0
static hid_t H5FD_ROS3_g = 0;
#if ROS3_STATS
#define ROS3_STATS_STARTING_MIN 0xfffffffful
#define ROS3_STATS_BASE 2
#define ROS3_STATS_INTERVAL 1
#define ROS3_STATS_START_POWER 10
#define ROS3_STATS_BIN_COUNT 16
#define ROS3_STATS_POW(bin_i, out_ptr) { \
unsigned long long donotshadowresult = 1; \
unsigned donotshadowindex = 0; \
for (donotshadowindex = 0; \
donotshadowindex < (((bin_i) * ROS3_STATS_INTERVAL) + \
ROS3_STATS_START_POWER); \
donotshadowindex++) \
{ \
donotshadowresult *= ROS3_STATS_BASE; \
} \
*(out_ptr) = donotshadowresult; \
}
static unsigned long long ros3_stats_boundaries[ROS3_STATS_BIN_COUNT];
typedef struct {
unsigned long long count;
unsigned long long bytes;
unsigned long long min;
unsigned long long max;
} ros3_statsbin;
#endif
typedef struct H5FD_ros3_t {
H5FD_t pub;
H5FD_ros3_fapl_t fa;
haddr_t eoa;
s3r_t *s3r_handle;
#if ROS3_STATS
ros3_statsbin meta[ROS3_STATS_BIN_COUNT + 1];
ros3_statsbin raw[ROS3_STATS_BIN_COUNT + 1];
#endif
} H5FD_ros3_t;
#define MAXADDR (((haddr_t)1 << (8 * sizeof(HDoff_t) - 1)) - 1)
#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
static herr_t H5FD__ros3_term(void);
static void *H5FD__ros3_fapl_get(H5FD_t *_file);
static void *H5FD__ros3_fapl_copy(const void *_old_fa);
static herr_t H5FD__ros3_fapl_free(void *_fa);
static H5FD_t *H5FD__ros3_open(const char *name, unsigned flags, hid_t fapl_id,
haddr_t maxaddr);
static herr_t H5FD__ros3_close(H5FD_t *_file);
static int H5FD__ros3_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
static herr_t H5FD__ros3_query(const H5FD_t *_f1, unsigned long *flags);
static haddr_t H5FD__ros3_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD__ros3_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
static haddr_t H5FD__ros3_get_eof(const H5FD_t *_file, H5FD_mem_t type);
static herr_t H5FD__ros3_get_handle(H5FD_t *_file, hid_t fapl,
void** file_handle);
static herr_t H5FD__ros3_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
haddr_t addr, size_t size, void *buf);
static herr_t H5FD__ros3_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id,
haddr_t addr, size_t size, const void *buf);
static herr_t H5FD__ros3_truncate(H5FD_t *_file, hid_t dxpl_id,
hbool_t closing);
static herr_t H5FD__ros3_lock(H5FD_t *_file, hbool_t rw);
static herr_t H5FD__ros3_unlock(H5FD_t *_file);
static herr_t H5FD__ros3_validate_config(const H5FD_ros3_fapl_t * fa);
static const H5FD_class_t H5FD_ros3_g = {
"ros3",
MAXADDR,
H5F_CLOSE_WEAK,
H5FD__ros3_term,
NULL,
NULL,
NULL,
sizeof(H5FD_ros3_fapl_t),
H5FD__ros3_fapl_get,
H5FD__ros3_fapl_copy,
H5FD__ros3_fapl_free,
0,
NULL,
NULL,
H5FD__ros3_open,
H5FD__ros3_close,
H5FD__ros3_cmp,
H5FD__ros3_query,
NULL,
NULL,
NULL,
H5FD__ros3_get_eoa,
H5FD__ros3_set_eoa,
H5FD__ros3_get_eof,
H5FD__ros3_get_handle,
H5FD__ros3_read,
H5FD__ros3_write,
NULL,
H5FD__ros3_truncate,
H5FD__ros3_lock,
H5FD__ros3_unlock,
H5FD_FLMAP_DICHOTOMY
};
H5FL_DEFINE_STATIC(H5FD_ros3_t);
static herr_t
H5FD__init_package(void)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
if(H5FD_ros3_init() < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to initialize ros3 VFD")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
hid_t
H5FD_ros3_init(void)
{
hid_t ret_value = H5I_INVALID_HID;
#if ROS3_STATS
unsigned int bin_i;
#endif
FUNC_ENTER_NOAPI(FAIL)
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD_ros3_init() called.\n");
#endif
if(H5I_VFL != H5I_get_type(H5FD_ROS3_g))
H5FD_ROS3_g = H5FD_register(&H5FD_ros3_g, sizeof(H5FD_class_t), FALSE);
#if ROS3_STATS
for (bin_i = 0; bin_i < ROS3_STATS_BIN_COUNT; bin_i++) {
unsigned long long value = 0;
ROS3_STATS_POW(bin_i, &value)
ros3_stats_boundaries[bin_i] = value;
}
#endif
ret_value = H5FD_ROS3_g;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_term(void)
{
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_term() called.\n");
#endif
H5FD_ROS3_g = 0;
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5Pset_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa)
{
H5P_genplist_t *plist = NULL;
herr_t ret_value = FAIL;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, fa);
HDassert(fa != NULL);
#if ROS3_DEBUG
HDfprintf(stdout, "H5Pset_fapl_ros3() called.\n");
#endif
plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
if(plist == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
if(FAIL == H5FD__ros3_validate_config(fa))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid ros3 config")
ret_value = H5P_set_driver(plist, H5FD_ROS3, (void *)fa);
done:
FUNC_LEAVE_API(ret_value)
}
static herr_t
H5FD__ros3_validate_config(const H5FD_ros3_fapl_t * fa)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
HDassert(fa != NULL);
if(fa->version != H5FD_CURR_ROS3_FAPL_T_VERSION)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unknown H5FD_ros3_fapl_t version");
if(fa->authenticate == TRUE)
if((fa->aws_region[0] == '\0') || (fa->secret_id[0] == '\0'))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Inconsistent authentication information");
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5Pget_fapl_ros3(hid_t fapl_id, H5FD_ros3_fapl_t *fa_out)
{
const H5FD_ros3_fapl_t *fa = NULL;
H5P_genplist_t *plist = NULL;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(FAIL)
H5TRACE2("e", "i*x", fapl_id, fa_out);
#if ROS3_DEBUG
HDfprintf(stdout, "H5Pget_fapl_ros3() called.\n");
#endif
if(fa_out == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "fa_out is NULL")
plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
if(plist == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
if(H5FD_ROS3 != H5P_peek_driver(plist))
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
fa = (const H5FD_ros3_fapl_t *)H5P_peek_driver_info(plist);
if(fa == NULL)
HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
HDmemcpy(fa_out, fa, sizeof(H5FD_ros3_fapl_t));
done:
FUNC_LEAVE_API(ret_value)
}
static void *
H5FD__ros3_fapl_get(H5FD_t *_file)
{
H5FD_ros3_t *file = (H5FD_ros3_t*)_file;
H5FD_ros3_fapl_t *fa = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
fa = (H5FD_ros3_fapl_t *)H5MM_calloc(sizeof(H5FD_ros3_fapl_t));
if(fa == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
HDmemcpy(fa, &(file->fa), sizeof(H5FD_ros3_fapl_t));
ret_value = fa;
done:
if(ret_value == NULL)
if(fa != NULL)
H5MM_xfree(fa);
FUNC_LEAVE_NOAPI(ret_value)
}
static void *
H5FD__ros3_fapl_copy(const void *_old_fa)
{
const H5FD_ros3_fapl_t *old_fa = (const H5FD_ros3_fapl_t*)_old_fa;
H5FD_ros3_fapl_t *new_fa = NULL;
void *ret_value = NULL;
FUNC_ENTER_STATIC
new_fa = (H5FD_ros3_fapl_t *)H5MM_malloc(sizeof(H5FD_ros3_fapl_t));
if(new_fa == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed");
HDmemcpy(new_fa, old_fa, sizeof(H5FD_ros3_fapl_t));
ret_value = new_fa;
done:
if(ret_value == NULL)
if(new_fa != NULL)
H5MM_xfree(new_fa);
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_fapl_free(void *_fa)
{
H5FD_ros3_fapl_t *fa = (H5FD_ros3_fapl_t*)_fa;
FUNC_ENTER_STATIC_NOERR
HDassert(fa != NULL);
H5MM_xfree(fa);
FUNC_LEAVE_NOAPI(SUCCEED)
}
#if ROS3_STATS
static herr_t
ros3_reset_stats(H5FD_ros3_t *file)
{
unsigned i = 0;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDprintf("ros3_reset_stats() called\n");
#endif
if(file == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file was null");
for(i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
file->raw[i].bytes = 0;
file->raw[i].count = 0;
file->raw[i].min = (unsigned long long)ROS3_STATS_STARTING_MIN;
file->raw[i].max = 0;
file->meta[i].bytes = 0;
file->meta[i].count = 0;
file->meta[i].min = (unsigned long long)ROS3_STATS_STARTING_MIN;
file->meta[i].max = 0;
}
done:
FUNC_LEAVE_NOAPI(ret_value);
}
#endif
static H5FD_t *
H5FD__ros3_open(const char *url, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
{
H5FD_ros3_t *file = NULL;
struct tm *now = NULL;
char iso8601now[ISO8601_SIZE];
unsigned char signing_key[SHA256_DIGEST_LENGTH];
s3r_t *handle = NULL;
H5FD_ros3_fapl_t fa;
H5FD_t *ret_value = NULL;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_open() called.\n");
#endif
HDcompile_assert(sizeof(HDoff_t) >= sizeof(size_t));
if(!url || !*url)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
if(0 == maxaddr || HADDR_UNDEF == maxaddr)
HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
if(ADDR_OVERFLOW(maxaddr))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr")
if(flags != H5F_ACC_RDONLY)
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, NULL, "only Read-Only access allowed")
if(FAIL == H5Pget_fapl_ros3(fapl_id, &fa))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "can't get property list")
if(CURLE_OK != curl_global_init(CURL_GLOBAL_DEFAULT))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to initialize curl global (placeholder flags)")
if(fa.authenticate == TRUE) {
now = gmnow();
HDassert( now != NULL );
if(ISO8601NOW(iso8601now, now) != (ISO8601_SIZE - 1))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "problem while writing iso8601 timestamp")
if(FAIL == H5FD_s3comms_signing_key(signing_key, (const char *)fa.secret_key,
(const char *)fa.aws_region, (const char *)iso8601now))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "problem while computing signing key")
handle = H5FD_s3comms_s3r_open( url, (const char *)fa.aws_region,
(const char *)fa.secret_id, (const unsigned char *)signing_key);
}
else
handle = H5FD_s3comms_s3r_open(url, NULL, NULL, NULL);
if(handle == NULL)
HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, NULL, "could not open");
file = H5FL_CALLOC(H5FD_ros3_t);
if(file == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
file->s3r_handle = handle;
HDmemcpy(&(file->fa), &fa, sizeof(H5FD_ros3_fapl_t));
#if ROS3_STATS
if(FAIL == ros3_reset_stats(file))
HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, NULL, "unable to reset file statistics")
#endif
ret_value = (H5FD_t*)file;
done:
if(ret_value == NULL) {
if(handle != NULL)
if(FAIL == H5FD_s3comms_s3r_close(handle))
HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "unable to close s3 file handle")
if(file != NULL)
file = H5FL_FREE(H5FD_ros3_t, file);
curl_global_cleanup();
}
FUNC_LEAVE_NOAPI(ret_value)
}
#if ROS3_STATS
static herr_t
ros3_fprint_stats(FILE *stream, const H5FD_ros3_t *file)
{
herr_t ret_value = SUCCEED;
parsed_url_t *purl = NULL;
unsigned i = 0;
unsigned long count_meta = 0;
unsigned long count_raw = 0;
double average_meta = 0.0;
double average_raw = 0.0;
unsigned long long min_meta = (unsigned long long)ROS3_STATS_STARTING_MIN;
unsigned long long min_raw = (unsigned long long)ROS3_STATS_STARTING_MIN;
unsigned long long max_meta = 0;
unsigned long long max_raw = 0;
unsigned long long bytes_raw = 0;
unsigned long long bytes_meta = 0;
double re_dub = 0.0;
unsigned suffix_i = 0;
const char suffixes[] = { ' ', 'K', 'M', 'G', 'T', 'P' };
FUNC_ENTER_STATIC
if(stream == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file stream cannot be null" );
if(file == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file cannot be null");
if(file->s3r_handle == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "s3 request handle cannot be null");
if(file->s3r_handle->purl == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "parsed url structure cannot be null");
purl = file->s3r_handle->purl;
HDfprintf(stream, "stats for %s://%s", purl->scheme, purl->host);
if(purl->port != NULL && purl->port[0] != '\0')
HDfprintf(stream, ":%s", purl->port);
if(purl->query != NULL && purl->query[0] != '\0') {
if (purl->path != NULL && purl->path[0] != '\0')
HDfprintf(stream, "/%s", purl->path);
else
HDfprintf(stream, "/");
HDfprintf(stream, "?%s", purl->query);
} else if (purl->path != NULL && purl->path[0] != '\0') {
HDfprintf(stream, "/%s", purl->path);
}
HDfprintf(stream, "\n");
for(i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
const ros3_statsbin *r = &file->raw[i];
const ros3_statsbin *m = &file->meta[i];
if(m->min < min_meta)
min_meta = m->min;
if(r->min < min_raw)
min_raw = r->min;
if(m->max > max_meta)
max_meta = m->max;
if(r->max > max_raw)
max_raw = r->max;
count_raw += r->count;
count_meta += m->count;
bytes_raw += r->bytes;
bytes_meta += m->bytes;
}
if(count_raw > 0)
average_raw = (double)bytes_raw / (double)count_raw;
if(count_meta > 0)
average_meta = (double)bytes_meta / (double)count_meta;
HDfprintf(stream, "TOTAL READS: %llu (%llu meta, %llu raw)\n",
count_raw + count_meta, count_meta, count_raw);
HDfprintf(stream, "TOTAL BYTES: %llu (%llu meta, %llu raw)\n",
bytes_raw + bytes_meta, bytes_meta, bytes_raw);
if(count_raw + count_meta == 0)
goto done;
HDfprintf(stream, "SIZES meta raw\n");
HDfprintf(stream, " min ");
if(count_meta == 0)
HDfprintf(stream, " 0.000 ");
else {
re_dub = (double)min_meta;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
}
if(count_raw == 0)
HDfprintf(stream, " 0.000 \n");
else {
re_dub = (double)min_raw;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
}
HDfprintf(stream, " avg ");
re_dub = (double)average_meta;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
re_dub = (double)average_raw;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
HDfprintf(stream, " max ");
re_dub = (double)max_meta;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c ", re_dub, suffixes[suffix_i]);
re_dub = (double)max_raw;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream, "%8.3lf%c\n", re_dub, suffixes[suffix_i]);
HDfprintf(stream,
"BINS # of reads total bytes average size\n");
HDfprintf(stream,
" up-to meta raw meta raw meta raw\n");
for(i = 0; i <= ROS3_STATS_BIN_COUNT; i++) {
const ros3_statsbin *m;
const ros3_statsbin *r;
unsigned long long range_end = 0;
char bm_suffix = ' ';
double bm_val = 0.0;
char br_suffix = ' ';
double br_val = 0.0;
char am_suffix = ' ';
double am_val = 0.0;
char ar_suffix = ' ';
double ar_val = 0.0;
m = &file->meta[i];
r = &file->raw[i];
if(r->count == 0 && m->count == 0)
continue;
range_end = ros3_stats_boundaries[i];
if(i == ROS3_STATS_BIN_COUNT) {
range_end = ros3_stats_boundaries[i-1];
HDfprintf(stream, ">");
}
else
HDfprintf(stream, " ");
bm_val = (double)m->bytes;
for(suffix_i = 0; bm_val >= 1024.0; suffix_i++)
bm_val /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
bm_suffix = suffixes[suffix_i];
br_val = (double)r->bytes;
for(suffix_i = 0; br_val >= 1024.0; suffix_i++)
br_val /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
br_suffix = suffixes[suffix_i];
if(m->count > 0)
am_val = (double)(m->bytes) / (double)(m->count);
for(suffix_i = 0; am_val >= 1024.0; suffix_i++)
am_val /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
am_suffix = suffixes[suffix_i];
if(r->count > 0)
ar_val = (double)(r->bytes) / (double)(r->count);
for(suffix_i = 0; ar_val >= 1024.0; suffix_i++)
ar_val /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
ar_suffix = suffixes[suffix_i];
re_dub = (double)range_end;
for(suffix_i = 0; re_dub >= 1024.0; suffix_i++)
re_dub /= 1024.0;
HDassert(suffix_i < sizeof(suffixes));
HDfprintf(stream,
" %8.3f%c %7d %7d %8.3f%c %8.3f%c %8.3f%c %8.3f%c\n",
re_dub, suffixes[suffix_i],
m->count,
r->count,
bm_val, bm_suffix,
br_val, br_suffix,
am_val, am_suffix,
ar_val, ar_suffix);
HDfflush(stream);
}
done:
FUNC_LEAVE_NOAPI(ret_value);
}
#endif
static herr_t
H5FD__ros3_close(H5FD_t H5_ATTR_UNUSED *_file)
{
H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_close() called.\n");
#endif
HDassert(file != NULL);
HDassert(file->s3r_handle != NULL);
if(FAIL == H5FD_s3comms_s3r_close(file->s3r_handle))
HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close S3 request handle")
#if ROS3_STATS
if(ros3_fprint_stats(stdout, file) == FAIL)
HGOTO_ERROR(H5E_INTERNAL, H5E_ERROR, FAIL, "problem while writing file statistics")
#endif
file = H5FL_FREE(H5FD_ros3_t, file);
done:
curl_global_cleanup();
FUNC_LEAVE_NOAPI(ret_value)
}
static int
H5FD__ros3_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
{
const H5FD_ros3_t *f1 = (const H5FD_ros3_t *)_f1;
const H5FD_ros3_t *f2 = (const H5FD_ros3_t *)_f2;
const parsed_url_t *purl1 = NULL;
const parsed_url_t *purl2 = NULL;
int ret_value = 0;
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_cmp() called.\n");
#endif
HDassert(f1->s3r_handle != NULL);
HDassert(f2->s3r_handle != NULL);
purl1 = (const parsed_url_t *)f1->s3r_handle->purl;
purl2 = (const parsed_url_t *)f2->s3r_handle->purl;
HDassert(purl1 != NULL);
HDassert(purl2 != NULL);
HDassert(purl1->scheme != NULL);
HDassert(purl2->scheme != NULL);
HDassert(purl1->host != NULL);
HDassert(purl2->host != NULL);
if(HDstrcmp(purl1->scheme, purl2->scheme))
HGOTO_DONE(-1)
if(HDstrcmp(purl1->host, purl2->host))
HGOTO_DONE(-1)
if(purl1->port && purl2->port) {
if(HDstrcmp(purl1->port, purl2->port))
HGOTO_DONE(-1)
}
else if(purl1->port)
HGOTO_DONE(-1)
else if(purl2->port)
HGOTO_DONE(-1)
if(purl1->path && purl2->path) {
if(HDstrcmp(purl1->path, purl2->path))
HGOTO_DONE(-1)
}
else if(purl1->path && !purl2->path)
HGOTO_DONE(-1)
else if(purl2->path && !purl1->path)
HGOTO_DONE(-1)
if(purl1->query && purl2->query) {
if(HDstrcmp(purl1->query, purl2->query))
HGOTO_DONE(-1)
}
else if(purl1->query && !purl2->query)
HGOTO_DONE(-1)
else if(purl2->query && !purl1->query)
HGOTO_DONE(-1)
if(f1->fa.aws_region[0] != '\0' && f2->fa.aws_region[0] != '\0') {
if(HDstrcmp(f1->fa.aws_region, f2->fa.aws_region))
HGOTO_DONE(-1)
}
else if(f1->fa.aws_region[0] != '\0')
HGOTO_DONE(-1)
else if(f2->fa.aws_region[0] != '\0')
HGOTO_DONE(-1)
if(f1->fa.secret_id[0] != '\0' && f2->fa.secret_id[0] != '\0') {
if(HDstrcmp(f1->fa.secret_id, f2->fa.secret_id))
HGOTO_DONE(-1)
}
else if(f1->fa.secret_id[0] != '\0')
HGOTO_DONE(-1)
else if(f2->fa.secret_id[0] != '\0')
HGOTO_DONE(-1)
if(f1->fa.secret_key[0] != '\0' && f2->fa.secret_key[0] != '\0') {
if(HDstrcmp(f1->fa.secret_key, f2->fa.secret_key))
HGOTO_DONE(-1)
}
else if(f1->fa.secret_key[0] != '\0')
HGOTO_DONE(-1)
else if(f2->fa.secret_key[0] != '\0')
HGOTO_DONE(-1)
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags)
{
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_query() called.\n");
#endif
if(flags) {
*flags = 0;
*flags |= H5FD_FEAT_DATA_SIEVE;
}
FUNC_LEAVE_NOAPI(SUCCEED)
}
static haddr_t
H5FD__ros3_get_eoa(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
const H5FD_ros3_t *file = (const H5FD_ros3_t *)_file;
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_get_eoa() called.\n");
#endif
FUNC_LEAVE_NOAPI(file->eoa)
}
static herr_t
H5FD__ros3_set_eoa(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type, haddr_t addr)
{
H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_set_eoa() called.\n");
#endif
file->eoa = addr;
FUNC_LEAVE_NOAPI(SUCCEED)
}
static haddr_t
H5FD__ros3_get_eof(const H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type)
{
const H5FD_ros3_t *file = (const H5FD_ros3_t *)_file;
FUNC_ENTER_STATIC_NOERR
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_get_eof() called.\n");
#endif
FUNC_LEAVE_NOAPI(H5FD_s3comms_s3r_get_filesize(file->s3r_handle))
}
static herr_t
H5FD__ros3_get_handle(H5FD_t *_file, hid_t H5_ATTR_UNUSED fapl,
void **file_handle)
{
H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_get_handle() called.\n");
#endif
if(!file_handle)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
*file_handle = file->s3r_handle;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_read(H5FD_t *_file, H5FD_mem_t H5_ATTR_UNUSED type,
hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size,
void *buf)
{
H5FD_ros3_t *file = (H5FD_ros3_t *)_file;
size_t filesize = 0;
herr_t ret_value = SUCCEED;
#if ROS3_STATS
ros3_statsbin *bin = NULL;
unsigned bin_i = 0;
#endif
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_read() called.\n");
#endif
HDassert(file != NULL);
HDassert(file->s3r_handle != NULL);
HDassert(buf != NULL);
filesize = H5FD_s3comms_s3r_get_filesize(file->s3r_handle);
if((addr > filesize) || ((addr + size) > filesize))
HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "range exceeds file address")
if(H5FD_s3comms_s3r_read(file->s3r_handle, addr, size, buf) == FAIL)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "unable to execute read")
#if ROS3_STATS
for(bin_i = 0; bin_i < ROS3_STATS_BIN_COUNT; bin_i++)
if((unsigned long long)size < ros3_stats_boundaries[bin_i])
break;
bin = (type == H5FD_MEM_DRAW)
? &file->raw[bin_i]
: &file->meta[bin_i];
if(bin->count == 0) {
bin->min = size;
bin->max = size;
}
else {
if(size < bin->min)
bin->min = size;
if(size > bin->max)
bin->max = size;
}
bin->count++;
bin->bytes += (unsigned long long)size;
#endif
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_write(H5FD_t H5_ATTR_UNUSED *_file, H5FD_mem_t H5_ATTR_UNUSED type,
hid_t H5_ATTR_UNUSED dxpl_id, haddr_t H5_ATTR_UNUSED addr,
size_t H5_ATTR_UNUSED size, const void H5_ATTR_UNUSED *buf)
{
herr_t ret_value = FAIL;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_write() called.\n");
#endif
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "cannot write to read-only file.")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_truncate(H5FD_t H5_ATTR_UNUSED *_file, hid_t H5_ATTR_UNUSED dxpl_id,
hbool_t H5_ATTR_UNUSED closing)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_STATIC
#if ROS3_DEBUG
HDfprintf(stdout, "H5FD__ros3_truncate() called.\n");
#endif
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "cannot truncate read-only file.")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5FD__ros3_lock(H5FD_t H5_ATTR_UNUSED *_file,
hbool_t H5_ATTR_UNUSED rw)
{
FUNC_ENTER_STATIC_NOERR
FUNC_LEAVE_NOAPI(SUCCEED)
}
static herr_t
H5FD__ros3_unlock(H5FD_t H5_ATTR_UNUSED *_file)
{
FUNC_ENTER_STATIC_NOERR
FUNC_LEAVE_NOAPI(SUCCEED)
}
#endif