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 COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*
15  * Programmer:	Robb Matzke <matzke@llnl.gov>
16  *		Wednesday, April  1, 1998
17  *
18  * Purpose:	Functions that operate on a shared message.  The shared
19  *		message doesn't ever actually appear in the object header as
20  *		a normal message.  Instead, if a message is shared, the
21  *		H5O_FLAG_SHARED bit is set and the message body is that
22  *		defined here for H5O_SHARED.  The message ID is the ID of the
23  *		pointed-to message and the pointed-to message is stored in
24  *		the global heap.
25  */
26 
27 /****************/
28 /* Module Setup */
29 /****************/
30 
31 #define H5O_PACKAGE		/*suppress error about including H5Opkg	  */
32 
33 
34 /***********/
35 /* Headers */
36 /***********/
37 #include "H5private.h"		/* Generic Functions			*/
38 #include "H5Eprivate.h"		/* Error handling		  	*/
39 #include "H5Fprivate.h"		/* File access				*/
40 #include "H5Gprivate.h"		/* Groups				*/
41 #include "H5HFprivate.h"        /* Fractal heap				*/
42 #include "H5Opkg.h"             /* Object headers			*/
43 #include "H5SMprivate.h"        /* Shared object header messages        */
44 #include "H5WBprivate.h"        /* Wrapped Buffers                      */
45 
46 /****************/
47 /* Local Macros */
48 /****************/
49 
50 /* First version, with full symbol table entry as link for object header sharing */
51 #define H5O_SHARED_VERSION_1	1
52 
53 /* Older version, with just address of object as link for object header sharing */
54 #define H5O_SHARED_VERSION_2	2
55 
56 /* Newest version, which recognizes messages that are stored in the SOHM heap */
57 #define H5O_SHARED_VERSION_3	3
58 #define H5O_SHARED_VERSION_LATEST	H5O_SHARED_VERSION_3
59 
60 /* Size of stack buffer for serialized messages */
61 #define H5O_MESG_BUF_SIZE               128
62 
63 
64 /******************/
65 /* Local Typedefs */
66 /******************/
67 
68 
69 /********************/
70 /* Local Prototypes */
71 /********************/
72 
73 
74 /*********************/
75 /* Package Variables */
76 /*********************/
77 
78 
79 /*****************************/
80 /* Library Private Variables */
81 /*****************************/
82 
83 
84 /*******************/
85 /* Local Variables */
86 /*******************/
87 
88 
89 
90 /*-------------------------------------------------------------------------
91  * Function:	H5O_shared_read
92  *
93  * Purpose:	Reads a message referred to by a shared message.
94  *
95  * Return:	Success:	Ptr to message in native format.  The message
96  *				should be freed by calling H5O_msg_reset().
97  *
98  *		Failure:	NULL
99  *
100  * Programmer:	Quincey Koziol
101  *		koziol@ncsa.uiuc.edu
102  *		Sep 24 2003
103  *
104  *-------------------------------------------------------------------------
105  */
106 static void *
H5O_shared_read(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,unsigned * ioflags,const H5O_shared_t * shared,const H5O_msg_class_t * type)107 H5O_shared_read(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned *ioflags,
108     const H5O_shared_t *shared, const H5O_msg_class_t *type)
109 {
110     H5HF_t *fheap = NULL;
111     H5WB_t *wb = NULL;          /* Wrapped buffer for attribute data */
112     uint8_t mesg_buf[H5O_MESG_BUF_SIZE]; /* Buffer for deserializing messages */
113     void *ret_value = NULL;     /* Return value */
114 
115     FUNC_ENTER_NOAPI_NOINIT
116 
117     /* check args */
118     HDassert(f);
119     HDassert(shared);
120     HDassert(type);
121     HDassert(type->share_flags & H5O_SHARE_IS_SHARABLE);
122 
123     /* This message could have a heap ID (SOHM) or the address of an object
124      * header on disk (named datatype)
125      */
126     HDassert(H5O_IS_STORED_SHARED(shared->type));
127 
128     /* Check for implicit shared object header message */
129     if(shared->type == H5O_SHARE_TYPE_SOHM) {
130         haddr_t fheap_addr;             /* Address of SOHM heap */
131         uint8_t *mesg_ptr;              /* Pointer to raw message in heap */
132         size_t mesg_size;               /* Size of message */
133 
134         /* Retrieve the fractal heap address for shared messages */
135         if(H5SM_get_fheap_addr(f, dxpl_id, type->id, &fheap_addr) < 0)
136             HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "can't get fheap address for shared messages")
137 
138         /* Open the fractal heap */
139         if(NULL == (fheap = H5HF_open(f, dxpl_id, fheap_addr)))
140             HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
141 
142         /* Get the size of the message in the heap */
143         if(H5HF_get_obj_len(fheap, dxpl_id, &(shared->u.heap_id), &mesg_size) < 0)
144             HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "can't get message size from fractal heap.")
145 
146         /* Wrap the local buffer for serialized message */
147         if(NULL == (wb = H5WB_wrap(mesg_buf, sizeof(mesg_buf))))
148             HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "can't wrap buffer")
149 
150         /* Get a pointer to a buffer that's large enough for message */
151         if(NULL == (mesg_ptr = (uint8_t *)H5WB_actual(wb, mesg_size)))
152             HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, NULL, "can't get actual buffer")
153 
154         /* Retrieve the message from the heap */
155         if(H5HF_read(fheap, dxpl_id, &(shared->u.heap_id), mesg_ptr) < 0)
156             HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "can't read message from fractal heap.")
157 
158         /* Decode the message */
159         if(NULL == (ret_value = (type->decode)(f, dxpl_id, open_oh, 0, ioflags, mesg_size, mesg_ptr)))
160             HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, NULL, "can't decode shared message.")
161     } /* end if */
162     else {
163         H5O_loc_t oloc;         /* Location for object header where message is stored */
164 
165         HDassert(shared->type == H5O_SHARE_TYPE_COMMITTED);
166 
167         /* Build the object location for the shared message's object header */
168         oloc.file = f;
169         oloc.addr = shared->u.loc.oh_addr;
170         oloc.holding_file = FALSE;
171 
172         if(open_oh && oloc.addr == H5O_OH_GET_ADDR(open_oh)) {
173             /* The shared message is in the already opened object header.  This
174              * is possible, for example, if an attribute's datatype is shared in
175              * the same object header the attribute is in.  Read the message
176              * directly. */
177             if(NULL == (ret_value = H5O_msg_read_oh(f, dxpl_id, open_oh, type->id, NULL)))
178                 HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read message")
179         } else
180             /* The shared message is in another object header */
181             if(NULL == (ret_value = H5O_msg_read(&oloc, type->id, NULL, dxpl_id)))
182                 HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to read message")
183     } /* end else */
184 
185     /* Mark the message as shared */
186     if(H5O_msg_set_share(type->id, shared, ret_value) < 0)
187         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to set sharing information")
188 
189 done:
190     /* Release resources */
191     if(fheap && H5HF_close(fheap, dxpl_id) < 0)
192         HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, NULL, "can't close fractal heap")
193     if(wb && H5WB_unwrap(wb) < 0)
194         HDONE_ERROR(H5E_OHDR, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
195 
196     FUNC_LEAVE_NOAPI(ret_value)
197 } /* end H5O_shared_read() */
198 
199 
200 /*-------------------------------------------------------------------------
201  * Function:	H5O_shared_link_adj
202  *
203  * Purpose:	Changes the link count for the object referenced by a shared
204  *              message.
205  *
206  *              This function changes the object header link count and is
207  *              only relevant for committed messages.  Messages shared in
208  *              the heap are re-shared each time they're written, so their
209  *              reference count is stored in the file-wide shared message
210  *              index and is changed in a different place in the code.
211  *
212  * Return:	Success:	Non-negative
213  *		Failure:	Negative
214  *
215  * Programmer:	Quincey Koziol
216  *		koziol@ncsa.uiuc.edu
217  *		Sep 26 2003
218  *
219  *-------------------------------------------------------------------------
220  */
221 static herr_t
H5O_shared_link_adj(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,const H5O_msg_class_t * type,H5O_shared_t * shared,int adjust)222 H5O_shared_link_adj(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
223     const H5O_msg_class_t *type, H5O_shared_t *shared, int adjust)
224 {
225     herr_t ret_value = SUCCEED;     /* Return value */
226 
227     FUNC_ENTER_NOAPI_NOINIT
228 
229     /* check args */
230     HDassert(f);
231     HDassert(shared);
232 
233     /* Check for type of shared message */
234     if(shared->type == H5O_SHARE_TYPE_COMMITTED) {
235         H5O_loc_t oloc;         /* Location for object header where message is stored */
236 
237         /*
238          * The shared message is stored in some object header.
239          * The other object header must be in the same file as the
240          * new object header. Adjust the reference count on that
241          * object header.
242          */
243         /* Unfortunately, it is possible for the shared->file pointer to become
244          * invalid if the oh is kept in cache (which is contained in
245          * shared->file->shared while shared->file is closed.  Just ignore
246          * shared->file until the "top-level" file pointer is removed at some
247          * point in the future.  -NAF */
248         /* This is related to Jira issue #7638 and should be uncommented after
249          * the library has been refactored to shift to using shared file
250          * pointers for file operations, instead of using top file pointers.
251          * -QAK */
252         /*if(shared->file->shared != f->shared)
253             HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "interfile hard links are not allowed")*/
254 
255         /* Build the object location for the shared message's object header */
256         oloc.file = f;
257         oloc.addr = shared->u.loc.oh_addr;
258         oloc.holding_file = FALSE;
259 
260         if(open_oh && oloc.addr == H5O_OH_GET_ADDR(open_oh)) {
261             /* The shared message is in the already opened object header.  This
262              * is possible, for example, if an attribute's datatype is shared in
263              * the same object header the attribute is in.  Adjust the link
264              * count directly. */
265             hbool_t deleted = FALSE; /* This is used only to satisfy H5O_link_oh */
266 
267             if(H5O_link_oh(f, adjust, dxpl_id, open_oh, &deleted) < 0)
268                 HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
269 
270             HDassert(!deleted);
271         } else
272             /* The shared message is in another object header */
273             if(H5O_link(&oloc, adjust, dxpl_id) < 0)
274                 HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
275     } /* end if */
276     else {
277         HDassert(shared->type == H5O_SHARE_TYPE_SOHM || shared->type == H5O_SHARE_TYPE_HERE);
278 
279         /* Check for decrementing reference count on shared message */
280         if(adjust < 0) {
281             if(H5SM_delete(f, dxpl_id, open_oh, shared) < 0)
282                 HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to delete message from SOHM table")
283         } /* end if */
284         /* Check for incrementing reference count on message */
285         else if(adjust > 0) {
286             if(H5SM_try_share(f, dxpl_id, open_oh, 0, type->id, shared, NULL) < 0)
287                 HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, FAIL, "error trying to share message")
288         } /* end if */
289     } /* end else */
290 
291 done:
292     FUNC_LEAVE_NOAPI(ret_value)
293 } /* end H5O_shared_link_adj() */
294 
295 
296 /*-------------------------------------------------------------------------
297  * Function:	H5O_shared_decode
298  *
299  * Purpose:	Decodes a shared object message
300  *
301  * Return:	Non-negative on success/Negative on failure
302  *
303  * Programmer:	Quincey Koziol
304  *              Monday, January 22, 2007
305  *
306  *-------------------------------------------------------------------------
307  */
308 void *
H5O_shared_decode(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,unsigned * ioflags,const uint8_t * buf,const H5O_msg_class_t * type)309 H5O_shared_decode(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh, unsigned *ioflags,
310     const uint8_t *buf, const H5O_msg_class_t *type)
311 {
312     H5O_shared_t sh_mesg;       /* Shared message info */
313     unsigned version;           /* Shared message version */
314     void *ret_value;            /* Return value */
315 
316     FUNC_ENTER_NOAPI_NOINIT
317 
318     /* Check args */
319     HDassert(f);
320     HDassert(buf);
321     HDassert(type);
322 
323     /* Version */
324     version = *buf++;
325     if(version < H5O_SHARED_VERSION_1 || version > H5O_SHARED_VERSION_LATEST)
326         HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for shared object message")
327 
328     /* Get the shared information type
329      * Flags are unused before version 3.
330      */
331     if(version >= H5O_SHARED_VERSION_2)
332         sh_mesg.type = *buf++;
333     else {
334         sh_mesg.type = H5O_SHARE_TYPE_COMMITTED;
335         buf++;
336     } /* end else */
337 
338     /* Skip reserved bytes (for version 1) */
339     if(version == H5O_SHARED_VERSION_1)
340         buf += 6;
341 
342     /* Body */
343     if(version == H5O_SHARED_VERSION_1) {
344         /* Initialize other location fields */
345         sh_mesg.u.loc.index = 0;
346 
347         /* Decode stored "symbol table entry" into message location */
348         buf += H5F_SIZEOF_SIZE(f);          /* Skip over local heap address */
349         H5F_addr_decode(f, &buf, &(sh_mesg.u.loc.oh_addr));
350     } /* end if */
351     else if (version >= H5O_SHARED_VERSION_2) {
352         /* If this message is in the heap, copy a heap ID.
353          * Otherwise, it is a named datatype, so copy an H5O_loc_t.
354          */
355         if(sh_mesg.type == H5O_SHARE_TYPE_SOHM) {
356             HDassert(version >= H5O_SHARED_VERSION_3);
357             HDmemcpy(&sh_mesg.u.heap_id, buf, sizeof(sh_mesg.u.heap_id));
358         } /* end if */
359         else {
360             /* The H5O_COMMITTED_FLAG should be set if this message
361              * is from an older version before the flag existed.
362              */
363             if(version < H5O_SHARED_VERSION_3)
364                 sh_mesg.type = H5O_SHARE_TYPE_COMMITTED;
365 
366             sh_mesg.u.loc.index = 0;
367             H5F_addr_decode(f, &buf, &sh_mesg.u.loc.oh_addr);
368         } /* end else */
369     } /* end else if */
370 
371     /* Set file pointer & message type for all types of shared messages */
372     sh_mesg.file = f;
373     sh_mesg.msg_type_id = type->id;
374 
375     /* Retrieve actual message, through decoded shared message info */
376     if(NULL == (ret_value = H5O_shared_read(f, dxpl_id, open_oh, ioflags, &sh_mesg, type)))
377         HGOTO_ERROR(H5E_OHDR, H5E_READERROR, NULL, "unable to retrieve native message")
378 
379 done:
380     FUNC_LEAVE_NOAPI(ret_value)
381 } /* end H5O_shared_decode() */
382 
383 
384 /*-------------------------------------------------------------------------
385  * Function:	H5O_shared_encode
386  *
387  * Purpose:	Encodes message _MESG into buffer BUF.
388  *
389  * Return:	Non-negative on success/Negative on failure
390  *
391  * Programmer:	Robb Matzke
392  *              Thursday, April  2, 1998
393  *
394  *-------------------------------------------------------------------------
395  */
396 herr_t
H5O_shared_encode(const H5F_t * f,uint8_t * buf,const H5O_shared_t * sh_mesg)397 H5O_shared_encode(const H5F_t *f, uint8_t *buf/*out*/, const H5O_shared_t *sh_mesg)
398 {
399     unsigned    version;
400 
401     FUNC_ENTER_NOAPI_NOINIT_NOERR
402 
403     /* Check args */
404     HDassert(f);
405     HDassert(buf);
406     HDassert(sh_mesg);
407 
408     /* If this message is shared in the heap, we need to use version 3 of the
409      * encoding and encode the SHARED_IN_HEAP flag.
410      */
411     if(sh_mesg->type == H5O_SHARE_TYPE_SOHM)
412         version = H5O_SHARED_VERSION_LATEST;
413     else {
414         HDassert(sh_mesg->type == H5O_SHARE_TYPE_COMMITTED);
415         version = H5O_SHARED_VERSION_2; /* version 1 is no longer used */
416     } /* end else */
417 
418     *buf++ = (uint8_t)version;
419     *buf++ = (uint8_t)sh_mesg->type;
420 
421     /* Encode either the heap ID of the message or the address of the
422      * object header that holds it.
423      */
424     if(sh_mesg->type == H5O_SHARE_TYPE_SOHM)
425         HDmemcpy(buf, &(sh_mesg->u.heap_id), sizeof(sh_mesg->u.heap_id));
426     else
427         H5F_addr_encode(f, &buf, sh_mesg->u.loc.oh_addr);
428 
429     FUNC_LEAVE_NOAPI(SUCCEED)
430 } /* end H5O_shared_encode() */
431 
432 
433 /*-------------------------------------------------------------------------
434  * Function:	H5O_set_shared
435  *
436  * Purpose:	Sets the shared component for a message.
437  *
438  * Return:      Non-negative on success/Negative on failure
439  *
440  * Programmer:	Quincey Koziol
441  *		koziol@ncsa.uiuc.edu
442  *		Sep 26 2003
443  *
444  *-------------------------------------------------------------------------
445  */
446 herr_t
H5O_set_shared(H5O_shared_t * dst,const H5O_shared_t * src)447 H5O_set_shared(H5O_shared_t *dst, const H5O_shared_t *src)
448 {
449     FUNC_ENTER_NOAPI_NOINIT_NOERR
450 
451     /* check args */
452     HDassert(dst);
453     HDassert(src);
454 
455     /* copy */
456     *dst = *src;
457 
458     FUNC_LEAVE_NOAPI(SUCCEED)
459 } /* end H5O_set_shared() */
460 
461 
462 /*-------------------------------------------------------------------------
463  * Function:	H5O_shared_size
464  *
465  * Purpose:	Returns the length of a shared object message.
466  *
467  * Return:	Success:	Length
468  *		Failure:	0
469  *
470  * Programmer:	Robb Matzke
471  *              Thursday, April  2, 1998
472  *
473  *-------------------------------------------------------------------------
474  */
475 size_t
H5O_shared_size(const H5F_t * f,const H5O_shared_t * sh_mesg)476 H5O_shared_size(const H5F_t *f, const H5O_shared_t *sh_mesg)
477 {
478     size_t ret_value;           /* Return value */
479 
480     FUNC_ENTER_NOAPI_NOINIT_NOERR
481 
482     if(sh_mesg->type == H5O_SHARE_TYPE_COMMITTED) {
483         ret_value = (size_t)1 +		/*version			*/
484             (size_t)1 +			/*the type field		*/
485             (size_t)H5F_SIZEOF_ADDR(f);	/*sharing by another obj hdr	*/
486     } /* end if */
487     else {
488         HDassert(sh_mesg->type == H5O_SHARE_TYPE_SOHM);
489         ret_value = 1 +			/*version			*/
490             1 +				/*the type field		*/
491             H5O_FHEAP_ID_LEN;		/* Shared in the heap		*/
492     } /* end else */
493 
494     FUNC_LEAVE_NOAPI(ret_value)
495 } /* end H5O_shared_size() */
496 
497 
498 /*-------------------------------------------------------------------------
499  * Function:    H5O_shared_delete
500  *
501  * Purpose:     Free file space referenced by message
502  *
503  * Return:      Non-negative on success/Negative on failure
504  *
505  * Programmer:  Quincey Koziol
506  *              Friday, September 26, 2003
507  *
508  *-------------------------------------------------------------------------
509  */
510 herr_t
H5O_shared_delete(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,const H5O_msg_class_t * type,H5O_shared_t * sh_mesg)511 H5O_shared_delete(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
512     const H5O_msg_class_t *type, H5O_shared_t *sh_mesg)
513 {
514     herr_t ret_value = SUCCEED;   /* Return value */
515 
516     FUNC_ENTER_NOAPI_NOINIT
517 
518     /* check args */
519     HDassert(f);
520     HDassert(sh_mesg);
521 
522     /*
523      * Committed datatypes increment the OH of the original message when they
524      * are written (in H5O_shared_link) and decrement it here.
525      * SOHMs in the heap behave differently; their refcount is incremented
526      * during H5SM_share when they are going to be written (in H5O_msg_append
527      * or H5O_msg_write). Their refcount in the SOHM indexes still needs to
528      * be decremented when they're deleted (in H5O_shared_link_adj).
529      */
530 
531     /* Decrement the reference count on the shared object */
532     if(H5O_shared_link_adj(f, dxpl_id, open_oh, type, sh_mesg, -1) < 0)
533         HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
534 
535 done:
536     FUNC_LEAVE_NOAPI(ret_value)
537 } /* end H5O_shared_delete() */
538 
539 
540 /*-------------------------------------------------------------------------
541  * Function:    H5O_shared_link
542  *
543  * Purpose:     Increment reference count on any objects referenced by
544  *              message
545  *
546  * Return:      Non-negative on success/Negative on failure
547  *
548  * Programmer:  Quincey Koziol
549  *              Friday, September 26, 2003
550  *
551  *-------------------------------------------------------------------------
552  */
553 herr_t
H5O_shared_link(H5F_t * f,hid_t dxpl_id,H5O_t * open_oh,const H5O_msg_class_t * type,H5O_shared_t * sh_mesg)554 H5O_shared_link(H5F_t *f, hid_t dxpl_id, H5O_t *open_oh,
555     const H5O_msg_class_t *type, H5O_shared_t *sh_mesg)
556 {
557     herr_t ret_value = SUCCEED;   /* Return value */
558 
559     FUNC_ENTER_NOAPI_NOINIT
560 
561     /* check args */
562     HDassert(f);
563     HDassert(sh_mesg);
564 
565     /* Increment the reference count on the shared object */
566     if(H5O_shared_link_adj(f, dxpl_id, open_oh, type, sh_mesg, 1) < 0)
567         HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust shared object link count")
568 
569 done:
570     FUNC_LEAVE_NOAPI(ret_value)
571 } /* end H5O_shared_link() */
572 
573 
574 /*-------------------------------------------------------------------------
575  * Function:    H5O_shared_copy_file
576  *
577  * Purpose:     Copies a message from _MESG to _DEST in file
578  *
579  * Return:      Success:        Non-negative
580  *              Failure:        Negative
581  *
582  * Programmer:  Quincey Koziol
583  *              January 22, 2007
584  *
585  *-------------------------------------------------------------------------
586  */
587 herr_t
H5O_shared_copy_file(H5F_t * file_src,H5F_t * file_dst,const H5O_msg_class_t * mesg_type,const void * _native_src,void * _native_dst,hbool_t H5_ATTR_UNUSED * recompute_size,unsigned * mesg_flags,H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata,hid_t dxpl_id)588 H5O_shared_copy_file(H5F_t *file_src, H5F_t *file_dst,
589     const H5O_msg_class_t *mesg_type, const void *_native_src, void *_native_dst,
590     hbool_t H5_ATTR_UNUSED *recompute_size, unsigned *mesg_flags, H5O_copy_t *cpy_info,
591     void H5_ATTR_UNUSED *udata, hid_t dxpl_id)
592 {
593     const H5O_shared_t  *shared_src = (const H5O_shared_t *)_native_src; /* Alias to shared info in native source */
594     H5O_shared_t        *shared_dst = (H5O_shared_t *)_native_dst; /* Alias to shared info in native destination message */
595     herr_t ret_value = SUCCEED;         /* Return value */
596 
597     FUNC_ENTER_NOAPI_NOINIT
598 
599     /* check args */
600     HDassert(file_src);
601     HDassert(file_dst);
602     HDassert(mesg_type);
603     HDassert(shared_src);
604     HDassert(shared_dst);
605     HDassert(recompute_size);
606     HDassert(cpy_info);
607 
608     /* Committed shared messages create a shared message at the destination
609      * and also copy the committed object that they point to.
610      *
611      * Other messages simulate sharing the destination message to determine how
612      * it will eventually be shared (if at all), but do not actually share the
613      * message until "post copy".  The "H5O_shared_t" part of the message will
614      * be updated (to allow calculation of the final size) but the message is
615      * not actually shared.
616      */
617     if(shared_src->type != H5O_SHARE_TYPE_COMMITTED) {
618         /* Simulate trying to share new message in the destination file. */
619         if(H5SM_try_share(file_dst, dxpl_id, NULL, H5SM_DEFER, mesg_type->id, _native_dst, mesg_flags) < 0)
620             HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to determine if message should be shared")
621     } /* end if */
622     else {
623         /* Mark the message as committed - as it will be committed in post copy
624          */
625         H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, file_dst, mesg_type->id, 0, HADDR_UNDEF)
626         *mesg_flags |= H5O_MSG_FLAG_SHARED;
627     } /* end else */
628 
629 done:
630     FUNC_LEAVE_NOAPI(ret_value)
631 } /* H5O_shared_copy_file() */
632 
633 
634 /*-------------------------------------------------------------------------
635  * Function:    H5O_shared_post_copy_file
636  *
637  * Purpose:     Delate a shared message and replace with a new one.
638  *              The function is needed at cases such as coping a shared reg_ref attribute.
639  *              When a shared reg_ref attribute is copied from one file to
640  *              another, the values in file need to be replaced. The only way
641  *              to complish that is to delete the old message and write the
642  *              new message with the correct values.
643  *
644  * Return:      Non-negative on success/Negative on failure
645  *
646  * Programmer:  Peter Cao
647  *              xcao@hdfgroup.org
648  *              May 24 2007
649  *
650  *-------------------------------------------------------------------------
651  */
652 herr_t
H5O_shared_post_copy_file(H5F_t * f,const H5O_msg_class_t * mesg_type,const H5O_shared_t * shared_src,H5O_shared_t * shared_dst,unsigned * mesg_flags,hid_t dxpl_id,H5O_copy_t * cpy_info)653 H5O_shared_post_copy_file(H5F_t *f, const H5O_msg_class_t *mesg_type,
654     const H5O_shared_t *shared_src, H5O_shared_t *shared_dst,
655     unsigned *mesg_flags, hid_t dxpl_id, H5O_copy_t *cpy_info)
656 {
657     herr_t ret_value = SUCCEED;         /* Return value */
658 
659     FUNC_ENTER_NOAPI_NOINIT
660 
661     /* check args */
662     HDassert(f);
663     HDassert(shared_src);
664     HDassert(shared_dst);
665 
666     /* Copy the target of committed messages, try to share others */
667     if(shared_src->type == H5O_SHARE_TYPE_COMMITTED) {
668         H5O_loc_t dst_oloc;
669         H5O_loc_t src_oloc;
670 
671         /* Copy the shared object from source to destination */
672         H5O_loc_reset(&dst_oloc);
673         dst_oloc.file = f;
674         src_oloc.file = shared_src->file;
675         src_oloc.addr = shared_src->u.loc.oh_addr;
676         if(H5O_copy_header_map(&src_oloc, &dst_oloc, dxpl_id, cpy_info, FALSE,
677                 NULL, NULL) < 0)
678             HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
679 
680         /* Set up destination message's shared info */
681         H5O_UPDATE_SHARED(shared_dst, H5O_SHARE_TYPE_COMMITTED, f, mesg_type->id, 0, dst_oloc.addr)
682     } /* end if */
683     else
684         /* Share the message */
685         if(H5SM_try_share(f, dxpl_id, NULL, H5SM_WAS_DEFERRED, mesg_type->id,
686                 shared_dst, mesg_flags) < 0)
687             HGOTO_ERROR(H5E_OHDR, H5E_BADMESG, FAIL, "can't share message")
688 
689 done:
690     FUNC_LEAVE_NOAPI(ret_value)
691 } /* end H5O_shared_post_copy_file() */
692 
693 
694 /*-------------------------------------------------------------------------
695  * Function:	H5O_shared_debug
696  *
697  * Purpose:	Prints debugging info for the message
698  *
699  * Return:	Non-negative on success/Negative on failure
700  *
701  * Programmer:	Robb Matzke
702  *              Thursday, April  2, 1998
703  *
704  *-------------------------------------------------------------------------
705  */
706 herr_t
H5O_shared_debug(const H5O_shared_t * mesg,FILE * stream,int indent,int fwidth)707 H5O_shared_debug(const H5O_shared_t *mesg, FILE *stream, int indent, int fwidth)
708 {
709     FUNC_ENTER_NOAPI_NOINIT_NOERR
710 
711     /* Check args */
712     HDassert(mesg);
713     HDassert(stream);
714     HDassert(indent >= 0);
715     HDassert(fwidth >= 0);
716 
717     switch(mesg->type) {
718         case H5O_SHARE_TYPE_UNSHARED:
719             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
720                     "Shared Message type:",
721                     "Unshared");
722             break;
723 
724         case H5O_SHARE_TYPE_COMMITTED:
725             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
726                     "Shared Message type:",
727                     "Obj Hdr");
728             HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
729                     "Object address:",
730                     mesg->u.loc.oh_addr);
731             break;
732 
733         case H5O_SHARE_TYPE_SOHM:
734             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
735                     "Shared Message type:",
736                     "SOHM");
737             HDfprintf(stream, "%*s%-*s %016llx\n", indent, "", fwidth,
738                     "Heap ID:",
739                     (unsigned long long)mesg->u.heap_id.val);
740             break;
741 
742         case H5O_SHARE_TYPE_HERE:
743             HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
744                     "Shared Message type:",
745                     "Here");
746             break;
747 
748         default:
749             HDfprintf(stream, "%*s%-*s %s (%u)\n", indent, "", fwidth,
750                     "Shared Message type:",
751                     "Unknown", (unsigned)mesg->type);
752     } /* end switch */
753 
754     FUNC_LEAVE_NOAPI(SUCCEED)
755 } /* end H5O_shared_debug() */
756 
757