Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5ESint.c |
16 | | * |
17 | | * Purpose: Internal "event set" routines for managing asynchronous |
18 | | * operations. |
19 | | * |
20 | | * Please see the asynchronous I/O RFC document |
21 | | * for a full description of how they work, etc. |
22 | | * |
23 | | *------------------------------------------------------------------------- |
24 | | */ |
25 | | |
26 | | /****************/ |
27 | | /* Module Setup */ |
28 | | /****************/ |
29 | | |
30 | | #include "H5ESmodule.h" /* This source code file is part of the H5ES module */ |
31 | | |
32 | | /***********/ |
33 | | /* Headers */ |
34 | | /***********/ |
35 | | #include "H5private.h" /* Generic Functions */ |
36 | | #include "H5Eprivate.h" /* Error handling */ |
37 | | #include "H5ESpkg.h" /* Event Sets */ |
38 | | #include "H5FLprivate.h" /* Free Lists */ |
39 | | #include "H5Iprivate.h" /* IDs */ |
40 | | #include "H5MMprivate.h" /* Memory management */ |
41 | | #include "H5RSprivate.h" /* Reference-counted strings */ |
42 | | #include "H5VLprivate.h" /* Virtual Object Layer */ |
43 | | |
44 | | /****************/ |
45 | | /* Local Macros */ |
46 | | /****************/ |
47 | | |
48 | | /******************/ |
49 | | /* Local Typedefs */ |
50 | | /******************/ |
51 | | |
52 | | /* Callback context for get events operations */ |
53 | | typedef struct H5ES_get_requests_ctx_t { |
54 | | hid_t *connector_ids; /* Output buffer for list of connector IDs that match the above requests */ |
55 | | void **requests; /* Output buffer for list of requests in event set */ |
56 | | size_t array_len; /* Length of the above output buffers */ |
57 | | size_t i; /* Number of elements filled in output buffers */ |
58 | | } H5ES_get_requests_ctx_t; |
59 | | |
60 | | /* Callback context for wait operations */ |
61 | | typedef struct H5ES_wait_ctx_t { |
62 | | H5ES_t *es; /* Event set being operated on */ |
63 | | uint64_t timeout; /* Timeout for wait operation (in ns) */ |
64 | | size_t *num_in_progress; /* Count of # of operations that have not completed */ |
65 | | bool *op_failed; /* Flag to indicate an operation failed */ |
66 | | } H5ES_wait_ctx_t; |
67 | | |
68 | | /* Callback context for cancel operations */ |
69 | | typedef struct H5ES_cancel_ctx_t { |
70 | | H5ES_t *es; /* Event set being operated on */ |
71 | | size_t *num_not_canceled; /* Count of # of operations were not canceled */ |
72 | | bool *op_failed; /* Flag to indicate an operation failed */ |
73 | | } H5ES_cancel_ctx_t; |
74 | | |
75 | | /* Callback context for get error info (gei) operations */ |
76 | | typedef struct H5ES_gei_ctx_t { |
77 | | H5ES_t *es; /* Event set being operated on */ |
78 | | size_t num_err_info; /* # of elements in err_info[] array */ |
79 | | size_t curr_err; /* Index of current error in array */ |
80 | | H5ES_err_info_t *curr_err_info; /* Pointer to current element in err_info[] array */ |
81 | | } H5ES_gei_ctx_t; |
82 | | |
83 | | /********************/ |
84 | | /* Package Typedefs */ |
85 | | /********************/ |
86 | | |
87 | | /********************/ |
88 | | /* Local Prototypes */ |
89 | | /********************/ |
90 | | static herr_t H5ES__close(H5ES_t *es); |
91 | | static herr_t H5ES__close_cb(void *es, void **request_token); |
92 | | static herr_t H5ES__insert(H5ES_t *es, H5VL_connector_t *connector, void *request_token, const char *app_file, |
93 | | const char *app_func, unsigned app_line, const char *caller, const char *api_args); |
94 | | static int H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx); |
95 | | static herr_t H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev); |
96 | | static herr_t H5ES__op_complete(H5ES_t *es, H5ES_event_t *ev, H5VL_request_status_t ev_status); |
97 | | static int H5ES__wait_cb(H5ES_event_t *ev, void *_ctx); |
98 | | static int H5ES__cancel_cb(H5ES_event_t *ev, void *_ctx); |
99 | | static int H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx); |
100 | | static int H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx); |
101 | | |
102 | | /*********************/ |
103 | | /* Package Variables */ |
104 | | /*********************/ |
105 | | |
106 | | /* Package initialization variable */ |
107 | | bool H5_PKG_INIT_VAR = false; |
108 | | |
109 | | /*****************************/ |
110 | | /* Library Private Variables */ |
111 | | /*****************************/ |
112 | | |
113 | | /*******************/ |
114 | | /* Local Variables */ |
115 | | /*******************/ |
116 | | |
117 | | /* Event Set ID class */ |
118 | | static const H5I_class_t H5I_EVENTSET_CLS[1] = {{ |
119 | | H5I_EVENTSET, /* ID class value */ |
120 | | 0, /* Class flags */ |
121 | | 0, /* # of reserved IDs for class */ |
122 | | (H5I_free_t)H5ES__close_cb /* Callback routine for closing objects of this class */ |
123 | | }}; |
124 | | |
125 | | /* Declare a static free list to manage H5ES_t structs */ |
126 | | H5FL_DEFINE_STATIC(H5ES_t); |
127 | | |
128 | | /*------------------------------------------------------------------------- |
129 | | * Function: H5ES__init_package |
130 | | * |
131 | | * Purpose: Initializes any interface-specific data or routines. |
132 | | * |
133 | | * Return: Non-negative on success / Negative on failure |
134 | | * |
135 | | * Purpose: Initialize the interface from some other layer. |
136 | | * |
137 | | *------------------------------------------------------------------------- |
138 | | */ |
139 | | herr_t |
140 | | H5ES__init_package(void) |
141 | 0 | { |
142 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
143 | |
|
144 | 0 | FUNC_ENTER_PACKAGE |
145 | | |
146 | | /* Initialize the ID group for the event set IDs */ |
147 | 0 | if (H5I_register_type(H5I_EVENTSET_CLS) < 0) |
148 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINIT, FAIL, "unable to initialize interface"); |
149 | | |
150 | 0 | done: |
151 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
152 | 0 | } /* end H5ES__init_package() */ |
153 | | |
154 | | /*------------------------------------------------------------------------- |
155 | | * Function: H5ES_term_package |
156 | | * |
157 | | * Purpose: Terminate this interface. |
158 | | * |
159 | | * Return: Success: Positive if anything is done that might |
160 | | * affect other interfaces; zero otherwise. |
161 | | * Failure: Negative |
162 | | * |
163 | | *------------------------------------------------------------------------- |
164 | | */ |
165 | | int |
166 | | H5ES_term_package(void) |
167 | 101 | { |
168 | 101 | int n = 0; |
169 | | |
170 | 101 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
171 | |
|
172 | 0 | if (H5_PKG_INIT_VAR) { |
173 | | /* Destroy the event set ID group */ |
174 | 0 | n += (H5I_dec_type_ref(H5I_EVENTSET) > 0); |
175 | | |
176 | | /* Mark closed */ |
177 | 0 | if (0 == n) |
178 | 0 | H5_PKG_INIT_VAR = false; |
179 | 0 | } /* end if */ |
180 | |
|
181 | 0 | FUNC_LEAVE_NOAPI(n) |
182 | 101 | } /* end H5ES_term_package() */ |
183 | | |
184 | | /*------------------------------------------------------------------------- |
185 | | * Function: H5ES__close_cb |
186 | | * |
187 | | * Purpose: Called when the ref count reaches zero on an event set's ID |
188 | | * |
189 | | * Return: SUCCEED / FAIL |
190 | | * |
191 | | *------------------------------------------------------------------------- |
192 | | */ |
193 | | static herr_t |
194 | | H5ES__close_cb(void *_es, void H5_ATTR_UNUSED **rt) |
195 | 0 | { |
196 | 0 | H5ES_t *es = (H5ES_t *)_es; /* The event set to close */ |
197 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
198 | |
|
199 | 0 | FUNC_ENTER_PACKAGE |
200 | | |
201 | | /* Sanity check */ |
202 | 0 | assert(es); |
203 | | |
204 | | /* Close the event set object */ |
205 | 0 | if (H5ES__close(es) < 0) |
206 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CLOSEERROR, FAIL, "unable to close event set"); |
207 | | |
208 | 0 | done: |
209 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
210 | 0 | } /* end H5ES__close_cb() */ |
211 | | |
212 | | /*------------------------------------------------------------------------- |
213 | | * Function: H5ES__create |
214 | | * |
215 | | * Purpose: Private function to create an event set object |
216 | | * |
217 | | * Return: Success: Pointer to an event set struct |
218 | | * Failure: NULL |
219 | | * |
220 | | *------------------------------------------------------------------------- |
221 | | */ |
222 | | H5ES_t * |
223 | | H5ES__create(void) |
224 | 0 | { |
225 | 0 | H5ES_t *es = NULL; /* Pointer to event set */ |
226 | 0 | H5ES_t *ret_value = NULL; /* Return value */ |
227 | |
|
228 | 0 | FUNC_ENTER_PACKAGE |
229 | | |
230 | | /* Allocate space for new event set */ |
231 | 0 | if (NULL == (es = H5FL_CALLOC(H5ES_t))) |
232 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, NULL, "can't allocate event set object"); |
233 | | |
234 | | /* Set the return value */ |
235 | 0 | ret_value = es; |
236 | |
|
237 | 0 | done: |
238 | 0 | if (!ret_value) |
239 | 0 | if (es && H5ES__close(es) < 0) |
240 | 0 | HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, NULL, "unable to free event set"); |
241 | |
|
242 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
243 | 0 | } /* end H5ES__create() */ |
244 | | |
245 | | /*------------------------------------------------------------------------- |
246 | | * Function: H5ES__insert |
247 | | * |
248 | | * Purpose: Insert a request token into an event set |
249 | | * |
250 | | * Return: SUCCEED / FAIL |
251 | | * |
252 | | *------------------------------------------------------------------------- |
253 | | */ |
254 | | static herr_t |
255 | | H5ES__insert(H5ES_t *es, H5VL_connector_t *connector, void *request_token, const char *app_file, |
256 | | const char *app_func, unsigned app_line, const char *caller, const char *api_args) |
257 | 0 | { |
258 | 0 | H5ES_event_t *ev = NULL; /* Event for request */ |
259 | 0 | bool ev_inserted = false; /* Flag to indicate that event is in active list */ |
260 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
261 | |
|
262 | 0 | FUNC_ENTER_PACKAGE |
263 | | |
264 | | /* Sanity check */ |
265 | 0 | assert(es); |
266 | | |
267 | | /* Create new event */ |
268 | 0 | if (NULL == (ev = H5ES__event_new(connector, request_token))) |
269 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCREATE, FAIL, "can't create event object"); |
270 | | |
271 | | /* Copy the app source information */ |
272 | | /* The 'app_func' & 'app_file' strings are statically allocated (by the compiler) |
273 | | * there's no need to duplicate them. |
274 | | */ |
275 | 0 | ev->op_info.app_file_name = app_file; |
276 | 0 | ev->op_info.app_func_name = app_func; |
277 | 0 | ev->op_info.app_line_num = app_line; |
278 | | |
279 | | /* Set the event's operation counter */ |
280 | 0 | ev->op_info.op_ins_count = es->op_counter++; |
281 | | |
282 | | /* Set the event's timestamp & execution time */ |
283 | 0 | ev->op_info.op_ins_ts = H5_now_usec(); |
284 | 0 | ev->op_info.op_exec_ts = UINT64_MAX; |
285 | 0 | ev->op_info.op_exec_time = UINT64_MAX; |
286 | | |
287 | | /* Copy the API routine's name & arguments */ |
288 | | /* The 'caller' string is also statically allocated (by the compiler) |
289 | | * there's no need to duplicate it. |
290 | | */ |
291 | 0 | ev->op_info.api_name = caller; |
292 | 0 | assert(ev->op_info.api_args == NULL); |
293 | 0 | if (api_args && NULL == (ev->op_info.api_args = H5MM_xstrdup(api_args))) |
294 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't copy API routine arguments"); |
295 | | |
296 | | /* Append fully initialized event onto the event set's 'active' list */ |
297 | 0 | H5ES__list_append(&es->active, ev); |
298 | 0 | ev_inserted = true; |
299 | | |
300 | | /* Invoke the event set's 'insert' callback, if present */ |
301 | 0 | if (es->ins_func) { |
302 | 0 | int status = -1; |
303 | | |
304 | | /* Prepare & restore library for user callback */ |
305 | 0 | H5_BEFORE_USER_CB(FAIL) |
306 | 0 | { |
307 | 0 | status = (es->ins_func)(&ev->op_info, es->ins_ctx); |
308 | 0 | } |
309 | 0 | H5_AFTER_USER_CB(FAIL) |
310 | 0 | if (status < 0) |
311 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'insert' callback for event set failed"); |
312 | 0 | } |
313 | | |
314 | 0 | done: |
315 | | /* Release resources on error */ |
316 | 0 | if (ret_value < 0) |
317 | 0 | if (ev) { |
318 | 0 | if (ev_inserted) |
319 | 0 | H5ES__list_remove(&es->active, ev); |
320 | 0 | if (H5ES__event_free(ev) < 0) |
321 | 0 | HDONE_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "unable to release event"); |
322 | 0 | } |
323 | |
|
324 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
325 | 0 | } /* end H5ES__insert() */ |
326 | | |
327 | | /*------------------------------------------------------------------------- |
328 | | * Function: H5ES_insert |
329 | | * |
330 | | * Purpose: Insert a request token into an event set |
331 | | * |
332 | | * Return: SUCCEED / FAIL |
333 | | * |
334 | | *------------------------------------------------------------------------- |
335 | | */ |
336 | | herr_t |
337 | | H5ES_insert(hid_t es_id, H5VL_connector_t *connector, void *token, const char *caller, |
338 | | const char *caller_args, ...) |
339 | 0 | { |
340 | 0 | H5ES_t *es = NULL; /* Event set for the operation */ |
341 | 0 | const char *app_file; /* Application source file name */ |
342 | 0 | const char *app_func; /* Application source function name */ |
343 | 0 | unsigned app_line; /* Application source line number */ |
344 | 0 | H5RS_str_t *rs = NULL; /* Ref-counted string to compose formatted argument string in */ |
345 | 0 | const char *api_args; /* Pointer to api_args string from ref-counted string */ |
346 | 0 | va_list ap; /* Varargs for caller */ |
347 | 0 | bool arg_started = false; /* Whether the va_list has been started */ |
348 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
349 | |
|
350 | 0 | FUNC_ENTER_NOAPI(FAIL) |
351 | | |
352 | | /* Sanity check */ |
353 | 0 | assert(connector); |
354 | 0 | assert(token); |
355 | 0 | assert(caller); |
356 | 0 | assert(caller_args); |
357 | | |
358 | | /* Get event set */ |
359 | 0 | if (NULL == (es = (H5ES_t *)H5I_object_verify(es_id, H5I_EVENTSET))) |
360 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an event set"); |
361 | | |
362 | | /* Check for errors in event set */ |
363 | 0 | if (es->err_occurred) |
364 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations"); |
365 | | |
366 | | /* Start working on the API routines arguments */ |
367 | 0 | va_start(ap, caller_args); |
368 | 0 | arg_started = true; |
369 | | |
370 | | /* Copy the app source information */ |
371 | 0 | (void)va_arg(ap, char *); /* Toss the 'app_file' parameter name */ |
372 | 0 | app_file = va_arg(ap, char *); |
373 | 0 | (void)va_arg(ap, char *); /* Toss the 'app_func' parameter name */ |
374 | 0 | app_func = va_arg(ap, char *); |
375 | 0 | (void)va_arg(ap, char *); /* Toss the 'app_line' parameter name */ |
376 | 0 | app_line = va_arg(ap, unsigned); |
377 | | |
378 | | /* Create the string for the API routine's arguments */ |
379 | 0 | if (NULL == (rs = H5RS_create(NULL))) |
380 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, FAIL, "can't allocate ref-counted string"); |
381 | | |
382 | | /* Copy the string for the API routine's arguments */ |
383 | | /* (skip the six characters from the app's file, function and line # arguments) */ |
384 | 0 | assert(0 == strncmp(caller_args, "*s*sIu", 6)); |
385 | 0 | if (H5_trace_args(rs, caller_args + 6, ap) < 0) |
386 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, FAIL, "can't create formatted API arguments"); |
387 | 0 | if (NULL == (api_args = H5RS_get_str(rs))) |
388 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "can't get pointer to formatted API arguments"); |
389 | | |
390 | | /* Insert the operation into the event set */ |
391 | 0 | if (H5ES__insert(es, connector, token, app_file, app_func, app_line, caller, api_args) < 0) |
392 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations"); |
393 | | |
394 | 0 | done: |
395 | | /* Clean up */ |
396 | 0 | if (arg_started) |
397 | 0 | va_end(ap); |
398 | 0 | if (rs) |
399 | 0 | H5RS_decr(rs); |
400 | |
|
401 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
402 | 0 | } /* end H5ES_insert() */ |
403 | | |
404 | | /*------------------------------------------------------------------------- |
405 | | * Function: H5ES__insert_request |
406 | | * |
407 | | * Purpose: Directly insert a request token into an event set |
408 | | * |
409 | | * Return: SUCCEED / FAIL |
410 | | * |
411 | | *------------------------------------------------------------------------- |
412 | | */ |
413 | | herr_t |
414 | | H5ES__insert_request(H5ES_t *es, H5VL_connector_t *connector, void *token) |
415 | 0 | { |
416 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
417 | |
|
418 | 0 | FUNC_ENTER_PACKAGE |
419 | | |
420 | | /* Sanity check */ |
421 | 0 | assert(es); |
422 | 0 | assert(connector); |
423 | 0 | assert(token); |
424 | | |
425 | | /* Insert an 'anonymous' operation into the event set */ |
426 | 0 | if (H5ES__insert(es, connector, token, NULL, NULL, 0, NULL, NULL) < 0) |
427 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTINSERT, FAIL, "event set has failed operations"); |
428 | | |
429 | 0 | done: |
430 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
431 | 0 | } /* end H5ES__insert_request() */ |
432 | | |
433 | | /*------------------------------------------------------------------------- |
434 | | * Function: H5ES__get_requests_cb |
435 | | * |
436 | | * Purpose: Iterator callback for H5ES__get_events - adds the event to |
437 | | * the list. |
438 | | * |
439 | | * Return: SUCCEED / FAIL |
440 | | * |
441 | | *------------------------------------------------------------------------- |
442 | | */ |
443 | | static int |
444 | | H5ES__get_requests_cb(H5ES_event_t *ev, void *_ctx) |
445 | 0 | { |
446 | 0 | H5ES_get_requests_ctx_t *ctx = (H5ES_get_requests_ctx_t *)_ctx; /* Callback context */ |
447 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
448 | |
|
449 | 0 | FUNC_ENTER_PACKAGE |
450 | | |
451 | | /* Sanity check */ |
452 | 0 | assert(ev); |
453 | 0 | assert(ctx); |
454 | 0 | assert(ctx->i < ctx->array_len); |
455 | | |
456 | | /* Get the connector ID for the event */ |
457 | 0 | if (ctx->connector_ids) |
458 | 0 | if ((ctx->connector_ids[ctx->i] = H5VL_conn_register(H5VL_OBJ_CONNECTOR(ev->request))) < 0) |
459 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTREGISTER, H5_ITER_ERROR, "unable to register VOL connector ID"); |
460 | | |
461 | | /* Get the request for the event */ |
462 | 0 | if (ctx->requests) |
463 | 0 | ctx->requests[ctx->i] = H5VL_OBJ_DATA(ev->request); |
464 | | |
465 | | /* Check if we've run out of room in the arrays */ |
466 | 0 | if (++ctx->i == ctx->array_len) |
467 | 0 | ret_value = H5_ITER_STOP; |
468 | |
|
469 | 0 | done: |
470 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
471 | 0 | } /* end H5ES__get_requests_cb() */ |
472 | | |
473 | | /*------------------------------------------------------------------------- |
474 | | * Function: H5ES__get_requests |
475 | | * |
476 | | * Purpose: Get all requests in an event set. |
477 | | * |
478 | | * Return: SUCCEED / FAIL |
479 | | * |
480 | | *------------------------------------------------------------------------- |
481 | | */ |
482 | | herr_t |
483 | | H5ES__get_requests(H5ES_t *es, H5_iter_order_t order, hid_t *connector_ids, void **requests, size_t array_len) |
484 | 0 | { |
485 | 0 | H5ES_get_requests_ctx_t ctx; /* Callback context */ |
486 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
487 | |
|
488 | 0 | FUNC_ENTER_PACKAGE |
489 | | |
490 | | /* Sanity check */ |
491 | 0 | assert(es); |
492 | 0 | assert(array_len > 0); |
493 | 0 | assert(requests || connector_ids); |
494 | | |
495 | | /* Set up context for iterator callbacks */ |
496 | 0 | ctx.connector_ids = connector_ids; |
497 | 0 | ctx.requests = requests; |
498 | 0 | ctx.array_len = array_len; |
499 | 0 | ctx.i = 0; |
500 | | |
501 | | /* Iterate over the events in the set */ |
502 | 0 | if (H5ES__list_iterate(&es->active, order, H5ES__get_requests_cb, &ctx) < 0) |
503 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed"); |
504 | | |
505 | 0 | done: |
506 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
507 | 0 | } /* end H5ES__get_requests() */ |
508 | | |
509 | | /*------------------------------------------------------------------------- |
510 | | * Function: H5ES__handle_fail |
511 | | * |
512 | | * Purpose: Handle a failed event |
513 | | * |
514 | | * Return: SUCCEED / FAIL |
515 | | * |
516 | | *------------------------------------------------------------------------- |
517 | | */ |
518 | | static herr_t |
519 | | H5ES__handle_fail(H5ES_t *es, H5ES_event_t *ev) |
520 | 0 | { |
521 | 0 | FUNC_ENTER_PACKAGE_NOERR |
522 | | |
523 | | /* Sanity check */ |
524 | 0 | assert(es); |
525 | 0 | assert(es->active.head); |
526 | 0 | assert(ev); |
527 | | |
528 | | /* Set error flag for event set */ |
529 | 0 | es->err_occurred = true; |
530 | | |
531 | | /* Remove event from normal list */ |
532 | 0 | H5ES__list_remove(&es->active, ev); |
533 | | |
534 | | /* Append event onto the event set's error list */ |
535 | 0 | H5ES__list_append(&es->failed, ev); |
536 | |
|
537 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
538 | 0 | } /* end H5ES__handle_fail() */ |
539 | | |
540 | | /*------------------------------------------------------------------------- |
541 | | * Function: H5ES__op_complete |
542 | | * |
543 | | * Purpose: Handle an operation completing |
544 | | * |
545 | | * Return: SUCCEED / FAIL |
546 | | * |
547 | | *------------------------------------------------------------------------- |
548 | | */ |
549 | | static herr_t |
550 | | H5ES__op_complete(H5ES_t *es, H5ES_event_t *ev, H5VL_request_status_t ev_status) |
551 | 0 | { |
552 | 0 | H5VL_request_specific_args_t vol_cb_args; /* Arguments to VOL callback */ |
553 | 0 | hid_t err_stack_id = H5I_INVALID_HID; /* Error stack for failed operation */ |
554 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
555 | |
|
556 | 0 | FUNC_ENTER_PACKAGE |
557 | | |
558 | | /* Sanity check */ |
559 | 0 | assert(es); |
560 | 0 | assert(ev); |
561 | 0 | assert(H5VL_REQUEST_STATUS_SUCCEED == ev_status || H5VL_REQUEST_STATUS_FAIL == ev_status || |
562 | 0 | H5VL_REQUEST_STATUS_CANCELED == ev_status); |
563 | | |
564 | | /* Handle each form of event completion */ |
565 | 0 | if (H5VL_REQUEST_STATUS_SUCCEED == ev_status || H5VL_REQUEST_STATUS_CANCELED == ev_status) { |
566 | | /* Invoke the event set's 'complete' callback, if present */ |
567 | 0 | if (es->comp_func) { |
568 | 0 | H5ES_status_t op_status; /* Status for complete callback */ |
569 | 0 | int status = -1; |
570 | | |
571 | | /* Set appropriate info for callback */ |
572 | 0 | if (H5VL_REQUEST_STATUS_SUCCEED == ev_status) { |
573 | | /* Translate status */ |
574 | 0 | op_status = H5ES_STATUS_SUCCEED; |
575 | | |
576 | | /* Set up VOL callback arguments */ |
577 | 0 | vol_cb_args.op_type = H5VL_REQUEST_GET_EXEC_TIME; |
578 | 0 | vol_cb_args.args.get_exec_time.exec_ts = &ev->op_info.op_exec_ts; |
579 | 0 | vol_cb_args.args.get_exec_time.exec_time = &ev->op_info.op_exec_time; |
580 | | |
581 | | /* Retrieve the execution time info */ |
582 | 0 | if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) |
583 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, |
584 | 0 | "unable to retrieve execution time info for operation"); |
585 | 0 | } |
586 | 0 | else |
587 | | /* Translate status */ |
588 | 0 | op_status = H5ES_STATUS_CANCELED; |
589 | | |
590 | | /* Prepare & restore library for user callback */ |
591 | 0 | H5_BEFORE_USER_CB(FAIL) |
592 | 0 | { |
593 | 0 | status = (es->comp_func)(&ev->op_info, op_status, H5I_INVALID_HID, es->comp_ctx); |
594 | 0 | } |
595 | 0 | H5_AFTER_USER_CB(FAIL) |
596 | 0 | if (status < 0) |
597 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'complete' callback for event set failed"); |
598 | 0 | } /* end if */ |
599 | | |
600 | | /* Event success or cancellation */ |
601 | 0 | if (H5ES__event_completed(ev, &es->active) < 0) |
602 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, FAIL, "unable to release completed event"); |
603 | 0 | } /* end if */ |
604 | 0 | else if (H5VL_REQUEST_STATUS_FAIL == ev_status) { |
605 | | /* Invoke the event set's 'complete' callback, if present */ |
606 | 0 | if (es->comp_func) { |
607 | | /* Set up VOL callback arguments */ |
608 | 0 | vol_cb_args.op_type = H5VL_REQUEST_GET_ERR_STACK; |
609 | 0 | vol_cb_args.args.get_err_stack.err_stack_id = H5I_INVALID_HID; |
610 | 0 | int status = -1; |
611 | | |
612 | | /* Retrieve the error stack for the operation */ |
613 | 0 | if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) |
614 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, FAIL, "unable to retrieve error stack for operation"); |
615 | | |
616 | | /* Set values */ |
617 | 0 | err_stack_id = vol_cb_args.args.get_err_stack.err_stack_id; |
618 | | |
619 | | /* Prepare & restore library for user callback */ |
620 | 0 | H5_BEFORE_USER_CB(FAIL) |
621 | 0 | { |
622 | 0 | status = (es->comp_func)(&ev->op_info, H5ES_STATUS_FAIL, err_stack_id, es->comp_ctx); |
623 | 0 | } |
624 | 0 | H5_AFTER_USER_CB(FAIL) |
625 | 0 | if (status < 0) |
626 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CALLBACK, FAIL, "'complete' callback for event set failed"); |
627 | 0 | } /* end if */ |
628 | | |
629 | | /* Handle failure */ |
630 | 0 | if (H5ES__handle_fail(es, ev) < 0) |
631 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, FAIL, "unable to handle failed event"); |
632 | 0 | } /* end else-if */ |
633 | 0 | else |
634 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADVALUE, FAIL, "unknown event status?!?"); |
635 | | |
636 | 0 | done: |
637 | | /* Clean up */ |
638 | 0 | if (H5I_INVALID_HID != err_stack_id) |
639 | 0 | if (H5I_dec_ref(err_stack_id) < 0) |
640 | 0 | HDONE_ERROR(H5E_EVENTSET, H5E_CANTDEC, FAIL, |
641 | 0 | "unable to decrement ref count on error stack for failed operation") |
642 | |
|
643 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
644 | 0 | } /* end H5ES__op_complete() */ |
645 | | |
646 | | /*------------------------------------------------------------------------- |
647 | | * Function: H5ES__wait_cb |
648 | | * |
649 | | * Purpose: Common routine for testing / waiting on an operation |
650 | | * |
651 | | * Return: SUCCEED / FAIL |
652 | | * |
653 | | *------------------------------------------------------------------------- |
654 | | */ |
655 | | static int |
656 | | H5ES__wait_cb(H5ES_event_t *ev, void *_ctx) |
657 | 0 | { |
658 | 0 | H5ES_wait_ctx_t *ctx = (H5ES_wait_ctx_t *)_ctx; /* Callback context */ |
659 | 0 | H5VL_request_status_t ev_status = H5VL_REQUEST_STATUS_SUCCEED; /* Status from event's operation */ |
660 | 0 | uint64_t start_time = 0, elapsed_time = 0; /* Start and elapsed times for waiting on an operation */ |
661 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
662 | |
|
663 | 0 | FUNC_ENTER_PACKAGE |
664 | | |
665 | | /* Sanity check */ |
666 | 0 | assert(ev); |
667 | 0 | assert(ctx); |
668 | | |
669 | | /* Wait on the request */ |
670 | 0 | if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) |
671 | 0 | start_time = H5_now_usec(); |
672 | 0 | if (H5VL_request_wait(ev->request, ctx->timeout, &ev_status) < 0) |
673 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTWAIT, H5_ITER_ERROR, "unable to test operation"); |
674 | 0 | if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) |
675 | 0 | elapsed_time = H5_now_usec() - start_time; |
676 | | |
677 | | /* Check for status values that indicate we should break out of the loop */ |
678 | 0 | if (ev_status == H5VL_REQUEST_STATUS_FAIL) { |
679 | | /* Handle event completion */ |
680 | 0 | if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) |
681 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event"); |
682 | | |
683 | | /* Record the error */ |
684 | 0 | *ctx->op_failed = true; |
685 | | |
686 | | /* Exit from the iteration */ |
687 | 0 | ret_value = H5_ITER_STOP; |
688 | 0 | } /* end if */ |
689 | 0 | else if (ev_status == H5VL_REQUEST_STATUS_SUCCEED || ev_status == H5VL_REQUEST_STATUS_CANCELED) { |
690 | | /* Handle event completion */ |
691 | 0 | if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) |
692 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event"); |
693 | 0 | } /* end else-if */ |
694 | 0 | else if (ev_status == H5VL_REQUEST_STATUS_CANT_CANCEL) |
695 | | /* Should never get a status of 'can't cancel' back from test / wait operation */ |
696 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADVALUE, H5_ITER_ERROR, |
697 | 0 | "received \"can't cancel\" status for operation"); |
698 | 0 | else { |
699 | | /* Sanity check */ |
700 | 0 | assert(ev_status == H5VL_REQUEST_STATUS_IN_PROGRESS); |
701 | | |
702 | | /* Increment "in progress operation" counter */ |
703 | 0 | (*ctx->num_in_progress)++; |
704 | 0 | } /* end if */ |
705 | | |
706 | | /* Check for updateable timeout */ |
707 | 0 | if (ctx->timeout != H5ES_WAIT_NONE && ctx->timeout != H5ES_WAIT_FOREVER) { |
708 | | /* Update timeout for next operation */ |
709 | 0 | if ((elapsed_time * 1000) > ctx->timeout) |
710 | 0 | ctx->timeout = H5ES_WAIT_NONE; |
711 | 0 | else |
712 | 0 | ctx->timeout -= (elapsed_time * 1000); /* Convert us to ns */ |
713 | 0 | } /* end if */ |
714 | |
|
715 | 0 | done: |
716 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
717 | 0 | } /* end H5ES__wait_cb() */ |
718 | | |
719 | | /*------------------------------------------------------------------------- |
720 | | * Function: H5ES__wait |
721 | | * |
722 | | * Purpose: Wait for operations in event set to complete |
723 | | * |
724 | | * Note: Timeout value is in ns, and is for H5ES__wait itself. |
725 | | * |
726 | | * Return: SUCCEED / FAIL |
727 | | * |
728 | | *------------------------------------------------------------------------- |
729 | | */ |
730 | | herr_t |
731 | | H5ES__wait(H5ES_t *es, uint64_t timeout, size_t *num_in_progress, bool *op_failed) |
732 | 0 | { |
733 | 0 | H5ES_wait_ctx_t ctx; /* Iterator callback context info */ |
734 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
735 | |
|
736 | 0 | FUNC_ENTER_PACKAGE |
737 | | |
738 | | /* Sanity check */ |
739 | 0 | assert(es); |
740 | 0 | assert(num_in_progress); |
741 | 0 | assert(op_failed); |
742 | | |
743 | | /* Set user's parameters to known values */ |
744 | 0 | *num_in_progress = 0; |
745 | 0 | *op_failed = false; |
746 | | |
747 | | /* Set up context for iterator callbacks */ |
748 | 0 | ctx.es = es; |
749 | 0 | ctx.timeout = timeout; |
750 | 0 | ctx.num_in_progress = num_in_progress; |
751 | 0 | ctx.op_failed = op_failed; |
752 | | |
753 | | /* Iterate over the events in the set, waiting for them to complete */ |
754 | 0 | if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__wait_cb, &ctx) < 0) |
755 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed"); |
756 | | |
757 | 0 | done: |
758 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
759 | 0 | } /* end H5ES__wait() */ |
760 | | |
761 | | /*------------------------------------------------------------------------- |
762 | | * Function: H5ES__cancel_cb |
763 | | * |
764 | | * Purpose: Callback for canceling operations |
765 | | * |
766 | | * Return: SUCCEED / FAIL |
767 | | * |
768 | | *------------------------------------------------------------------------- |
769 | | */ |
770 | | static int |
771 | | H5ES__cancel_cb(H5ES_event_t *ev, void *_ctx) |
772 | 0 | { |
773 | 0 | H5ES_cancel_ctx_t *ctx = (H5ES_cancel_ctx_t *)_ctx; /* Callback context */ |
774 | 0 | H5VL_request_status_t ev_status = H5VL_REQUEST_STATUS_SUCCEED; /* Status from event's operation */ |
775 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
776 | |
|
777 | 0 | FUNC_ENTER_PACKAGE |
778 | | |
779 | | /* Sanity check */ |
780 | 0 | assert(ev); |
781 | 0 | assert(ctx); |
782 | | |
783 | | /* Attempt to cancel the request */ |
784 | 0 | if (H5VL_request_cancel(ev->request, &ev_status) < 0) |
785 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTCANCEL, H5_ITER_ERROR, "unable to cancel operation"); |
786 | | |
787 | | /* Check for status values that indicate we should break out of the loop */ |
788 | 0 | if (ev_status == H5VL_REQUEST_STATUS_FAIL) { |
789 | | /* Handle event completion */ |
790 | 0 | if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) |
791 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTSET, H5_ITER_ERROR, "unable to handle failed event"); |
792 | | |
793 | | /* Record the error */ |
794 | 0 | *ctx->op_failed = true; |
795 | | |
796 | | /* Exit from the iteration */ |
797 | 0 | ret_value = H5_ITER_STOP; |
798 | 0 | } /* end if */ |
799 | 0 | else if (ev_status == H5VL_REQUEST_STATUS_SUCCEED) { |
800 | | /* Increment "not canceled" counter */ |
801 | 0 | (*ctx->num_not_canceled)++; |
802 | | |
803 | | /* Handle event completion */ |
804 | 0 | if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) |
805 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event"); |
806 | 0 | } /* end else-if */ |
807 | 0 | else if (ev_status == H5VL_REQUEST_STATUS_CANT_CANCEL || ev_status == H5VL_REQUEST_STATUS_IN_PROGRESS) { |
808 | | /* Increment "not canceled" counter */ |
809 | 0 | (*ctx->num_not_canceled)++; |
810 | 0 | } /* end else-if */ |
811 | 0 | else { |
812 | | /* Sanity check */ |
813 | 0 | assert(ev_status == H5VL_REQUEST_STATUS_CANCELED); |
814 | | |
815 | | /* Handle event completion */ |
816 | 0 | if (H5ES__op_complete(ctx->es, ev, ev_status) < 0) |
817 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release completed event"); |
818 | 0 | } /* end else */ |
819 | | |
820 | 0 | done: |
821 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
822 | 0 | } /* end H5ES__cancel_cb() */ |
823 | | |
824 | | /*------------------------------------------------------------------------- |
825 | | * Function: H5ES__cancel |
826 | | * |
827 | | * Purpose: Cancel operations in event set |
828 | | * |
829 | | * Return: SUCCEED / FAIL |
830 | | * |
831 | | *------------------------------------------------------------------------- |
832 | | */ |
833 | | herr_t |
834 | | H5ES__cancel(H5ES_t *es, size_t *num_not_canceled, bool *op_failed) |
835 | 0 | { |
836 | 0 | H5ES_cancel_ctx_t ctx; /* Iterator callback context info */ |
837 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
838 | |
|
839 | 0 | FUNC_ENTER_PACKAGE |
840 | | |
841 | | /* Sanity check */ |
842 | 0 | assert(es); |
843 | 0 | assert(num_not_canceled); |
844 | 0 | assert(op_failed); |
845 | | |
846 | | /* Set user's parameters to known values */ |
847 | 0 | *num_not_canceled = 0; |
848 | 0 | *op_failed = false; |
849 | | |
850 | | /* Set up context for iterator callbacks */ |
851 | 0 | ctx.es = es; |
852 | 0 | ctx.num_not_canceled = num_not_canceled; |
853 | 0 | ctx.op_failed = op_failed; |
854 | | |
855 | | /* Iterate over the events in the set, attempting to cancel them */ |
856 | 0 | if (H5ES__list_iterate(&es->active, H5_ITER_NATIVE, H5ES__cancel_cb, &ctx) < 0) |
857 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed"); |
858 | | |
859 | 0 | done: |
860 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
861 | 0 | } /* end H5ES__cancel() */ |
862 | | |
863 | | /*------------------------------------------------------------------------- |
864 | | * Function: H5ES__get_err_info_cb |
865 | | * |
866 | | * Purpose: Retrieve information about a failed operation |
867 | | * |
868 | | * Return: SUCCEED / FAIL |
869 | | * |
870 | | *------------------------------------------------------------------------- |
871 | | */ |
872 | | static int |
873 | | H5ES__get_err_info_cb(H5ES_event_t *ev, void *_ctx) |
874 | 0 | { |
875 | 0 | H5VL_request_specific_args_t vol_cb_args; /* Arguments to VOL callback */ |
876 | 0 | H5ES_gei_ctx_t *ctx = (H5ES_gei_ctx_t *)_ctx; /* Callback context */ |
877 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
878 | |
|
879 | 0 | FUNC_ENTER_PACKAGE |
880 | | |
881 | | /* Sanity check */ |
882 | 0 | assert(ev); |
883 | 0 | assert(ctx); |
884 | | |
885 | | /* Copy operation info for event */ |
886 | | /* The 'app_func_name', 'app_file_name', and 'api_name' strings are statically allocated (by the compiler) |
887 | | * so there's no need to duplicate them internally, but they are duplicated |
888 | | * here, when they are given back to the user. |
889 | | */ |
890 | 0 | if (NULL == (ctx->curr_err_info->api_name = H5MM_xstrdup(ev->op_info.api_name))) |
891 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine name"); |
892 | 0 | if (NULL == (ctx->curr_err_info->api_args = H5MM_xstrdup(ev->op_info.api_args))) |
893 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 API routine arguments"); |
894 | 0 | if (NULL == (ctx->curr_err_info->app_file_name = H5MM_xstrdup(ev->op_info.app_file_name))) |
895 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application file name"); |
896 | 0 | if (NULL == (ctx->curr_err_info->app_func_name = H5MM_xstrdup(ev->op_info.app_func_name))) |
897 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTALLOC, H5_ITER_ERROR, "can't copy HDF5 application function name"); |
898 | 0 | ctx->curr_err_info->app_line_num = ev->op_info.app_line_num; |
899 | 0 | ctx->curr_err_info->op_ins_count = ev->op_info.op_ins_count; |
900 | 0 | ctx->curr_err_info->op_ins_ts = ev->op_info.op_ins_ts; |
901 | 0 | ctx->curr_err_info->op_exec_ts = ev->op_info.op_exec_ts; |
902 | 0 | ctx->curr_err_info->op_exec_time = ev->op_info.op_exec_time; |
903 | | |
904 | | /* Set up VOL callback arguments */ |
905 | 0 | vol_cb_args.op_type = H5VL_REQUEST_GET_ERR_STACK; |
906 | 0 | vol_cb_args.args.get_err_stack.err_stack_id = H5I_INVALID_HID; |
907 | | |
908 | | /* Get error stack for event */ |
909 | 0 | if (H5VL_request_specific(ev->request, &vol_cb_args) < 0) |
910 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTGET, H5_ITER_ERROR, "unable to retrieve error stack for operation"); |
911 | | |
912 | | /* Set value */ |
913 | 0 | ctx->curr_err_info->err_stack_id = vol_cb_args.args.get_err_stack.err_stack_id; |
914 | | |
915 | | /* Remove event from event set's failed list */ |
916 | 0 | H5ES__list_remove(&ctx->es->failed, ev); |
917 | | |
918 | | /* Free event node */ |
919 | 0 | if (H5ES__event_free(ev) < 0) |
920 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event"); |
921 | | |
922 | | /* Advance to next element of err_info[] array */ |
923 | 0 | ctx->curr_err++; |
924 | 0 | ctx->curr_err_info++; |
925 | | |
926 | | /* Stop iteration if err_info[] array is full */ |
927 | 0 | if (ctx->curr_err == ctx->num_err_info) |
928 | 0 | ret_value = H5_ITER_STOP; |
929 | |
|
930 | 0 | done: |
931 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
932 | 0 | } /* end H5ES__get_err_info_cb() */ |
933 | | |
934 | | /*------------------------------------------------------------------------- |
935 | | * Function: H5ES__get_err_info |
936 | | * |
937 | | * Purpose: Retrieve information about failed operations |
938 | | * |
939 | | * Return: SUCCEED / FAIL |
940 | | * |
941 | | *------------------------------------------------------------------------- |
942 | | */ |
943 | | herr_t |
944 | | H5ES__get_err_info(H5ES_t *es, size_t num_err_info, H5ES_err_info_t err_info[], size_t *num_cleared) |
945 | 0 | { |
946 | 0 | H5ES_gei_ctx_t ctx; /* Iterator callback context info */ |
947 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
948 | |
|
949 | 0 | FUNC_ENTER_PACKAGE |
950 | | |
951 | | /* Sanity check */ |
952 | 0 | assert(es); |
953 | 0 | assert(num_err_info); |
954 | 0 | assert(err_info); |
955 | 0 | assert(num_cleared); |
956 | | |
957 | | /* Set up context for iterator callbacks */ |
958 | 0 | ctx.es = es; |
959 | 0 | ctx.num_err_info = num_err_info; |
960 | 0 | ctx.curr_err = 0; |
961 | 0 | ctx.curr_err_info = &err_info[0]; |
962 | | |
963 | | /* Iterate over the failed events in the set, copying their error info */ |
964 | 0 | if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__get_err_info_cb, &ctx) < 0) |
965 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed"); |
966 | | |
967 | | /* Set # of failed events cleared from event set's failed list */ |
968 | 0 | *num_cleared = ctx.curr_err; |
969 | |
|
970 | 0 | done: |
971 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
972 | 0 | } /* end H5ES__get_err_info() */ |
973 | | |
974 | | /*------------------------------------------------------------------------- |
975 | | * Function: H5ES__close_failed_cb |
976 | | * |
977 | | * Purpose: Release a failed event |
978 | | * |
979 | | * Return: SUCCEED / FAIL |
980 | | * |
981 | | *------------------------------------------------------------------------- |
982 | | */ |
983 | | static int |
984 | | H5ES__close_failed_cb(H5ES_event_t *ev, void *_ctx) |
985 | 0 | { |
986 | 0 | H5ES_t *es = (H5ES_t *)_ctx; /* Callback context */ |
987 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
988 | |
|
989 | 0 | FUNC_ENTER_PACKAGE |
990 | | |
991 | | /* Sanity check */ |
992 | 0 | assert(ev); |
993 | 0 | assert(es); |
994 | | |
995 | | /* Remove event from event set's failed list */ |
996 | 0 | H5ES__list_remove(&es->failed, ev); |
997 | | |
998 | | /* Free event node */ |
999 | 0 | if (H5ES__event_free(ev) < 0) |
1000 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_CANTRELEASE, H5_ITER_ERROR, "unable to release failed event"); |
1001 | | |
1002 | 0 | done: |
1003 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1004 | 0 | } /* end H5ES__close_failed_cb() */ |
1005 | | |
1006 | | /*------------------------------------------------------------------------- |
1007 | | * Function: H5ES__close |
1008 | | * |
1009 | | * Purpose: Destroy an event set object |
1010 | | * |
1011 | | * Return: SUCCEED / FAIL |
1012 | | * |
1013 | | *------------------------------------------------------------------------- |
1014 | | */ |
1015 | | herr_t |
1016 | | H5ES__close(H5ES_t *es) |
1017 | 0 | { |
1018 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1019 | |
|
1020 | 0 | FUNC_ENTER_PACKAGE |
1021 | | |
1022 | | /* Sanity check */ |
1023 | 0 | assert(es); |
1024 | | |
1025 | | /* Fail if active operations still present */ |
1026 | 0 | if (H5ES__list_count(&es->active) > 0) |
1027 | 0 | HGOTO_ERROR( |
1028 | 0 | H5E_EVENTSET, H5E_CANTCLOSEOBJ, FAIL, |
1029 | 0 | "can't close event set while unfinished operations are present (i.e. wait on event set first)"); |
1030 | | |
1031 | | /* Iterate over the failed events in the set, releasing them */ |
1032 | 0 | if (H5ES__list_iterate(&es->failed, H5_ITER_NATIVE, H5ES__close_failed_cb, (void *)es) < 0) |
1033 | 0 | HGOTO_ERROR(H5E_EVENTSET, H5E_BADITER, FAIL, "iteration failed"); |
1034 | | |
1035 | | /* Release the event set */ |
1036 | 0 | es = H5FL_FREE(H5ES_t, es); |
1037 | |
|
1038 | 0 | done: |
1039 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1040 | 0 | } /* end H5ES__close() */ |