Source
1
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+
* Copyright by The HDF Group. *
3
+
* Copyright by the Board of Trustees of the University of Illinois. *
4
+
* All rights reserved. *
5
+
* *
6
+
* This file is part of HDF5. The full HDF5 copyright notice, including *
7
+
* terms governing use, modification, and redistribution, is contained in *
8
+
* the files COPYING and Copyright.html. COPYING can be found at the root *
9
+
* of the source code distribution tree; Copyright.html can be found at the *
10
+
* root level of an installed copy of the electronic HDF5 document set and *
11
+
* is linked from the top-level documents page. It can also be found at *
12
+
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
13
+
* access to either file, you may request a copy from help@hdfgroup.org. *
14
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
+
16
+
/* This program demonstrates how to create and use "external links" in
17
+
* HDF5.
18
+
*
19
+
* External links point from one HDF5 file to an object (Group, Dataset, or
20
+
* committed Datatype) in another file.
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
+
/* Basic external link example
50
+
*
51
+
* Creates two files and uses an external link to access an object in the
52
+
* second file from the first file.
53
+
*/
54
+
static void extlink_example(void)
55
+
{
56
+
hid_t source_file_id, targ_file_id;
57
+
hid_t group_id, group2_id;
58
+
59
+
/* Create two files, a source and a target */
60
+
source_file_id = H5Fcreate(SOURCE_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
61
+
targ_file_id = H5Fcreate(TARGET_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
62
+
63
+
/* Create a group in the target file for the external link to point to. */
64
+
group_id = H5Gcreate2(targ_file_id, "target_group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
65
+
66
+
/* Close the group and the target file */
67
+
H5Gclose(group_id);
68
+
69
+
/* Create an external link in the source file pointing to the target group.
70
+
* We could instead have created the external link first, then created the
71
+
* group it points to; the order doesn't matter.
72
+
*/
73
+
H5Lcreate_external(TARGET_FILE, "target_group", source_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);
74
+
75
+
/* Now we can use the external link to create a new group inside the
76
+
* target group (even though the target file is closed!). The external
77
+
* link works just like a soft link.
78
+
*/
79
+
group_id = H5Gcreate2(source_file_id, "ext_link/new_group", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
80
+
81
+
/* The group is inside the target file and we can access it normally.
82
+
* Here, group_id and group2_id point to the same group inside the
83
+
* target file.
84
+
*/
85
+
group2_id = H5Gopen2(targ_file_id, "target_group/new_group", H5P_DEFAULT);
86
+
87
+
/* Don't forget to close the IDs we opened. */
88
+
H5Gclose(group2_id);
89
+
H5Gclose(group_id);
90
+
91
+
H5Fclose(targ_file_id);
92
+
H5Fclose(source_file_id);
93
+
94
+
/* The link from the source file to the target file will work as long as
95
+
* the target file can be found. If the target file is moved, renamed,
96
+
* or deleted in the filesystem, HDF5 won't be able to find it and the
97
+
* external link will "dangle."
98
+
*/
99
+
}
100
+
101
+
•
102
+
/* External link prefix example
103
+
*
104
+
* Uses a group access property list to set a "prefix" for the filenames
105
+
* accessed through an external link.
106
+
*
107
+
* Group access property lists inherit from link access property lists;
108
+
* the external link prefix property is actually a property of LAPLs.
109
+
*
110
+
* This example requires a "red" directory and a "blue" directory to exist
111
+
* where it is run (so to run this example on Unix, first mkdir red and mkdir
112
+
* blue).
113
+
*/
114
+
static void extlink_prefix_example(void)
115
+
{
116
+
hid_t source_file_id, red_file_id, blue_file_id;
117
+
hid_t group_id, group2_id;
118
+
hid_t gapl_id;
119
+
120
+
/* Create three files, a source and two targets. The targets will have
121
+
* the same name, but one will be located in the red directory and one will
122
+
* be located in the blue directory */
123
+
source_file_id = H5Fcreate(PREFIX_SOURCE_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
124
+
red_file_id = H5Fcreate("red/prefix_target.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
125
+
blue_file_id = H5Fcreate("blue/prefix_target.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
126
+
127
+
/* This test needs a red and a blue directory in the filesystem. If they're not present,
128
+
* trying to create the files above will fail.
129
+
*/
130
+
if(red_file_id < 0 || blue_file_id < 0)
131
+
printf("This test requires directories named 'red' and 'blue' to exist. Did you forget to create them?\n");
132
+
133
+
/* Create an external link in the source file pointing to the root group of
134
+
* a file named prefix_target.h5. This file doesn't exist in the current
135
+
* directory, but the files in the red and blue directories both have this
136
+
* name.
137
+
*/
138
+
H5Lcreate_external("prefix_target.h5", "/", source_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);
139
+
140
+
/* If we tried to traverse the external link now, we would fail (since the
141
+
* file it points to doesn't exist). Instead, we'll create a group access
142
+
* property list that will provide a prefix path to the external link.
143
+
* Group access property lists inherit the properties of link access
144
+
* property lists.
145
+
*/
146
+
gapl_id = H5Pcreate(H5P_GROUP_ACCESS);
147
+
H5Pset_elink_prefix(gapl_id, "red/");
148
+
149
+
/* Now if we traverse the external link, HDF5 will look for an external
150
+
* file named red/prefix_target.h5, which exists.
151
+
* To pass the group access property list, we need to use H5Gopen2.
152
+
*/
153
+
group_id = H5Gopen2(source_file_id, "ext_link", gapl_id);
154
+
155
+
/* Now we can use the open group ID to create a new group inside the
156
+
* "red" file.
157
+
*/
158
+
group2_id = H5Gcreate2(group_id, "pink", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
159
+
160
+
/* Close both groups. */
161
+
H5Gclose(group2_id);
162
+
H5Gclose(group_id);
163
+
164
+
/* If we change the prefix, the same external link can find a file in the blue
165
+
* directory.
166
+
*/
167
+
H5Pset_elink_prefix(gapl_id, "blue/");
168
+
group_id = H5Gopen2(source_file_id, "ext_link", gapl_id);
169
+
group2_id = H5Gcreate2(group_id, "sky blue", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
170
+
171
+
/* Close both groups. */
172
+
H5Gclose(group2_id);
173
+
H5Gclose(group_id);
174
+
175
+
/* Each file has had a group created inside it using the same external link. */
176
+
group_id = H5Gopen2(red_file_id, "pink", H5P_DEFAULT);
177
+
group2_id = H5Gopen2(blue_file_id, "sky blue", H5P_DEFAULT);
178
+
179
+
/* Clean up our open IDs */
180
+
H5Gclose(group2_id);
181
+
H5Gclose(group_id);
182
+
H5Pclose(gapl_id);
183
+
H5Fclose(blue_file_id);
184
+
H5Fclose(red_file_id);
185
+
H5Fclose(source_file_id);
186
+
187
+
/* User-defined links can expand on the ability to pass in parameters
188
+
* using an access property list; for instance, a user-defined link
189
+
* might function like an external link but allow the full filename to be
190
+
* passed in through the access property list.
191
+
*/
192
+
}
193
+
194
+
•
195
+
/* Soft Link example
196
+
*
197
+
* Create a new class of user-defined links that behave like HDF5's built-in
198
+
* soft links.
199
+
*
200
+
* This isn't very useful by itself (HDF5's soft links already do the same
201
+
* thing), but it can serve as an example for how to reference objects by
202
+
* name.
203
+
*/
204
+
205
+
/* We need to define the callback function that the soft link will use.
206
+
* It is defined after the example below.
207
+
* To keep the example simple, these links don't have a query callback.
208
+
* In general, link classes should always be query-able.
209
+
* We might also have wanted to supply a creation callback that checks
210
+
* that a path was supplied in the udata.
211
+
*/
212
+
static hid_t UD_soft_traverse(const char *link_name, hid_t cur_group,
213
+
const void *udata, size_t udata_size, hid_t lapl_id);
214
+
215
+
static void soft_link_example(void)
216
+
{
217
+
hid_t file_id;
218
+
hid_t group_id;
219
+
/* Define the link class that we'll use to register "user-defined soft
220
+
* links" using the callbacks we defined above.
221
+
* A link class can have NULL for any callback except its traverse
222
+
* callback.
223
+
*/
224
+
const H5L_class_t UD_soft_class[1] = {{
225
+
H5L_LINK_CLASS_T_VERS, /* Version number for this struct.
226
+
* This field is always H5L_LINK_CLASS_T_VERS */
227
+
(H5L_type_t)UD_SOFT_CLASS, /* Link class id number. This can be any
228
+
* value between H5L_TYPE_UD_MIN (64) and
229
+
* H5L_TYPE_MAX (255). It should be a
230
+
* value that isn't already being used by
231
+
* another kind of link. We'll use 65. */
232
+
"UD_soft_link", /* Link class name for debugging */
233
+
NULL, /* Creation callback */
234
+
NULL, /* Move callback */
235
+
NULL, /* Copy callback */
236
+
UD_soft_traverse, /* The actual traversal function */
237
+
NULL, /* Deletion callback */
238
+
NULL /* Query callback */
239
+
}};
240
+
241
+
242
+
/* First, create a file and an object within the file for the link to
243
+
* point to.
244
+
*/
245
+
file_id = H5Fcreate(SOFT_LINK_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
246
+
group_id = H5Gcreate2(file_id, TARGET_GROUP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
247
+
H5Gclose(group_id);
248
+
249
+
/* This is how we create a normal soft link to the group.
250
+
*/
251
+
H5Lcreate_soft(TARGET_GROUP, file_id, SOFT_LINK_NAME, H5P_DEFAULT, H5P_DEFAULT);
252
+
253
+
/* To do the same thing using a user-defined link, we first have to
254
+
* register the link class we defined.
255
+
*/
256
+
H5Lregister(UD_soft_class);
257
+
258
+
/* Now create a user-defined link. We give it the path to the group
259
+
* as its udata.1
260
+
*/
261
+
H5Lcreate_ud(file_id, UD_SOFT_LINK_NAME, (H5L_type_t)UD_SOFT_CLASS, TARGET_GROUP,
262
+
strlen(TARGET_GROUP) + 1, H5P_DEFAULT, H5P_DEFAULT);
263
+
264
+
/* We can access the group through the UD soft link like we would through
265
+
* a normal soft link. This link will still dangle if the object's
266
+
* original name is changed or unlinked.
267
+
*/
268
+
group_id = H5Gopen2(file_id, UD_SOFT_LINK_NAME, H5P_DEFAULT);
269
+
270
+
/* The group is now open normally. Don't forget to close it! */
271
+
H5Gclose(group_id);
272
+
273
+
H5Fclose(file_id);
274
+
}
275
+
276
+
/* UD_soft_traverse
277
+
* The actual traversal function simply needs to open the correct object by
278
+
* name and return its ID.
279
+
*/
280
+
•
281
+
static hid_t UD_soft_traverse(const char *link_name, hid_t cur_group,
282
+
const void *udata, size_t udata_size, hid_t lapl_id)
283
+
{
284
+
const char *target = (const char *) udata;
285
+
hid_t ret_value;
286
+
287
+
/* Pass the udata straight through to HDF5. If it's invalid, let HDF5
288
+
* return an error.
289
+
*/
290
+
ret_value = H5Oopen(cur_group, target, lapl_id);
291
+
return ret_value;
292
+
}
293
+
294
+
295
+
/* Hard Link example
296
+
*
297
+
* Create a new class of user-defined links that behave like HDF5's built-in
298
+
* hard links.
299
+
*
300
+
* This isn't very useful by itself (HDF5's hard links already do the same
301
+
* thing), but it can serve as an example for how to reference objects by
302
+
* address.
303
+
*/
304
+
305
+
/* We need to define the callback functions that the hard link will use.
306
+
* These are defined after the example below.
307
+
* To keep the example simple, these links don't have a query callback.
308
+
* Generally, real link classes should always be query-able.
309
+
*/
310
+
static herr_t UD_hard_create(const char *link_name, hid_t loc_group,
311
+
const void *udata, size_t udata_size, hid_t lcpl_id);
312
+
static herr_t UD_hard_delete(const char *link_name, hid_t loc_group,
313
+
const void *udata, size_t udata_size);
314
+
static hid_t UD_hard_traverse(const char *link_name, hid_t cur_group,
315
+
const void *udata, size_t udata_size, hid_t lapl_id);
316
+
317
+
static void hard_link_example(void)
318
+
{
319
+
hid_t file_id;
320
+
hid_t group_id;
321
+
H5L_info_t li;
322
+
/* Define the link class that we'll use to register "user-defined hard
323
+
* links" using the callbacks we defined above.
324
+
* A link class can have NULL for any callback except its traverse
325
+
* callback.
326
+
*/
327
+
const H5L_class_t UD_hard_class[1] = {{
328
+
H5L_LINK_CLASS_T_VERS, /* Version number for this struct.
329
+
* This field is always H5L_LINK_CLASS_T_VERS */
330
+
(H5L_type_t)UD_HARD_CLASS, /* Link class id number. This can be any
331
+
* value between H5L_TYPE_UD_MIN (64) and
332
+
* H5L_TYPE_MAX (255). It should be a
333
+
* value that isn't already being used by
334
+
* another kind of link. We'll use 66. */
335
+
"UD_hard_link", /* Link class name for debugging */
336
+
UD_hard_create, /* Creation callback */
337
+
NULL, /* Move callback */
338
+
NULL, /* Copy callback */
339
+
UD_hard_traverse, /* The actual traversal function */
340
+
UD_hard_delete, /* Deletion callback */
341
+
NULL /* Query callback */
342
+
}};
343
+
344
+
345
+
/* First, create a file and an object within the file for the link to
346
+
* point to.
347
+
*/
348
+
file_id = H5Fcreate(HARD_LINK_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
349
+
group_id = H5Gcreate2(file_id, TARGET_GROUP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
350
+
H5Gclose(group_id);
351
+
352
+
/* This is how we create a normal hard link to the group. This
353
+
* creates a second "name" for the group.
354
+
*/
355
+
H5Lcreate_hard(file_id, TARGET_GROUP, file_id, HARD_LINK_NAME, H5P_DEFAULT, H5P_DEFAULT);
356
+
357
+
/* To do the same thing using a user-defined link, we first have to
358
+
* register the link class we defined.
359
+
*/
360
+
H5Lregister(UD_hard_class);
361
+
362
+
/* Since hard links link by object address, we'll need to retrieve
363
+
* the target group's address. We do this by calling H5Lget_info
364
+
* on a hard link to the object.
365
+
*/
366
+
H5Lget_info(file_id, TARGET_GROUP, &li, H5P_DEFAULT);
367
+
368
+
/* Now create a user-defined link. We give it the group's address
369
+
* as its udata.
370
+
*/
371
+
H5Lcreate_ud(file_id, UD_HARD_LINK_NAME, (H5L_type_t)UD_HARD_CLASS, &(li.u.address),
372
+
sizeof(li.u.address), H5P_DEFAULT, H5P_DEFAULT);
373
+
374
+
/* The UD hard link has now incremented the group's reference count
375
+
* like a normal hard link would. This means that we can unlink the
376
+
* other two links to that group and it won't be deleted until the
377
+
* UD hard link is deleted.
378
+
*/
379
+
H5Ldelete(file_id, TARGET_GROUP, H5P_DEFAULT);
380
+
H5Ldelete(file_id, HARD_LINK_NAME, H5P_DEFAULT);
381
+
382
+
/* The group is still accessible through the UD hard link. If this were
383
+
* a soft link instead, the object would have been deleted when the last
384
+
* hard link to it was unlinked. */
385
+
group_id = H5Gopen2(file_id, UD_HARD_LINK_NAME, H5P_DEFAULT);
386
+
387
+
/* The group is now open normally. Don't forget to close it! */
388
+
H5Gclose(group_id);
389
+
390
+
/* Removing the user-defined hard link will delete the group. */
391
+
H5Ldelete(file_id, UD_HARD_LINK_NAME, H5P_DEFAULT);
392
+
393
+
H5Fclose(file_id);
394
+
}
395
+
396
+
/* Callbacks for User-defined hard links. */
397
+
/* UD_hard_create
398
+
* The most important thing this callback does is to increment the reference
399
+
* count on the target object. Without this step, the object could be
400
+
* deleted while this link still pointed to it, resulting in possible data
401
+
* corruption!
402
+
* The create callback also checks the arguments used to create this link.
403
+
* If this function returns a negative value, the call to H5Lcreate_ud()
404
+
* will also return failure and the link will not be created.
405
+
*/
406
+
static herr_t UD_hard_create(const char *link_name, hid_t loc_group,
407
+
const void *udata, size_t udata_size, hid_t lcpl_id)
408
+
{
409
+
haddr_t addr;
410
+
hid_t target_obj = -1;
411
+
herr_t ret_value = 0;
412
+
413
+
/* Make sure that the address passed in looks valid */
414
+
if(udata_size != sizeof(haddr_t))
415
+
{
416
+
ret_value = -1;
417
+
goto done;
418
+
}
419
+
420
+
addr = *((const haddr_t *) udata);
421
+
422
+
/* Open the object this link points to so that we can increment
423
+
* its reference count. This also ensures that the address passed
424
+
* in points to a real object (although this check is not perfect!) */
425
+
target_obj= H5Oopen_by_addr(loc_group, addr);
426
+
if(target_obj < 0)
427
+
{
428
+
ret_value = -1;
429
+
goto done;
430
+
}
431
+
432
+
/* Increment the reference count of the target object */
433
+
if(H5Oincr_refcount(target_obj) < 0)
434
+
{
435
+
ret_value = -1;
436
+
goto done;
437
+
}
438
+
439
+
done:
440
+
/* Close the target object if we opened it */
441
+
if(target_obj >= 0)
442
+
H5Oclose(target_obj);
443
+
return ret_value;
444
+
}
445
+
446
+
/* UD_hard_delete
447
+
* Since the creation function increments the object's reference count, it's
448
+
* important to decrement it again when the link is deleted.
449
+
*/
450
+
static herr_t UD_hard_delete(const char *link_name, hid_t loc_group,
451
+
const void *udata, size_t udata_size)
452
+
{
453
+
haddr_t addr;
454
+
hid_t target_obj = -1;
455
+
herr_t ret_value = 0;
456
+
457
+
/* Sanity check; we have already verified the udata's size in the creation
458
+
* callback.
459
+
*/
460
+
if(udata_size != sizeof(haddr_t))
461
+
{
462
+
ret_value = -1;
463
+
goto done;
464
+
}
465
+
466
+
addr = *((const haddr_t *) udata);
467
+
468
+
/* Open the object this link points to */
469
+
target_obj= H5Oopen_by_addr(loc_group, addr);
470
+
if(target_obj < 0)
471
+
{
472
+
ret_value = -1;
473
+
goto done;
474
+
}
475
+
476
+
/* Decrement the reference count of the target object */
477
+
if(H5Odecr_refcount(target_obj) < 0)
478
+
{
479
+
ret_value = -1;
480
+
goto done;
481
+
}
482
+
483
+
done:
484
+
/* Close the target object if we opened it */
485
+
if(target_obj >= 0)
486
+
H5Oclose(target_obj);
487
+
return ret_value;
488
+
}
489
+
490
+
/* UD_hard_traverse
491
+
* The actual traversal function simply needs to open the correct object and
492
+
* return its ID.
493
+
*/
494
+
static hid_t UD_hard_traverse(const char *link_name, hid_t cur_group,
495
+
const void *udata, size_t udata_size, hid_t lapl_id)
496
+
{
497
+
haddr_t addr;
498
+
hid_t ret_value = -1;
499
+
500
+
/* Sanity check; we have already verified the udata's size in the creation
501
+
* callback.
502
+
*/
503
+
if(udata_size != sizeof(haddr_t))
504
+
return -1;
505
+
506
+
addr = *((const haddr_t *) udata);
507
+
508
+
/* Open the object by address. If H5Oopen_by_addr fails, ret_value will
509
+
* be negative to indicate that the traversal function failed.
510
+
*/
511
+
ret_value = H5Oopen_by_addr(cur_group, addr);
512
+
513
+
return ret_value;
514
+
}
515
+
516
+
•
517
+
518
+
/* Plist example
519
+
*
520
+
* Create a new class of user-defined links that open objects within a file
521
+
* based on a value passed in through a link access property list.
522
+
*
523
+
* Group, dataset, and datatype access property lists all inherit from link
524
+
* access property lists, so they can be used instead of LAPLs.
525
+
*/
526
+
527
+
/* We need to define the callback functions that this link type will use.
528
+
* These are defined after the example below.
529
+
* These links have no udata, so they don't need a query function.
530
+
*/
531
+
static hid_t UD_plist_traverse(const char *link_name, hid_t cur_group,
532
+
const void *udata, size_t udata_size, hid_t lapl_id);
533
+
534
+
static void plist_link_example(void)
535
+
{
536
+
hid_t file_id;
537
+
hid_t group_id, group2_id;
538
+
hid_t gapl_id;
539
+
char *path = NULL;
540
+
541
+
/* Define the link class that we'll use to register "plist
542
+
* links" using the callback we defined above.
543
+
* A link class can have NULL for any callback except its traverse
544
+
* callback.
545
+
*/
546
+
const H5L_class_t UD_plist_class[1] = {{
547
+
H5L_LINK_CLASS_T_VERS, /* Version number for this struct.
548
+
* This field is always H5L_LINK_CLASS_T_VERS */
549
+
(H5L_type_t)UD_PLIST_CLASS, /* Link class id number. This can be any
550
+
* value between H5L_TYPE_UD_MIN (64) and
551
+
* H5L_TYPE_MAX (255). It should be a
552
+
* value that isn't already being used by
553
+
* another kind of link. We'll use 67. */
554
+
"UD_plist_link", /* Link class name for debugging */
555
+
NULL, /* Creation callback */
556
+
NULL, /* Move callback */
557
+
NULL, /* Copy callback */
558
+
UD_plist_traverse, /* The actual traversal function */
559
+
NULL, /* Deletion callback */
560
+
NULL /* Query callback */
561
+
}};
562
+
563
+
564
+
/* First, create a file and two objects within the file for the link to
565
+
* point to.
566
+
*/
567
+
file_id = H5Fcreate(HARD_LINK_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
568
+
group_id = H5Gcreate2(file_id, "group_1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
569
+
H5Gclose(group_id);
570
+
group_id = H5Gcreate2(file_id, "group_1/group_2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
571
+
H5Gclose(group_id);
572
+
573
+
/* Register "plist links" and create one. It has no udata at all. */
574
+
H5Lregister(UD_plist_class);
575
+
H5Lcreate_ud(file_id, "plist_link", (H5L_type_t)UD_PLIST_CLASS, NULL, 0,
576
+
H5P_DEFAULT, H5P_DEFAULT);
577
+
578
+
/* Create a group access property list to pass in the target for the
579
+
* plist link.
580
+
*/
581
+
gapl_id = H5Pcreate(H5P_GROUP_ACCESS);
582
+
583
+
/* There is no HDF5 API for setting the property that controls these
584
+
* links, so we have to add the property manually
585
+
*/
586
+
H5Pinsert2(gapl_id, PLIST_LINK_PROP, sizeof(const char *), &(path), NULL, NULL, NULL, NULL, NULL, NULL);
587
+
588
+
/* Set the property to point to the first group. */
589
+
path = "group_1";
590
+
H5Pset(gapl_id, PLIST_LINK_PROP, &path);
591
+
592
+
/* Open the first group through the plist link using the GAPL we just
593
+
* created */
594
+
group_id = H5Gopen2(file_id, "plist_link", gapl_id);
595
+
596
+
/* If we change the value set on the property list, it will change where
597
+
* the plist link points.
598
+
*/
599
+
path = "group_1/group_2";
600
+
H5Pset(gapl_id, PLIST_LINK_PROP, &path);
601
+
group2_id = H5Gopen2(file_id, "plist_link", gapl_id);
602
+
603
+
/* group_id points to group_1 and group2_id points to group_2, both opened
604
+
* through the same link.
605
+
* Using more than one of this type of link could quickly become confusing,
606
+
* since they will all use the same property list; however, there is
607
+
* nothing to prevent the links from changing the property list in their
608
+
* traverse callbacks.
609
+
*/
610
+
611
+
/* Clean up */
612
+
H5Pclose(gapl_id);
613
+
H5Gclose(group_id);
614
+
H5Gclose(group2_id);
615
+
H5Fclose(file_id);
616
+
}
617
+
618
+
/* Traversal callback for User-defined plist links. */
619
+
/* UD_plist_traverse
620
+
* Open a path passed in through the property list.
621
+
*/
622
+
static hid_t UD_plist_traverse(const char *link_name, hid_t cur_group,
623
+
const void *udata, size_t udata_size, hid_t lapl_id)
624
+
{
625
+
char * path;
626
+
hid_t ret_value = -1;
627
+
628
+
/* If the link property isn't set or can't be found, traversal fails. */
629
+
if(H5Pexist(lapl_id, PLIST_LINK_PROP) < 0)
630
+
goto error;
631
+
632
+
if(H5Pget(lapl_id, PLIST_LINK_PROP, &path) < 0)
633
+
goto error;
634
+
635
+
/* Open the object by address. If H5Oopen_by_addr fails, ret_value will
636
+
* be negative to indicate that the traversal function failed.
637
+
*/
638
+
ret_value = H5Oopen(cur_group, path, lapl_id);
639
+
640
+
return ret_value;
641
+
642
+
error:
643
+
return -1;
644
+
}
645
+
646
+
•
647
+
648
+
/* Main function
649
+
*
650
+
* Invokes the example functions.
651
+
*/
652
+
int
653
+
main(void)
654
+
{
655
+
printf("Testing basic external links.\n");
656
+
extlink_example();
657
+
658
+
printf("Testing external link prefixes.\n");
659
+
extlink_prefix_example();
660
+
661
+
printf("Testing user-defined soft links.\n");
662
+
soft_link_example();
663
+
664
+
printf("Testing user-defined hard links.\n");
665
+
hard_link_example();
666
+
667
+
printf("Testing user-defined property list links.\n");
668
+
plist_link_example();
669
+
670
+
return 0;
671
+
}
672
+
673
+