summaryrefslogtreecommitdiffstats
path: root/src/H5ES.c
blob: 24452f9a3d4be4518df67ad3534d9ed02a70bfd6 (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
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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
 *
 * 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                                  */
#include "H5MMprivate.h" /* Memory management                    */

/****************/
/* 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
 *
 *-------------------------------------------------------------------------
 */
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:    H5ESinsert_request
 *
 * Purpose:     Insert a request from a VOL connector into an event set.
 *
 * Note:        This function is primarily targeted at VOL connector
 *              authors and is _not_ designed for general-purpose application use.
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESinsert_request(hid_t es_id, hid_t connector_id, void *request)
{
    H5ES_t *es;                  /* Event set */
    H5VL_t *connector = NULL;    /* VOL connector */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "ii*x", es_id, connector_id, request);

    /* 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 == request)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL request pointer");

    /* Create new VOL connector object, using the connector ID */
    if (NULL == (connector = H5VL_new_connector(connector_id)))
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, FAIL, "can't create VOL connector object");

    /* Insert request into event set */
    if (H5ES__insert_request(es, connector, request) < 0)
        HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "can't insert request into event set");

done:
    /* Clean up on error */
    if (ret_value < 0)
        /* Release newly created connector */
        if (connector && H5VL_conn_dec_rc(connector) < 0)
            HDONE_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "unable to decrement ref count on VOL connector");

    FUNC_LEAVE_API(ret_value)
} /* end H5ESinsert_request() */

/*-------------------------------------------------------------------------
 * Function:    H5ESget_count
 *
 * Purpose:     Retrieve the # of events in an event set
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_count(hid_t es_id, size_t *count /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "i*z", es_id, count);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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);
    } /* end if */

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.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_op_counter(hid_t es_id, uint64_t *op_counter /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "i*UL", es_id, op_counter);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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;
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESget_requests
 *
 * Purpose:     Retrieve the requests in an event set.  Up to *count
 *              requests are stored in the provided requests array, and
 *              the connector ids corresponding to these requests are
 *              stored in the provided connector_ids array.  Either or
 *              both of these arrays may be NULL, in which case this
 *              information is not returned.  If these arrays are
 *              non-NULL, they must be large enough to contain *count
 *              entries.  On exit, *count is set to the total number of
 *              events in the event set.
 *
 *              Events are returned in the order they were added to the
 *              event set.  If order is H5_ITER_INC or H5_ITER_NATIVE,
 *              events will be returned starting from the oldest. If order
 *              is H5_ITER_DEC, events will be returned starting with the
 *              newest/most recent.
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_requests(hid_t es_id, H5_iter_order_t order, hid_t *connector_ids, void **requests, size_t array_len,
                 size_t *count /*out*/)
{
    H5ES_t *es;                  /* Event set */
    herr_t  ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE6("e", "iIo*i**xz*z", es_id, order, connector_ids, requests, array_len, count);

    /* Check arguments */
    if (NULL == (es = H5I_object_verify(es_id, H5I_EVENTSET)))
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid event set identifier");
    if (order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified");

    /* Call internal routine */
    if (array_len > 0 && (requests || connector_ids))
        if (H5ES__get_requests(es, order, connector_ids, requests, array_len) < 0)
            HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't get requests");

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

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

/*-------------------------------------------------------------------------
 * 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.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESwait(hid_t es_id, uint64_t timeout, size_t *num_in_progress /*out*/, hbool_t *op_failed /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE4("e", "iUL*z*b", es_id, timeout, num_in_progress, op_failed);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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");
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5EScancel
 *
 * Purpose:     Attempt to cancel operations in an event set
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5EScancel(hid_t es_id, size_t *num_not_canceled /*out*/, hbool_t *op_failed /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "i*z*b", es_id, num_not_canceled, op_failed);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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_not_canceled)
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL num_not_canceled pointer");
        if (NULL == op_failed)
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL op_failed pointer");

        /* Cancel operations */
        if (H5ES__cancel(es, num_not_canceled, op_failed) < 0)
            HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCANCEL, FAIL, "can't cancel operations");
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESget_err_status
 *
 * Purpose:     Check if event set has failed operations
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_err_status(hid_t es_id, hbool_t *err_status /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "i*b", es_id, err_status);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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;
    } /* end if */

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.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESget_err_count(hid_t es_id, size_t *num_errs /*out*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "i*z", es_id, num_errs);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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 */
    }     /* 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().
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
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*/)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE4("e", "iz*#*z", es_id, num_err_info, err_info, num_cleared);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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)");
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESfree_err_info
 *
 * Purpose:     Convenience routine to free 1+ H5ES_err_info_t structs.
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESfree_err_info(size_t num_err_info, H5ES_err_info_t err_info[])
{
    size_t u;                   /* Local index variable */
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE2("e", "z*#", num_err_info, err_info);

    /* Check arguments */
    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");

    /* Iterate over array, releasing error information */
    for (u = 0; u < num_err_info; u++) {
        H5MM_xfree(err_info[u].api_name);
        H5MM_xfree(err_info[u].api_args);
        H5MM_xfree(err_info[u].app_file_name);
        H5MM_xfree(err_info[u].app_func_name);
        if (H5I_dec_app_ref(err_info[u].err_stack_id) < 0)
            HGOTO_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, "can't close error stack for err_info #%zu", u);
    } /* end for */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESregister_insert_func
 *
 * Purpose:     Registers a callback to invoke when a new operation is inserted
 *              into an event set.
 *
 * Note:        Only one insert callback can be registered for each event set.
 *              Registering a new callback will replace the existing one.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESregister_insert_func(hid_t es_id, H5ES_event_insert_func_t func, void *ctx)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "iEI*x", es_id, func, ctx);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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 == func)
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL function callback pointer");

        /* Set the event set's insert callback */
        es->ins_func = func;
        es->ins_ctx  = ctx;
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESregister_complete_func
 *
 * Purpose:     Registers a callback to invoke when an operation completes
 *              within an event set.
 *
 * Note:        Only one complete callback can be registered for each event set.
 *              Registering a new callback will replace the existing one.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESregister_complete_func(hid_t es_id, H5ES_event_complete_func_t func, void *ctx)
{
    herr_t ret_value = SUCCEED; /* Return value */

    FUNC_ENTER_API(FAIL)
    H5TRACE3("e", "iEC*x", es_id, func, ctx);

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != es_id) {
        H5ES_t *es; /* Event set */

        /* 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 == func)
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL function callback pointer");

        /* Set the event set's completion callback */
        es->comp_func = func;
        es->comp_ctx  = ctx;
    } /* end if */

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

/*-------------------------------------------------------------------------
 * Function:    H5ESclose
 *
 * Purpose:     Closes an event set.
 *
 * Note:        Fails if active operations are present.
 *
 * Note:        H5ES_NONE is a valid value for 'es_id', but functions as a no-op
 *
 * Return:      SUCCEED / FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5ESclose(hid_t es_id)
{
    herr_t ret_value = SUCCEED; /* Return value */

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

    /* Passing H5ES_NONE is valid, but a no-op */
    if (H5ES_NONE != 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");
    } /* end if */

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