summaryrefslogtreecommitdiffstats
path: root/src/H5ES.c
blob: 2ba8a72eddd4eac8f64bdd2fa6254734b238fa61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*-------------------------------------------------------------------------
 *
 * Created:     H5ES.c
 *              Apr  6 2020
 *              Quincey Koziol
 *
 * Purpose:     Implements an "event set" for managing asynchronous
 *                      operations.
 *
 *                      Please see the asynchronous I/O RFC document
 *                      for a full description of how they work, etc.
 *
 *-------------------------------------------------------------------------
 */

/****************/
/* Module Setup */
/****************/

#include "H5ESmodule.h" /* This source code file is part of the H5ES module */

/***********/
/* Headers */
/***********/
#include "H5private.h"   /* Generic Functions			*/
#include "H5Eprivate.h"  /* Error handling		  	*/
#include "H5ESpkg.h"     /* Event Sets                           */
#include "H5FLprivate.h" /* Free Lists                           */
#include "H5Iprivate.h"  /* IDs                                  */

/****************/
/* Local Macros */
/****************/

/******************/
/* Local Typedefs */
/******************/

/********************/
/* Package Typedefs */
/********************/

/********************/
/* Local Prototypes */
/********************/

/*********************/
/* Package Variables */
/*********************/

/*****************************/
/* Library Private Variables */
/*****************************/

/*******************/
/* Local Variables */
/*******************/

/*-------------------------------------------------------------------------
 * Function:    H5EScreate
 *
 * Purpose:     Creates an event set.
 *
 * Return:      Success:    An ID for the event set
 *              Failure:    H5I_INVALID_HID
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, April 8, 2020
 *
 *-------------------------------------------------------------------------
 */
hid_t
H5EScreate(void)
{
    H5ES_t *es;                          /* Pointer to event set object */
    hid_t   ret_value = H5I_INVALID_HID; /* Return value */

    FUNC_ENTER_API(H5I_INVALID_HID)
    H5TRACE0("i", "");

    /* Create the new event set object */
    if (NULL == (es = H5ES__create()))
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, H5I_INVALID_HID, "can't create event set")

    /* Register the new event set to get an ID for it */
    if ((ret_value = H5I_register(H5I_EVENTSET, es, TRUE)) < 0)
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register event set")

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5EScreate() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_count
 *
 * Purpose:     Retrieve the # of events in an event set
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, April 8, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_count(hid_t es_id, size_t *count /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "ix", es_id, count);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")

    /* Retrieve the count, if non-NULL */
    if (count)
        *count = H5ES__list_count(&es->active);

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESget_count() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_op_counter
 *
 * Purpose:     Retrieve the counter that will be assigned to the next operation
 *              inserted into the event set.
 *
 * Note:        This is designed for wrapper libraries mainly, to use as a
 *              mechanism for matching operations inserted into the event
 *              set with [possible] errors that occur.
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Fiiday, November 6, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_op_counter(hid_t es_id, uint64_t *op_counter /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "ix", es_id, op_counter);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")

    /* Retrieve the operation counter, if non-NULL */
    if (op_counter)
        *op_counter = es->op_counter;

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESget_op_counter() */

/*-------------------------------------------------------------------------
 * Function:    H5ESwait
 *
 * Purpose:     Wait (with timeout) for operations in event set to complete
 *
 * Note:        Timeout value is in ns, and is for the H5ESwait call, not each
 *              individual operation.   For example: if '10' is passed as
 *              a timeout value and the event set waited 4ns for the first
 *              operation to complete, the remaining operations would be
 *              allowed to wait for at most 6ns more.  i.e. the timeout value
 *              is "used up" across all operations, until it reaches 0, then
 *              any remaining operations are only checked for completion, not
 *              waited on.
 *
 * Note:        This call will stop waiting on operations and will return
 *              immediately if an operation fails.  If a failure occurs, the
 *              value returned for the # of operations in progress may be
 *              inaccurate.
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Monday, July 13, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESwait(hid_t es_id, uint64_t timeout, size_t *num_in_progress /*out*/, hbool_t *op_failed /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE4("e", "iULxx", es_id, timeout, num_in_progress, op_failed);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")
    if (NULL == num_in_progress)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL num_in_progress pointer")
    if (NULL == op_failed)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL op_failed pointer")

    /* Wait for operations */
    if (H5ES__wait(es, timeout, num_in_progress, op_failed) < 0)
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTWAIT, FAIL, "can't wait on operations")

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESwait() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_err_status
 *
 * Purpose:     Check if event set has failed operations
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Thursday, October 15, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_err_status(hid_t es_id, hbool_t *err_status /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "ix", es_id, err_status);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")

    /* Retrieve the error flag, if non-NULL */
    if (err_status)
        *err_status = es->err_occurred;

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESget_err_status() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_err_count
 *
 * Purpose:     Retrieve # of failed operations
 *
 * Note:        Does not wait for active operations to complete, so count may
 *              not include all failures.
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Thursday, October 15, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_err_count(hid_t es_id, size_t *num_errs /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "ix", es_id, num_errs);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")

    /* Retrieve the error flag, if non-NULL */
    if (num_errs) {
        if (es->err_occurred)
            *num_errs = H5ES__list_count(&es->failed);
        else
            *num_errs = 0;
    } /* end if */

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESget_err_count() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_err_info
 *
 * Purpose:     Retrieve information about failed operations
 *
 * Note:        The strings retrieved for each error info must be released
 *              by calling H5free_memory().
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Friday, November 6, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_err_info(hid_t es_id, size_t num_err_info, H5ES_err_info_t err_info[] /*out*/,
                 size_t *num_cleared /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE4("e", "izxx", es_id, num_err_info, err_info, num_cleared);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier")
    if (0 == num_err_info)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "err_info array size is 0")
    if (NULL == err_info)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL err_info array pointer")
    if (NULL == num_cleared)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL errors cleared pointer")

    /* Retrieve the error information */
    if (H5ES__get_err_info(es, num_err_info, err_info, num_cleared) < 0)
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't retrieve error info for failed operation(s)")

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESget_err_info() */

/*-------------------------------------------------------------------------
 * Function:    H5ESclose
 *
 * Purpose:     Closes an event set.
 *
 * Note:        Fails if active operations are present.
 *
 * Return:      SUCCEED / FAIL
 *
 * Programmer:  Quincey Koziol
 *              Wednesday, April 8, 2020
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESclose(hid_t es_id)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE1("e", "i", es_id);

    /* Check arguments */
    if (H5I_EVENTSET != H5I_get_type(es_id))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event set")

    /*
     * Decrement the counter on the object.  It will be freed if the count
     * reaches zero.
     */
    if (H5I_dec_app_ref(es_id) < 0)
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "unable to decrement ref count on event set")

done:
    FUNC_LEAVE_API(ret_value)
} /* end H5ESclose() */