summaryrefslogtreecommitdiffstats
path: root/src/H5VLnative_object.c
blob: 8f60ac49007c50c71d26010716fe7810737d8a84 (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
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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://support.hdfgroup.org/ftp/HDF5/releases.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * Purpose:     Object callbacks for the native VOL connector
 *
 */

#define H5O_FRIEND              /* Suppress error about including H5Opkg    */
#define H5F_FRIEND              /* Suppress error about including H5Fpkg    */

#include "H5private.h"          /* Generic Functions                        */
#include "H5Eprivate.h"         /* Error handling                           */
#include "H5Fpkg.h"             /* Files (pkg needed for id_exists)         */
#include "H5Gprivate.h"         /* Groups                                   */
#include "H5Iprivate.h"         /* IDs                                      */
#include "H5Opkg.h"             /* Object headers                           */
#include "H5Pprivate.h"         /* Property lists                           */
#include "H5VLprivate.h"        /* Virtual Object Layer                     */

#include "H5VLnative_private.h" /* Native VOL connector                     */


/*-------------------------------------------------------------------------
 * Function:    H5VL__native_object_open
 *
 * Purpose:     Handles the object open callback
 *
 * Return:      Success:    object pointer
 *              Failure:    NULL
 *
 *-------------------------------------------------------------------------
 */
void *
H5VL__native_object_open(void *obj, const H5VL_loc_params_t *loc_params, H5I_type_t *opened_type,
    hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
{
    H5G_loc_t   loc;
    void       *ret_value = NULL;

    FUNC_ENTER_PACKAGE

    if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file or file object")

    switch(loc_params->type) {
        case H5VL_OBJECT_BY_NAME:
            {
                /* Open the object */
                if(NULL == (ret_value = H5O_open_name(&loc, loc_params->loc_data.loc_by_name.name, opened_type)))
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by name")
                break;
            }

        case H5VL_OBJECT_BY_IDX:
            {
                /* Open the object */
                if(NULL == (ret_value = H5O_open_by_idx(&loc, loc_params->loc_data.loc_by_idx.name, loc_params->loc_data.loc_by_idx.idx_type,
                        loc_params->loc_data.loc_by_idx.order, loc_params->loc_data.loc_by_idx.n, opened_type)))
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by index")
                break;
            }

        case H5VL_OBJECT_BY_TOKEN:
            {
                H5O_token_t token = *loc_params->loc_data.loc_by_token.token;
                haddr_t addr;

                /* Decode token */
                if(H5VL_native_token_to_addr(loc.oloc->file, H5I_FILE, token, &addr) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, NULL, "can't deserialize object token into address")

                /* Open the object */
                if(NULL == (ret_value = H5O_open_by_addr(&loc, addr, opened_type)))
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object by address")
                break;
            }

        case H5VL_OBJECT_BY_SELF:
        default:
            HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, NULL, "unknown open parameters")
    } /* end switch */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_object_open() */


/*-------------------------------------------------------------------------
 * Function:    H5VL__native_object_copy
 *
 * Purpose:     Handles the object copy callback
 *
 * Return:      SUCCEED/FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5VL__native_object_copy(void *src_obj, const H5VL_loc_params_t *loc_params1, const char *src_name,
    void *dst_obj, const H5VL_loc_params_t *loc_params2, const char *dst_name,
    hid_t ocpypl_id, hid_t lcpl_id, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
{
    H5G_loc_t   src_loc;                /* Source object group location */
    H5G_loc_t   dst_loc;                /* Destination group location */
    herr_t      ret_value = FAIL;

    FUNC_ENTER_PACKAGE

    /* get location for objects */
    if(H5G_loc_real(src_obj, loc_params1->obj_type, &src_loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
    if(H5G_loc_real(dst_obj, loc_params2->obj_type, &dst_loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")

    /* Copy the object */
    if((ret_value = H5O_copy(&src_loc, src_name, &dst_loc, dst_name, ocpypl_id, lcpl_id)) < 0)
        HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "unable to copy object")

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_object_copy() */


/*-------------------------------------------------------------------------
 * Function:    H5VL__native_object_get
 *
 * Purpose:     Handles the object get callback
 *
 * Return:      SUCCEED/FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5VL__native_object_get(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_get_t get_type,
    hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
{
    herr_t      ret_value = SUCCEED;    /* Return value */
    H5G_loc_t   loc;                    /* Location of group */

    FUNC_ENTER_PACKAGE

    if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")

    switch(get_type) {

        /* Object file */
        case H5VL_OBJECT_GET_FILE:
            {
                void **ret = HDva_arg(arguments, void **);

                if(loc_params->type == H5VL_OBJECT_BY_SELF) {
                    *ret = (void *)loc.oloc->file;

                    /* TODO we currently need to set id_exists to TRUE because
                     * the upper layer will create an ID from the returned
                     * object. In theory this should not be needed and id_exists
                     * should be removed once the H5Fmount code gets fixed. */
                    loc.oloc->file->id_exists = TRUE;
                } else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_file parameters")
                break;
            }

        /* Object name */
        case H5VL_OBJECT_GET_NAME:
            {
                ssize_t *ret = HDva_arg(arguments, ssize_t *);
                char *name = HDva_arg(arguments, char *);
                size_t size = HDva_arg(arguments, size_t);

                if(loc_params->type == H5VL_OBJECT_BY_SELF) {
                    /* Retrieve object's name */
                    if((*ret = H5G_get_name(&loc, name, size, NULL)) < 0)
                        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't retrieve object name")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_TOKEN) {
                    H5O_loc_t obj_oloc; /* Object location */
                    H5O_token_t token = *loc_params->loc_data.loc_by_token.token;

                    /* Initialize the object location */
                    H5O_loc_reset(&obj_oloc);
                    obj_oloc.file = loc.oloc->file;

                    /* Decode token */
                    if(H5VL_native_token_to_addr(obj_oloc.file, H5I_FILE, token, &obj_oloc.addr) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize object token into address")

                    /* Retrieve object's name */
                    if((*ret = H5G_get_name_by_addr(loc.oloc->file, &obj_oloc, name, size)) < 0)
                        HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't determine object name")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_name parameters")
                break;
            }

        /* Object type */
        case H5VL_OBJECT_GET_TYPE:
            {
                H5O_type_t *obj_type = HDva_arg(arguments, H5O_type_t *);

                if(loc_params->type == H5VL_OBJECT_BY_TOKEN) {
                    H5O_loc_t obj_oloc; /* Object location */
                    unsigned rc;        /* Reference count of object */
                    H5O_token_t token = *loc_params->loc_data.loc_by_token.token;

                    /* Initialize the object location */
                    H5O_loc_reset(&obj_oloc);
                    obj_oloc.file = loc.oloc->file;

                    /* Decode token */
                    if(H5VL_native_token_to_addr(obj_oloc.file, H5I_FILE, token, &obj_oloc.addr) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTUNSERIALIZE, FAIL, "can't deserialize object token into address")

                    /* Get the # of links for object, and its type */
                    /* (To check to make certain that this object hasn't been deleted) */
                    if(H5O_get_rc_and_type(&obj_oloc, &rc, obj_type) < 0 || 0 == rc)
                        HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, FAIL, "dereferencing deleted object")
                } else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown get_type parameters")
                break;
            }

        /* H5Oget_info(_name|_by_idx)3 */
        case H5VL_OBJECT_GET_INFO:
            {
                H5O_info2_t  *oinfo = HDva_arg(arguments, H5O_info2_t *);
                unsigned fields         = HDva_arg(arguments, unsigned);

                /* Use the original H5Oget_info code to get the data */

                if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oget_info */
                    /* Retrieve the object's information */
                    if(H5G_loc_info(&loc, ".", oinfo, fields) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oget_info_by_name */
                    /* Retrieve the object's information */
                    if(H5G_loc_info(&loc, loc_params->loc_data.loc_by_name.name, oinfo, fields) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end else-if */
                else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Oget_info_by_idx */
                    H5G_loc_t   obj_loc;                /* Location used to open group */
                    H5G_name_t  obj_path;               /* Opened object group hier. path */
                    H5O_loc_t   obj_oloc;               /* Opened object object location */

                    /* Set up opened group location to fill in */
                    obj_loc.oloc = &obj_oloc;
                    obj_loc.path = &obj_path;
                    H5G_loc_reset(&obj_loc);

                    /* Find the object's location, according to the order in the index */
                    if(H5G_loc_find_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
                                           loc_params->loc_data.loc_by_idx.idx_type,
                                           loc_params->loc_data.loc_by_idx.order,
                                           loc_params->loc_data.loc_by_idx.n, &obj_loc/*out*/) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "group not found")

                    /* Retrieve the object's information */
                    if(H5O_get_info(obj_loc.oloc, oinfo, fields) < 0) {
                        H5G_loc_free(&obj_loc);
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object info")
                    } /* end if */

                    /* Release the object location */
                    if(H5G_loc_free(&obj_loc) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "unknown get info parameters")
                break;
            }

        default:
            HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information from object")
    } /* end switch */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_object_get() */


/*-------------------------------------------------------------------------
 * Function:    H5VL__native_object_specific
 *
 * Purpose:     Handles the object specific callback
 *
 * Return:      SUCCEED/FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5VL__native_object_specific(void *obj, const H5VL_loc_params_t *loc_params, H5VL_object_specific_t specific_type,
    hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
{
    H5G_loc_t    loc;
    herr_t       ret_value = SUCCEED;    /* Return value */

    FUNC_ENTER_PACKAGE

    if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")

    switch(specific_type) {
        /* H5Oincr_refcount / H5Odecr_refcount */
        case H5VL_OBJECT_CHANGE_REF_COUNT:
            {
                int update_ref  = HDva_arg(arguments, int);
                H5O_loc_t  *oloc = loc.oloc;

                if(H5O_link(oloc, update_ref) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")

                break;
            }

        /* H5Oexists_by_name */
        case H5VL_OBJECT_EXISTS:
            {
                htri_t *ret = HDva_arg(arguments, htri_t *);

                if(loc_params->type == H5VL_OBJECT_BY_NAME) {
                    /* Check if the object exists */
                    if((*ret = H5G_loc_exists(&loc, loc_params->loc_data.loc_by_name.name)) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine if '%s' exists", loc_params->loc_data.loc_by_name.name)
                } /* end if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object exists parameters")
                break;
            }

        /* Lookup object */
        case H5VL_OBJECT_LOOKUP:
            {
                H5O_token_t *token = va_arg(arguments, H5O_token_t *);

                HDassert(token);

                if(loc_params->type == H5VL_OBJECT_BY_NAME) {
                    H5G_loc_t obj_loc;      /* Group hier. location of object */
                    H5G_name_t obj_path;    /* Object group hier. path */
                    H5O_loc_t obj_oloc;     /* Object object location */

                    /* Set up opened group location to fill in */
                    obj_loc.oloc = &obj_oloc;
                    obj_loc.path = &obj_path;
                    H5G_loc_reset(&obj_loc);

                    /* Find the object */
                    if(H5G_loc_find(&loc, loc_params->loc_data.loc_by_name.name, &obj_loc) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")

                    /* Encode token */
                    if(H5VL_native_addr_to_token(loc.oloc->file, H5I_FILE, obj_loc.oloc->addr, token) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "can't serialize address into object token")

                    /* Release the object location */
                    if(H5G_loc_free(&obj_loc) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
                } /* end if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object exists parameters")
                break;
            }

        case H5VL_OBJECT_VISIT:
            {
                H5_index_t idx_type     = (H5_index_t)HDva_arg(arguments, int); /* enum work-around */
                H5_iter_order_t order   = (H5_iter_order_t)HDva_arg(arguments, int); /* enum work-around */
                H5O_iterate2_t op       = HDva_arg(arguments, H5O_iterate2_t);
                void *op_data           = HDva_arg(arguments, void *);
                unsigned fields         = HDva_arg(arguments, unsigned);

                /* Call internal object visitation routine */
                if(loc_params->type == H5VL_OBJECT_BY_SELF) {
                    /* H5Ovisit */
                    if((ret_value = H5O__visit(&loc, ".", idx_type, order, op, op_data, fields)) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_NAME) {
                    /* H5Ovisit_by_name */
                    if((ret_value = H5O__visit(&loc, loc_params->loc_data.loc_by_name.name, idx_type, order, op, op_data, fields)) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown object visit params");
                break;
            }

        case H5VL_OBJECT_FLUSH:
            {
                hid_t   oid     = HDva_arg(arguments, hid_t);

                /* Flush the object's metadata */
                if(H5O_flush(loc.oloc, oid) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTFLUSH, FAIL, "unable to flush object")

                break;
            }

        case H5VL_OBJECT_REFRESH:
            {
                hid_t                   oid         = HDva_arg(arguments, hid_t);
                H5O_loc_t              *oloc        = loc.oloc;

                /* Refresh the metadata */
                if(H5O_refresh_metadata(oid, *oloc) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to refresh object")

                break;
            }

        default:
            HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't recognize this operation type")
    } /* end switch */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_object_specific() */


/*-------------------------------------------------------------------------
 * Function:    H5VL__native_object_optional
 *
 * Purpose:     Handles the object optional callback
 *
 * Return:      SUCCEED/FAIL
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5VL__native_object_optional(void *obj, H5VL_object_optional_t optional_type,
    hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req, va_list arguments)
{
    H5VL_loc_params_t *loc_params = HDva_arg(arguments, H5VL_loc_params_t *);
    H5G_loc_t   loc;                    /* Location of group */
    herr_t       ret_value = SUCCEED;    /* Return value */

    FUNC_ENTER_PACKAGE

    if(H5G_loc_real(obj, loc_params->obj_type, &loc) < 0)
        HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")

    switch(optional_type) {
        /* H5Oget_comment / H5Oget_comment_by_name */
        case H5VL_NATIVE_OBJECT_GET_COMMENT:
            {
                char     *comment =  HDva_arg(arguments, char *);
                size_t   bufsize  =  HDva_arg(arguments, size_t);
                ssize_t  *ret     =  HDva_arg(arguments, ssize_t *);

                /* Retrieve the object's comment */
                if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oget_comment */
                    if((*ret = H5G_loc_get_comment(&loc, ".", comment/*out*/, bufsize)) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oget_comment_by_name */
                    if((*ret = H5G_loc_get_comment(&loc, loc_params->loc_data.loc_by_name.name, comment/*out*/, bufsize)) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown set_coment parameters")
                break;
            }

        /* H5Oset_comment */
        case H5VL_NATIVE_OBJECT_SET_COMMENT:
            {
                const char    *comment  = HDva_arg(arguments, char *);

                if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oset_comment */
                    /* (Re)set the object's comment */
                    if(H5G_loc_set_comment(&loc, ".", comment) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oset_comment_by_name */
                    /* (Re)set the object's comment */
                    if(H5G_loc_set_comment(&loc, loc_params->loc_data.loc_by_name.name, comment) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "unknown set_coment parameters")
                break;
            }

        /* H5Odisable_mdc_flushes */
        case H5VL_NATIVE_OBJECT_DISABLE_MDC_FLUSHES:
            {
                H5O_loc_t  *oloc = loc.oloc;

                if (H5O_disable_mdc_flushes(oloc) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork the metadata cache");

                break;
            }

        /* H5Oenable_mdc_flushes */
        case H5VL_NATIVE_OBJECT_ENABLE_MDC_FLUSHES:
            {
                H5O_loc_t  *oloc = loc.oloc;

                if (H5O_enable_mdc_flushes(oloc) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork the metadata cache");

                break;
            }

        /* H5Oare_mdc_flushes_disabled */
        case H5VL_NATIVE_OBJECT_ARE_MDC_FLUSHES_DISABLED:
            {
                H5O_loc_t  *oloc = loc.oloc;
                hbool_t *are_disabled = (hbool_t *)HDva_arg(arguments, hbool_t *);

                if (H5O_are_mdc_flushes_disabled(oloc, are_disabled) < 0)
                    HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine metadata cache cork status");

                break;
            }

        /* H5Oget_native_info(_name|_by_idx) */
        case H5VL_NATIVE_OBJECT_GET_NATIVE_INFO:
            {
                H5O_native_info_t  *native_info = HDva_arg(arguments, H5O_native_info_t *);
                unsigned fields         = HDva_arg(arguments, unsigned);

                /* Use the original H5Oget_info code to get the data */

                if(loc_params->type == H5VL_OBJECT_BY_SELF) { /* H5Oget_info */
                    /* Retrieve the object's information */
                    if(H5G_loc_native_info(&loc, ".", native_info, fields) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end if */
                else if(loc_params->type == H5VL_OBJECT_BY_NAME) { /* H5Oget_info_by_name */
                    /* Retrieve the object's information */
                    if(H5G_loc_native_info(&loc, loc_params->loc_data.loc_by_name.name, native_info, fields) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
                } /* end else-if */
                else if(loc_params->type == H5VL_OBJECT_BY_IDX) { /* H5Oget_info_by_idx */
                    H5G_loc_t   obj_loc;                /* Location used to open group */
                    H5G_name_t  obj_path;               /* Opened object group hier. path */
                    H5O_loc_t   obj_oloc;               /* Opened object object location */

                    /* Set up opened group location to fill in */
                    obj_loc.oloc = &obj_oloc;
                    obj_loc.path = &obj_path;
                    H5G_loc_reset(&obj_loc);

                    /* Find the object's location, according to the order in the index */
                    if(H5G_loc_find_by_idx(&loc, loc_params->loc_data.loc_by_idx.name,
                                           loc_params->loc_data.loc_by_idx.idx_type,
                                           loc_params->loc_data.loc_by_idx.order,
                                           loc_params->loc_data.loc_by_idx.n, &obj_loc/*out*/) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "group not found")

                    /* Retrieve the object's information */
                    if(H5O_get_native_info(obj_loc.oloc, native_info, fields) < 0) {
                        H5G_loc_free(&obj_loc);
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object info")
                    } /* end if */

                    /* Release the object location */
                    if(H5G_loc_free(&obj_loc) < 0)
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
                } /* end else-if */
                else
                    HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, FAIL, "unknown get info parameters")

                break;
            }

        default:
            HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't perform this operation on object");
    } /* end switch */

done:
    FUNC_LEAVE_NOAPI(ret_value)
} /* end H5VL__native_object_optional() */

---------------------------------------- */ static herr_t H5O__cache_image_len(const void *_thing, size_t *image_len) { const H5O_t *oh = (const H5O_t *)_thing; /* Object header to query */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(oh); HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(oh->cache_info.type == H5AC_OHDR); HDassert(image_len); /* Report the object header's prefix+first chunk length */ *image_len = oh->chunk[0].size; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O__cache_image_len() */ /*------------------------------------------------------------------------- * Function: H5O__cache_serialize * * Purpose: Serialize the contents of the supplied object header, and * load this data into the supplied buffer. * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_serialize(const H5F_t *f, void *image, size_t len, void *_thing) { H5O_t *oh = (H5O_t *)_thing; /* Object header to encode */ uint8_t *chunk_image; /* Pointer to object header prefix buffer */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(f); HDassert(image); HDassert(oh); HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(oh->cache_info.type == H5AC_OHDR); HDassert(oh->chunk[0].size == len); #ifdef H5O_DEBUG H5O__assert(oh); #endif /* H5O_DEBUG */ /* Point to raw data 'image' for first chunk, which * has room for the prefix */ chunk_image = oh->chunk[0].image; /* Later versions of object header prefix have different format and * also require that chunk 0 always be updated, since the checksum * on the entire block of memory needs to be updated if anything is * modified */ if(oh->version > H5O_VERSION_1) { uint64_t chunk0_size; /* Size of chunk 0's data */ HDassert(oh->chunk[0].size >= (size_t)H5O_SIZEOF_HDR(oh)); chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh); /* Verify magic number */ HDassert(!HDmemcmp(chunk_image, H5O_HDR_MAGIC, H5_SIZEOF_MAGIC)); chunk_image += H5_SIZEOF_MAGIC; /* Version */ *chunk_image++ = oh->version; /* Flags */ *chunk_image++ = oh->flags; /* Time fields */ if(oh->flags & H5O_HDR_STORE_TIMES) { UINT32ENCODE(chunk_image, oh->atime); UINT32ENCODE(chunk_image, oh->mtime); UINT32ENCODE(chunk_image, oh->ctime); UINT32ENCODE(chunk_image, oh->btime); } /* end if */ /* Attribute fields */ if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) { UINT16ENCODE(chunk_image, oh->max_compact); UINT16ENCODE(chunk_image, oh->min_dense); } /* end if */ /* First chunk size */ switch(oh->flags & H5O_HDR_CHUNK0_SIZE) { case 0: /* 1 byte size */ HDassert(chunk0_size < 256); *chunk_image++ = (uint8_t)chunk0_size; break; case 1: /* 2 byte size */ HDassert(chunk0_size < 65536); UINT16ENCODE(chunk_image, chunk0_size); break; case 2: /* 4 byte size */ /* use <= 2**32 -1 to stay within 4 bytes integer range */ HDassert(chunk0_size <= 4294967295UL); UINT32ENCODE(chunk_image, chunk0_size); break; case 3: /* 8 byte size */ UINT64ENCODE(chunk_image, chunk0_size); break; default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0") } /* end switch */ } /* end if */ else { /* Version */ *chunk_image++ = oh->version; /* Reserved */ *chunk_image++ = 0; /* Number of messages */ #ifdef H5O_ENABLE_BAD_MESG_COUNT if(oh->store_bad_mesg_count) UINT16ENCODE(chunk_image, (oh->nmesgs - 1)) else #endif /* H5O_ENABLE_BAD_MESG_COUNT */ UINT16ENCODE(chunk_image, oh->nmesgs); /* Link count */ UINT32ENCODE(chunk_image, oh->nlink); /* First chunk size */ UINT32ENCODE(chunk_image, (oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh))); /* Zero to alignment */ HDmemset(chunk_image, 0, (size_t)(H5O_SIZEOF_HDR(oh) - 12)); chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - 12); } /* end else */ HDassert((size_t)(chunk_image - oh->chunk[0].image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); /* Serialize messages for this chunk */ if(H5O__chunk_serialize(f, oh, (unsigned)0) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize first object header chunk") /* copy the chunk into the image -- this is potentially expensive. * Can we rework things so that the object header and the cache * share a buffer? */ H5MM_memcpy(image, oh->chunk[0].image, len); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_serialize() */ /*------------------------------------------------------------------------- * Function: H5O__cache_notify * * Purpose: Handle cache action notifications * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Jul 23 2016 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_notify(H5AC_notify_action_t action, void *_thing) { H5O_t *oh = (H5O_t *)_thing; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* * Check arguments. */ HDassert(oh); switch(action) { case H5AC_NOTIFY_ACTION_AFTER_INSERT: case H5AC_NOTIFY_ACTION_AFTER_LOAD: if(oh->swmr_write) { /* Sanity check */ HDassert(oh->proxy); /* Register the object header as a parent of the virtual entry */ if(H5AC_proxy_entry_add_parent(oh->proxy, oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add object header as parent of proxy") } /* end if */ break; case H5AC_NOTIFY_ACTION_AFTER_FLUSH: case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED: /* do nothing */ break; case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: { unsigned u; /* Local index variable */ /* Mark messages stored with the object header (i.e. messages in chunk 0) as clean */ for(u = 0; u < oh->nmesgs; u++) if(oh->mesg[u].chunkno == 0) oh->mesg[u].dirty = FALSE; #ifndef NDEBUG /* Reset the number of messages dirtied by decoding */ oh->ndecode_dirtied = 0; #endif /* NDEBUG */ } break; case H5AC_NOTIFY_ACTION_CHILD_DIRTIED: case H5AC_NOTIFY_ACTION_CHILD_CLEANED: case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED: case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED: /* do nothing */ break; case H5AC_NOTIFY_ACTION_BEFORE_EVICT: if(oh->swmr_write) { /* Unregister the object header as a parent of the virtual entry */ if(H5AC_proxy_entry_remove_parent(oh->proxy, oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't remove object header as parent of proxy") } /* end if */ break; default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache") } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_notify() */ /*------------------------------------------------------------------------- * Function: H5O__cache_free_icr * * Purpose: Free the in core representation of the supplied object header. * * Note: The metadata cache sets the object's cache_info.magic to * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr * callback (checked in assert). * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_free_icr(void *_thing) { H5O_t *oh = (H5O_t *)_thing; /* Object header to destroy */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(oh); HDassert(oh->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); HDassert(oh->cache_info.type == H5AC_OHDR); /* Destroy object header */ if(H5O__free(oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_free_icr() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_get_initial_load_size() * * Purpose: Tell the metadata cache how large the on disk image of the * chunk proxy is, so it can load the image into a buffer for the * deserialize call. * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_get_initial_load_size(void *_udata, size_t *image_len) { const H5O_chk_cache_ud_t *udata = (const H5O_chk_cache_ud_t *)_udata; /* User data for callback */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(udata); HDassert(udata->oh); HDassert(image_len); /* Set the image length size */ *image_len = udata->size; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O__cache_chk_get_initial_load_size() */ /*------------------------------------------------------------------------- * Function: H5B2__cache_chk_verify_chksum * * Purpose: Verify the computed checksum of the data structure is the * same as the stored chksum. * * Return: Success: TRUE/FALSE * Failure: Negative * * Programmer: Vailin Choi * Aug 2015 * *------------------------------------------------------------------------- */ static htri_t H5O__cache_chk_verify_chksum(const void *_image, size_t len, void *_udata) { const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */ htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(image); /* There is no checksum for version 1 */ if(udata->oh->version != H5O_VERSION_1) { uint32_t stored_chksum; /* Stored metadata checksum value */ uint32_t computed_chksum; /* Computed metadata checksum value */ /* Get stored and computed checksums */ H5F_get_checksums(image, len, &stored_chksum, &computed_chksum); if(stored_chksum != computed_chksum) ret_value = FALSE; } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_verify_chksum() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_deserialize * * Purpose: Attempt to deserialize the object header continuation chunk * contained in the supplied buffer, load the data into an instance * of H5O_chunk_proxy_t, and return a pointer to the new instance. * * Return: Success: Pointer to in core representation * Failure: NULL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static void * H5O__cache_chk_deserialize(const void *image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_udata, hbool_t *dirty) { H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk proxy object */ H5O_chk_cache_ud_t *udata = (H5O_chk_cache_ud_t *)_udata; /* User data for callback */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(image); HDassert(len > 0); HDassert(udata); HDassert(udata->oh); HDassert(dirty); /* Allocate space for the object header data structure */ if(NULL == (chk_proxy = H5FL_CALLOC(H5O_chunk_proxy_t))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, NULL, "memory allocation failed") /* Check if we are still decoding the object header */ /* (as opposed to bringing a piece of it back from the file) */ if(udata->decoding) { /* Sanity check */ HDassert(udata->common.f); HDassert(udata->common.cont_msg_info); /* Parse the chunk */ if(H5O__chunk_deserialize(udata->oh, udata->common.addr, udata->size, (const uint8_t *)image, &(udata->common), dirty) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't deserialize object header chunk") /* Set the chunk number for the chunk proxy */ H5_CHECKED_ASSIGN(chk_proxy->chunkno, unsigned, udata->oh->nchunks - 1, size_t); } /* end if */ else { /* Sanity check */ HDassert(udata->chunkno < udata->oh->nchunks); /* Set the chunk number for the chunk proxy */ chk_proxy->chunkno = udata->chunkno; /* Sanity check that the chunk representation we have in memory is * the same as the one being brought in from disk. */ HDassert(0 == HDmemcmp(image, udata->oh->chunk[chk_proxy->chunkno].image, udata->oh->chunk[chk_proxy->chunkno].size)); } /* end else */ /* Increment reference count of object header */ if(H5O__inc_rc(udata->oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "can't increment reference count on object header") chk_proxy->oh = udata->oh; /* Set return value */ ret_value = chk_proxy; done: if(NULL == ret_value) if(chk_proxy && H5O__chunk_dest(chk_proxy) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, NULL, "unable to destroy object header chunk") FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_deserialize() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_image_len * * Purpose: Return the on disk image size of a object header chunk to the * metadata cache via the image_len. * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_image_len(const void *_thing, size_t *image_len) { const H5O_chunk_proxy_t * chk_proxy = (const H5O_chunk_proxy_t *)_thing; /* Chunk proxy to query */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(chk_proxy); HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK); HDassert(chk_proxy->oh); HDassert(image_len); *image_len = chk_proxy->oh->chunk[chk_proxy->chunkno].size; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5O__cache_chk_image_len() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_serialize * * Purpose: Given a pointer to an instance of an object header chunk and an * appropriately sized buffer, serialize the contents of the * instance for writing to disk, and copy the serialized data * into the buffer. * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_serialize(const H5F_t *f, void *image, size_t len, void *_thing) { H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk to serialize */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(f); HDassert(image); HDassert(chk_proxy); HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK); HDassert(chk_proxy->oh); HDassert(chk_proxy->oh->chunk[chk_proxy->chunkno].size == len); /* Serialize messages for this chunk */ if(H5O__chunk_serialize(f, chk_proxy->oh, chk_proxy->chunkno) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSERIALIZE, FAIL, "unable to serialize object header continuation chunk") /* copy the chunk into the image -- this is potentially expensive. * Can we rework things so that the chunk and the cache share a buffer? */ H5MM_memcpy(image, chk_proxy->oh->chunk[chk_proxy->chunkno].image, len); done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_serialize() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_notify * * Purpose: Handle cache action notifications * * Return: Non-negative on success/Negative on failure * * Programmer: Neil Fortner * Mar 20 2012 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_notify(H5AC_notify_action_t action, void *_thing) { H5O_chunk_proxy_t *chk_proxy = (H5O_chunk_proxy_t *)_thing; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* * Check arguments. */ HDassert(chk_proxy); HDassert(chk_proxy->oh); switch(action) { case H5AC_NOTIFY_ACTION_AFTER_INSERT: case H5AC_NOTIFY_ACTION_AFTER_LOAD: if(chk_proxy->oh->swmr_write) { /* Add flush dependency on chunk with continuation, if one exists */ if(chk_proxy->fd_parent) { /* Sanity checks */ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type); HDassert((((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_ID) || (((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_CHK_ID)); /* Add flush dependency from chunk containing the continuation message * that points to this chunk (either oh or another chunk proxy object) */ if(H5AC_create_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") } /* end if */ /* Add flush dependency on object header */ { if(H5AC_create_flush_dependency(chk_proxy->oh, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTDEPEND, FAIL, "unable to create flush dependency") } /* end if */ /* Add flush dependency on object header proxy, if proxy exists */ { /* Sanity check */ HDassert(chk_proxy->oh->proxy); /* Register the object header chunk as a parent of the virtual entry */ if(H5AC_proxy_entry_add_parent(chk_proxy->oh->proxy, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add object header chunk as parent of proxy") } } /* end if */ break; case H5AC_NOTIFY_ACTION_AFTER_FLUSH: case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED: /* do nothing */ break; case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: { unsigned u; /* Local index variable */ /* Mark messages in chunk as clean */ for(u = 0; u < chk_proxy->oh->nmesgs; u++) if(chk_proxy->oh->mesg[u].chunkno == chk_proxy->chunkno) chk_proxy->oh->mesg[u].dirty = FALSE; } break; case H5AC_NOTIFY_ACTION_CHILD_DIRTIED: case H5AC_NOTIFY_ACTION_CHILD_CLEANED: case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED: case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED: /* do nothing */ break; case H5AC_NOTIFY_ACTION_BEFORE_EVICT: if(chk_proxy->oh->swmr_write) { /* Remove flush dependency on parent object header chunk, if one is set */ if(chk_proxy->fd_parent) { /* Sanity checks */ HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->magic == H5C__H5C_CACHE_ENTRY_T_MAGIC); HDassert(((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type); HDassert((((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_ID) || (((H5C_cache_entry_t *)(chk_proxy->fd_parent))->type->id == H5AC_OHDR_CHK_ID)); if(H5AC_destroy_flush_dependency(chk_proxy->fd_parent, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency") chk_proxy->fd_parent = NULL; } /* end if */ /* Unregister the object header as a parent of the virtual entry */ if(H5AC_destroy_flush_dependency(chk_proxy->oh, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency") /* Unregister the object header chunk as a parent of the virtual entry */ if(H5AC_proxy_entry_remove_parent(chk_proxy->oh->proxy, chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't remove object header chunk as parent of proxy") } /* end if */ break; default: #ifdef NDEBUG HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown action from metadata cache") #else /* NDEBUG */ HDassert(0 && "Unknown action?!?"); #endif /* NDEBUG */ } /* end switch */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_notify() */ /*------------------------------------------------------------------------- * Function: H5O__cache_chk_free_icr * * Purpose: Free the in core memory associated with the supplied object * header continuation chunk. * * Note: The metadata cache sets the object's cache_info.magic to * H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC before calling a free_icr * callback (checked in assert). * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: John Mainzer * 7/28/14 * *------------------------------------------------------------------------- */ static herr_t H5O__cache_chk_free_icr(void *_thing) { H5O_chunk_proxy_t * chk_proxy = (H5O_chunk_proxy_t *)_thing; /* Object header chunk proxy to release */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(chk_proxy); HDassert(chk_proxy->cache_info.magic == H5C__H5C_CACHE_ENTRY_T_BAD_MAGIC); HDassert(chk_proxy->cache_info.type == H5AC_OHDR_CHK); /* Destroy object header chunk proxy */ if(H5O__chunk_dest(chk_proxy) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header chunk proxy") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__cache_chk_free_icr() */ /*------------------------------------------------------------------------- * Function: H5O__add_cont_msg * * Purpose: Add information from a continuation message to the list of * continuation messages in the object header * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: Quincey Koziol * koziol@hdfgroup.org * July 12, 2008 * *------------------------------------------------------------------------- */ static herr_t H5O__add_cont_msg(H5O_cont_msgs_t *cont_msg_info, const H5O_cont_t *cont) { size_t contno; /* Continuation message index */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(cont_msg_info); HDassert(cont); /* Increase chunk array size, if necessary */ if(cont_msg_info->nmsgs >= cont_msg_info->alloc_nmsgs) { size_t na = MAX(H5O_NCHUNKS, cont_msg_info->alloc_nmsgs * 2); /* Double # of messages allocated */ H5O_cont_t *x; if(NULL == (x = H5FL_SEQ_REALLOC(H5O_cont_t, cont_msg_info->msgs, na))) HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "memory allocation failed") cont_msg_info->alloc_nmsgs = na; cont_msg_info->msgs = x; } /* end if */ /* Init the continuation message info */ contno = cont_msg_info->nmsgs++; cont_msg_info->msgs[contno].addr = cont->addr; cont_msg_info->msgs[contno].size = cont->size; cont_msg_info->msgs[contno].chunkno = cont->chunkno; done: FUNC_LEAVE_NOAPI(ret_value) } /* H5O__add_cont_msg() */ /*------------------------------------------------------------------------- * Function: H5O__prefix_deserialize() * * Purpose: Deserialize an object header prefix * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: Quincey Koziol * December 14, 2016 * *------------------------------------------------------------------------- */ static herr_t H5O__prefix_deserialize(const uint8_t *_image, H5O_cache_ud_t *udata) { const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ H5O_t *oh = NULL; /* Object header read in */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(image); HDassert(udata); /* Allocate space for the new object header data structure */ if(NULL == (oh = H5FL_CALLOC(H5O_t))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed") /* File-specific, non-stored information */ oh->sizeof_size = H5F_SIZEOF_SIZE(udata->common.f); oh->sizeof_addr = H5F_SIZEOF_ADDR(udata->common.f); /* Check for presence of magic number */ /* (indicates version 2 or later) */ if(!HDmemcmp(image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC)) { /* Magic number */ image += H5_SIZEOF_MAGIC; /* Version */ oh->version = *image++; if(H5O_VERSION_2 != oh->version) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") /* Flags */ oh->flags = *image++; if(oh->flags & ~H5O_HDR_ALL_FLAGS) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unknown object header status flag(s)") /* Number of links to object (unless overridden by refcount message) */ oh->nlink = 1; /* Time fields */ if(oh->flags & H5O_HDR_STORE_TIMES) { uint32_t tmp; /* Temporary value */ UINT32DECODE(image, tmp); oh->atime = (time_t)tmp; UINT32DECODE(image, tmp); oh->mtime = (time_t)tmp; UINT32DECODE(image, tmp); oh->ctime = (time_t)tmp; UINT32DECODE(image, tmp); oh->btime = (time_t)tmp; } /* end if */ else oh->atime = oh->mtime = oh->ctime = oh->btime = 0; /* Attribute fields */ if(oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) { UINT16DECODE(image, oh->max_compact); UINT16DECODE(image, oh->min_dense); if(oh->max_compact < oh->min_dense) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header attribute phase change values") } /* end if */ else { oh->max_compact = H5O_CRT_ATTR_MAX_COMPACT_DEF; oh->min_dense = H5O_CRT_ATTR_MIN_DENSE_DEF; } /* end else */ /* First chunk size */ switch(oh->flags & H5O_HDR_CHUNK0_SIZE) { case 0: /* 1 byte size */ udata->chunk0_size = *image++; break; case 1: /* 2 byte size */ UINT16DECODE(image, udata->chunk0_size); break; case 2: /* 4 byte size */ UINT32DECODE(image, udata->chunk0_size); break; case 3: /* 8 byte size */ UINT64DECODE(image, udata->chunk0_size); break; default: HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad size for chunk 0") } /* end switch */ if(udata->chunk0_size > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") } /* end if */ else { /* Version */ oh->version = *image++; if(H5O_VERSION_1 != oh->version) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "bad object header version number") /* Flags */ oh->flags = H5O_CRT_OHDR_FLAGS_DEF; /* Reserved */ image++; /* Number of messages */ UINT16DECODE(image, udata->v1_pfx_nmesgs); /* Link count */ UINT32DECODE(image, oh->nlink); /* Reset unused time fields */ oh->atime = oh->mtime = oh->ctime = oh->btime = 0; /* Reset unused attribute fields */ oh->max_compact = 0; oh->min_dense = 0; /* First chunk size */ UINT32DECODE(image, udata->chunk0_size); if((udata->v1_pfx_nmesgs > 0 && udata->chunk0_size < H5O_SIZEOF_MSGHDR_OH(oh)) || (udata->v1_pfx_nmesgs == 0 && udata->chunk0_size > 0)) HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "bad object header chunk size") /* Reserved, in version 1 (for 8-byte alignment padding) */ image += 4; } /* end else */ /* Verify object header prefix length */ HDassert((size_t)(image - _image) == (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); /* If udata->oh is to be freed (see H5O__cache_verify_chksum), save the pointer to udata->oh and free it later after setting udata->oh with the new object header */ if(udata->free_oh) { H5O_t *saved_oh = udata->oh; HDassert(udata->oh); /* Save the object header for later use in 'deserialize' callback */ udata->oh = oh; if(H5O__free(saved_oh) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't destroy object header") udata->free_oh = FALSE; } else /* Save the object header for later use in 'deserialize' callback */ udata->oh = oh; oh = NULL; done: /* Release the [possibly partially initialized] object header on errors */ if(ret_value < 0 && oh) if(H5O__free(oh) < 0) HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to destroy object header data") FUNC_LEAVE_NOAPI(ret_value) } /* end H5O__prefix_deserialize() */ /*------------------------------------------------------------------------- * Function: H5O__chunk_deserialize * * Purpose: Deserialize a chunk for an object header * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: Quincey Koziol * koziol@hdfgroup.org * July 12, 2008 * *------------------------------------------------------------------------- */ static herr_t H5O__chunk_deserialize(H5O_t *oh, haddr_t addr, size_t len, const uint8_t *image, H5O_common_cache_ud_t *udata, hbool_t *dirty) { const uint8_t *chunk_image; /* Pointer into buffer to decode */ uint8_t *eom_ptr; /* Pointer to end of messages for a chunk */ unsigned merged_null_msgs = 0; /* Number of null messages merged together */ unsigned chunkno; /* Current chunk's index */ #ifndef NDEBUG unsigned nullcnt; /* Count of null messages (for sanity checking gaps in chunks) */ #endif /* NDEBUG */ hbool_t mesgs_modified = FALSE; /* Whether any messages were modified when the object header was deserialized */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(oh); HDassert(H5F_addr_defined(addr)); HDassert(image); HDassert(udata->f); HDassert(udata->cont_msg_info); /* Increase chunk array size, if necessary */ if(oh->nchunks >= oh->alloc_nchunks) { size_t na = MAX(H5O_NCHUNKS, oh->alloc_nchunks * 2); /* Double # of chunks allocated */ H5O_chunk_t *x; if(NULL == (x = H5FL_SEQ_REALLOC(H5O_chunk_t, oh->chunk, na))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed") oh->alloc_nchunks = na; oh->chunk = x; } /* end if */ /* Init the chunk data info */ chunkno = (unsigned)oh->nchunks++; oh->chunk[chunkno].gap = 0; oh->chunk[chunkno].addr = addr; if(chunkno == 0) /* First chunk's 'image' includes room for the object header prefix */ oh->chunk[0].size = len + (size_t)H5O_SIZEOF_HDR(oh); else oh->chunk[chunkno].size = len; if(NULL == (oh->chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image, oh->chunk[chunkno].size))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed") oh->chunk[chunkno].chunk_proxy = NULL; /* Copy disk image into chunk's image */ H5MM_memcpy(oh->chunk[chunkno].image, image, oh->chunk[chunkno].size); /* Point into chunk image to decode */ chunk_image = oh->chunk[chunkno].image; /* Handle chunk 0 as special case */ if(chunkno == 0) /* Skip over [already decoded] prefix */ chunk_image += (size_t)(H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)); /* Check for magic # on chunks > 0 in later versions of the format */ else if(chunkno > 0 && oh->version > H5O_VERSION_1) { /* Magic number */ if(HDmemcmp(chunk_image, H5O_CHK_MAGIC, (size_t)H5_SIZEOF_MAGIC)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "wrong object header chunk signature") chunk_image += H5_SIZEOF_MAGIC; } /* end if */ /* Decode messages from this chunk */ eom_ptr = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM_OH(oh)); #ifndef NDEBUG nullcnt = 0; #endif /* NDEBUG */ while(chunk_image < eom_ptr) { size_t mesg_size; /* Size of message read in */ unsigned id; /* ID (type) of current message */ uint8_t flags; /* Flags for current message */ H5O_msg_crt_idx_t crt_idx = 0; /* Creation index for current message */ /* Decode message prefix info */ /* Version # */ if(oh->version == H5O_VERSION_1) UINT16DECODE(chunk_image, id) else id = *chunk_image++; /* Message size */ UINT16DECODE(chunk_image, mesg_size); if(mesg_size != H5O_ALIGN_OH(oh, mesg_size)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message not aligned") /* Message flags */ flags = *chunk_image++; if(flags & ~H5O_MSG_FLAG_BITS) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unknown flag for message") if((flags & H5O_MSG_FLAG_SHARED) && (flags & H5O_MSG_FLAG_DONTSHARE)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message") if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message") if((flags & H5O_MSG_FLAG_WAS_UNKNOWN) && !(flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "bad flag combination for message") /* Delay checking the "shareable" flag until we've made sure id * references a valid message class that this version of the library * knows about */ /* Reserved bytes/creation index */ if(oh->version == H5O_VERSION_1) chunk_image += 3; /*reserved*/ else { /* Only decode creation index if they are being tracked */ if(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) UINT16DECODE(chunk_image, crt_idx); } /* end else */ /* Try to detect invalidly formatted object header message that * extends past end of chunk. */ if(chunk_image + mesg_size > eom_ptr) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "corrupt object header") #ifndef NDEBUG /* Increment count of null messages */ if(H5O_NULL_ID == id) nullcnt++; #endif /* NDEBUG */ /* Check for combining two adjacent 'null' messages */ if((udata->file_intent & H5F_ACC_RDWR) && H5O_NULL_ID == id && oh->nmesgs > 0 && H5O_NULL_ID == oh->mesg[oh->nmesgs - 1].type->id && oh->mesg[oh->nmesgs - 1].chunkno == chunkno) { size_t mesgno; /* Current message to operate on */ /* Combine adjacent null messages */ mesgno = oh->nmesgs - 1; oh->mesg[mesgno].raw_size += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + mesg_size; oh->mesg[mesgno].dirty = TRUE; merged_null_msgs++; } /* end if */ else { H5O_mesg_t *mesg; /* Pointer to new message */ unsigned ioflags = 0; /* Flags for decode routine */ /* Check if we need to extend message table to hold the new message */ if(oh->nmesgs >= oh->alloc_nmesgs) if(H5O__alloc_msgs(oh, (size_t)1) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "can't allocate more space for messages") /* Get pointer to message to set up */ mesg = &oh->mesg[oh->nmesgs]; /* Increment # of messages */ oh->nmesgs++; /* Initialize information about message */ mesg->dirty = FALSE; mesg->flags = flags; mesg->crt_idx = crt_idx; mesg->native = NULL; mesg->raw = (uint8_t *)chunk_image; /* Casting away const OK - QAK */ mesg->raw_size = mesg_size; mesg->chunkno = chunkno; /* Point unknown messages at 'unknown' message class */ /* (Usually from future versions of the library) */ if(id >= H5O_UNKNOWN_ID || #ifdef H5O_ENABLE_BOGUS id == H5O_BOGUS_VALID_ID || #endif NULL == H5O_msg_class_g[id]) { H5O_unknown_t *unknown; /* Pointer to "unknown" message info */ /* Allocate "unknown" message info */ if(NULL == (unknown = H5FL_MALLOC(H5O_unknown_t))) HGOTO_ERROR(H5E_OHDR, H5E_CANTALLOC, FAIL, "memory allocation failed") /* Save the original message type ID */ *unknown = id; /* Save 'native' form of unknown message */ mesg->native = unknown; /* Set message to "unknown" class */ mesg->type = H5O_msg_class_g[H5O_UNKNOWN_ID]; /* Check for "fail if unknown" message flags */ if(((udata->file_intent & H5F_ACC_RDWR) && (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE)) || (flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS)) HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "unknown message with 'fail if unknown' flag found") /* Check for "mark if unknown" message flag, etc. */ else if((flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) && !(flags & H5O_MSG_FLAG_WAS_UNKNOWN) && (udata->file_intent & H5F_ACC_RDWR)) { /* Mark the message as "unknown" */ /* This is a bit aggressive, since the application may * never change anything about the object (metadata or * raw data), but we can sort out the finer details * when/if we start using the flag - QAK */ /* Also, it's possible that this functionality may not * get invoked if the object header is brought into * the metadata cache in some other "weird" way, like * using H5Ocopy() - QAK */ mesg->flags |= H5O_MSG_FLAG_WAS_UNKNOWN; /* Mark the message and chunk as dirty */ mesg->dirty = TRUE; mesgs_modified = TRUE; } /* end if */ } /* end if */ else { /* Check for message of unshareable class marked as "shareable" */ if((flags & H5O_MSG_FLAG_SHAREABLE) && H5O_msg_class_g[id] && !(H5O_msg_class_g[id]->share_flags & H5O_SHARE_IS_SHARABLE)) HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "message of unshareable class flagged as shareable") /* Set message class for "known" messages */ mesg->type = H5O_msg_class_g[id]; } /* end else */ /* Do some inspection/interpretation of new messages from this chunk */ /* (detect continuation messages, ref. count messages, etc.) */ /* Check if message is a continuation message */ if(H5O_CONT_ID == id) { H5O_cont_t *cont; /* Decode continuation message */ cont = (H5O_cont_t *)(H5O_MSG_CONT->decode)(udata->f, NULL, 0, &ioflags, mesg->raw_size, mesg->raw); H5_CHECKED_ASSIGN(cont->chunkno, unsigned, udata->cont_msg_info->nmsgs + 1, size_t); /* the next continuation message/chunk */ /* Save 'native' form of continuation message */ mesg->native = cont; /* Add to continuation messages left to interpret */ if(H5O__add_cont_msg(udata->cont_msg_info, cont) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't add continuation message") } /* end if */ /* Check if message is a ref. count message */ else if(H5O_REFCOUNT_ID == id) { H5O_refcount_t *refcount; /* Decode ref. count message */ if(oh->version <= H5O_VERSION_1) HGOTO_ERROR(H5E_OHDR, H5E_VERSION, FAIL, "object header version does not support reference count message") refcount = (H5O_refcount_t *)(H5O_MSG_REFCOUNT->decode)(udata->f, NULL, 0, &ioflags, mesg->raw_size, mesg->raw); /* Save 'native' form of ref. count message */ mesg->native = refcount; /* Set object header values */ oh->has_refcount_msg = TRUE; if(!refcount) HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't decode refcount") oh->nlink = *refcount; } /* end if */ /* Check if message is a link message */ else if(H5O_LINK_ID == id) { /* Increment the count of link messages */ oh->link_msgs_seen++; } /* end if */ /* Check if message is an attribute message */ else if(H5O_ATTR_ID == id) { /* Increment the count of attribute messages */ oh->attr_msgs_seen++; } /* end if */ /* Mark the message & chunk as dirty if the message was changed by decoding */ if((ioflags & H5O_DECODEIO_DIRTY) && (udata->file_intent & H5F_ACC_RDWR)) { mesg->dirty = TRUE; mesgs_modified = TRUE; } /* end if */ } /* end else */ /* Advance decode pointer past message */ chunk_image += mesg_size; /* Check for 'gap' at end of chunk */ if((eom_ptr - chunk_image) > 0 && (eom_ptr - chunk_image) < H5O_SIZEOF_MSGHDR_OH(oh)) { /* Gaps can only occur in later versions of the format */ HDassert(oh->version > H5O_VERSION_1); /* Gaps should only occur in chunks with no null messages */ HDassert(nullcnt == 0); /* Set gap information for chunk */ oh->chunk[chunkno].gap = (size_t)(eom_ptr - chunk_image); /* Increment location in chunk */ chunk_image += oh->chunk[chunkno].gap; } /* end if */ } /* end while */ /* Check for correct checksum on chunks, in later versions of the format */ if(oh->version > H5O_VERSION_1) { uint32_t stored_chksum; /* Checksum from file */ /* checksum verification already done in verify_chksum cb */ /* Metadata checksum */ UINT32DECODE(chunk_image, stored_chksum); } /* end if */ /* Sanity check */ HDassert(chunk_image == oh->chunk[chunkno].image + oh->chunk[chunkno].size); /* Mark the chunk dirty if we've modified messages */ if(mesgs_modified) *dirty = TRUE; /* Mark the chunk dirty if we've merged null messages */ if(merged_null_msgs > 0) { udata->merged_null_msgs += merged_null_msgs; *dirty = TRUE; } /* end if */ done: if(ret_value < 0 && udata->cont_msg_info->msgs) { udata->cont_msg_info->msgs = H5FL_SEQ_FREE(H5O_cont_t, udata->cont_msg_info->msgs); udata->cont_msg_info->alloc_nmsgs = 0; } FUNC_LEAVE_NOAPI(ret_value) } /* H5O__chunk_deserialize() */ /*------------------------------------------------------------------------- * Function: H5O__chunk_serialize * * Purpose: Serialize a chunk for an object header * * Return: Success: SUCCEED * Failure: FAIL * * Programmer: Quincey Koziol * koziol@hdfgroup.org * July 12, 2008 * *------------------------------------------------------------------------- */ static herr_t H5O__chunk_serialize(const H5F_t *f, H5O_t *oh, unsigned chunkno) { H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(f); HDassert(oh); /* Encode any dirty messages in this chunk */ for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) if(curr_msg->dirty && curr_msg->chunkno == chunkno) /* Casting away const OK -QAK */ if(H5O_msg_flush((H5F_t *)f, oh, curr_msg) < 0) HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message") /* Sanity checks */ if(oh->version > H5O_VERSION_1) /* Make certain the magic # is present */ HDassert(!HDmemcmp(oh->chunk[chunkno].image, (chunkno == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC)); else /* Gaps should never occur in version 1 of the format */ HDassert(oh->chunk[chunkno].gap == 0); /* Extra work, for later versions of the format */ if(oh->version > H5O_VERSION_1) { uint32_t metadata_chksum; /* Computed metadata checksum value */ uint8_t *chunk_image; /* Pointer into object header chunk */ /* Check for gap in chunk & zero it out */ if(oh->chunk[chunkno].gap) HDmemset((oh->chunk[chunkno].image + oh->chunk[chunkno].size) - (H5O_SIZEOF_CHKSUM + oh->chunk[chunkno].gap), 0, oh->chunk[chunkno].gap); /* Compute metadata checksum */ metadata_chksum = H5_checksum_metadata(oh->chunk[chunkno].image, (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM), 0); /* Metadata checksum */ chunk_image = oh->chunk[chunkno].image + (oh->chunk[chunkno].size - H5O_SIZEOF_CHKSUM); UINT32ENCODE(chunk_image, metadata_chksum); } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5O__chunk_serialize() */