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  *
16  * Created:		H5EAdblkpage.c
17  *			Nov 20 2008
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Data block page routines for extensible arrays.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /**********************/
26 /* Module Declaration */
27 /**********************/
28 
29 #include "H5EAmodule.h"         /* This source code file is part of the H5EA module */
30 
31 
32 /***********************/
33 /* Other Packages Used */
34 /***********************/
35 
36 
37 /***********/
38 /* Headers */
39 /***********/
40 #include "H5private.h"		/* Generic Functions			*/
41 #include "H5Eprivate.h"		/* Error handling		  	*/
42 #include "H5EApkg.h"		/* Extensible Arrays			*/
43 #include "H5FLprivate.h"	/* Free Lists                           */
44 #include "H5VMprivate.h"		/* Vectors and arrays 			*/
45 
46 
47 /****************/
48 /* Local Macros */
49 /****************/
50 
51 
52 /******************/
53 /* Local Typedefs */
54 /******************/
55 
56 
57 /********************/
58 /* Package Typedefs */
59 /********************/
60 
61 
62 /********************/
63 /* Local Prototypes */
64 /********************/
65 
66 
67 /*********************/
68 /* Package Variables */
69 /*********************/
70 
71 
72 /*****************************/
73 /* Library Private Variables */
74 /*****************************/
75 
76 
77 /*******************/
78 /* Local Variables */
79 /*******************/
80 
81 /* Declare a free list to manage the H5EA_dblk_page_t struct */
82 H5FL_DEFINE_STATIC(H5EA_dblk_page_t);
83 
84 
85 
86 /*-------------------------------------------------------------------------
87  * Function:	H5EA__dblk_page_alloc
88  *
89  * Purpose:	Allocate extensible array data block page
90  *
91  * Return:	Non-NULL pointer to data block on success/NULL on failure
92  *
93  * Programmer:	Quincey Koziol
94  *		koziol@hdfgroup.org
95  *		Nov 20 2008
96  *
97  *-------------------------------------------------------------------------
98  */
99 BEGIN_FUNC(PKG, ERR,
100 H5EA_dblk_page_t *, NULL, NULL,
101 H5EA__dblk_page_alloc(H5EA_hdr_t *hdr, H5EA_sblock_t *parent))
102 
103     /* Local variables */
104     H5EA_dblk_page_t *dblk_page = NULL;          /* Extensible array data block page */
105 
106     /* Check arguments */
107     HDassert(hdr);
108 
109     /* Allocate memory for the data block */
110     if(NULL == (dblk_page = H5FL_CALLOC(H5EA_dblk_page_t)))
111 	H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
112 
113     /* Share common array information */
114     if(H5EA__hdr_incr(hdr) < 0)
115 	H5E_THROW(H5E_CANTINC, "can't increment reference count on shared array header")
116     dblk_page->hdr = hdr;
117 
118     /* Set non-zero internal fields */
119     dblk_page->parent = parent;
120 
121     /* Allocate buffer for elements in data block page */
122     if(NULL == (dblk_page->elmts = H5EA__hdr_alloc_elmts(hdr, hdr->dblk_page_nelmts)))
123         H5E_THROW(H5E_CANTALLOC, "memory allocation failed for data block page element buffer")
124 
125     /* Set the return value */
126     ret_value = dblk_page;
127 
128 CATCH
129     if(!ret_value)
130         if(dblk_page && H5EA__dblk_page_dest(dblk_page) < 0)
131             H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
132 
133 END_FUNC(PKG)   /* end H5EA__dblk_page_alloc() */
134 
135 
136 /*-------------------------------------------------------------------------
137  * Function:	H5EA__dblk_page_create
138  *
139  * Purpose:	Creates a new extensible array data block page in the file
140  *
141  * Return:	Valid file address on success/HADDR_UNDEF on failure
142  *
143  * Programmer:	Quincey Koziol
144  *		koziol@hdfgroup.org
145  *		Nov 20 2008
146  *
147  *-------------------------------------------------------------------------
148  */
149 BEGIN_FUNC(PKG, ERR,
150 herr_t, SUCCEED, FAIL,
151 H5EA__dblk_page_create(H5EA_hdr_t *hdr, H5EA_sblock_t *parent, haddr_t addr))
152 
153     /* Local variables */
154     H5EA_dblk_page_t *dblk_page = NULL; /* Extensible array data block page */
155     hbool_t inserted = FALSE;           /* Whether the header was inserted into cache */
156 
157     /* Sanity check */
158     HDassert(hdr);
159 
160     /* Allocate the data block page */
161     if(NULL == (dblk_page = H5EA__dblk_page_alloc(hdr, parent)))
162 	H5E_THROW(H5E_CANTALLOC, "memory allocation failed for extensible array data block page")
163 
164     /* Set info about data block page on disk */
165     dblk_page->addr = addr;
166     dblk_page->size = H5EA_DBLK_PAGE_SIZE(hdr);
167 
168     /* Clear any elements in data block page to fill value */
169     if((hdr->cparam.cls->fill)(dblk_page->elmts, (size_t)hdr->dblk_page_nelmts) < 0)
170         H5E_THROW(H5E_CANTSET, "can't set extensible array data block page elements to class's fill value")
171 
172     /* Cache the new extensible array data block page */
173     if(H5AC_insert_entry(hdr->f, H5AC_EARRAY_DBLK_PAGE, dblk_page->addr, dblk_page, H5AC__NO_FLAGS_SET) < 0)
174 	H5E_THROW(H5E_CANTINSERT, "can't add extensible array data block page to cache")
175     inserted = TRUE;
176 
177     /* Add data block page as child of 'top' proxy */
178     if(hdr->top_proxy) {
179         if(H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, dblk_page) < 0)
180             H5E_THROW(H5E_CANTSET, "unable to add extensible array entry as child of array proxy")
181         dblk_page->top_proxy = hdr->top_proxy;
182     } /* end if */
183 
184 CATCH
185     if(ret_value < 0)
186         if(dblk_page) {
187             /* Remove from cache, if inserted */
188             if(inserted)
189                 if(H5AC_remove_entry(dblk_page) < 0)
190                     H5E_THROW(H5E_CANTREMOVE, "unable to remove extensible array data block page from cache")
191 
192             /* Destroy data block page */
193             if(H5EA__dblk_page_dest(dblk_page) < 0)
194                 H5E_THROW(H5E_CANTFREE, "unable to destroy extensible array data block page")
195         } /* end if */
196 
197 END_FUNC(PKG)   /* end H5EA__dblk_page_create() */
198 
199 
200 /*-------------------------------------------------------------------------
201  * Function:	H5EA__dblk_page_protect
202  *
203  * Purpose:	Convenience wrapper around protecting extensible array data
204  *              block page
205  *
206  * Return:	Non-NULL pointer to data block page on success/NULL on failure
207  *
208  * Programmer:	Quincey Koziol
209  *		koziol@hdfgroup.org
210  *		Nov 20 2008
211  *
212  *-------------------------------------------------------------------------
213  */
214 BEGIN_FUNC(PKG, ERR,
215 H5EA_dblk_page_t *, NULL, NULL,
216 H5EA__dblk_page_protect(H5EA_hdr_t *hdr, H5EA_sblock_t *parent,
217     haddr_t dblk_page_addr, unsigned flags))
218 
219     /* Local variables */
220     H5EA_dblk_page_t *dblk_page = NULL; /* Extensible array data block page */
221     H5EA_dblk_page_cache_ud_t udata;    /* Information needed for loading data block page */
222 
223     /* Sanity check */
224     HDassert(hdr);
225     HDassert(H5F_addr_defined(dblk_page_addr));
226 
227     /* only the H5AC__READ_ONLY_FLAG may be set */
228     HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
229 
230     /* Set up user data */
231     udata.hdr = hdr;
232     udata.parent = parent;
233     udata.dblk_page_addr = dblk_page_addr;
234 
235     /* Protect the data block page */
236     if(NULL == (dblk_page = (H5EA_dblk_page_t *)H5AC_protect(hdr->f, H5AC_EARRAY_DBLK_PAGE, dblk_page_addr, &udata, flags)))
237         H5E_THROW(H5E_CANTPROTECT, "unable to protect extensible array data block page, address = %llu", (unsigned long long)dblk_page_addr)
238 
239     /* Create top proxy, if it doesn't exist */
240     if(hdr->top_proxy && NULL == dblk_page->top_proxy) {
241         /* Add data block page as child of 'top' proxy */
242         if(H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, dblk_page) < 0)
243             H5E_THROW(H5E_CANTSET, "unable to add extensible array entry as child of array proxy")
244         dblk_page->top_proxy = hdr->top_proxy;
245     } /* end if */
246 
247     /* Set return value */
248     ret_value = dblk_page;
249 
250 CATCH
251     /* Clean up on error */
252     if(!ret_value) {
253         /* Release the data block page, if it was protected */
254         if(dblk_page && H5AC_unprotect(hdr->f, H5AC_EARRAY_DBLK_PAGE, dblk_page->addr, dblk_page, H5AC__NO_FLAGS_SET) < 0)
255             H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array data block page, address = %llu", (unsigned long long)dblk_page->addr)
256     } /* end if */
257 
258 END_FUNC(PKG)   /* end H5EA__dblk_page_protect() */
259 
260 
261 /*-------------------------------------------------------------------------
262  * Function:	H5EA__dblk_page_unprotect
263  *
264  * Purpose:	Convenience wrapper around unprotecting extensible array
265  *              data block page
266  *
267  * Return:	Non-negative on success/Negative on failure
268  *
269  * Programmer:	Quincey Koziol
270  *		koziol@hdfgroup.org
271  *		Nov 20 2008
272  *
273  *-------------------------------------------------------------------------
274  */
275 BEGIN_FUNC(PKG, ERR,
276 herr_t, SUCCEED, FAIL,
277 H5EA__dblk_page_unprotect(H5EA_dblk_page_t *dblk_page, unsigned cache_flags))
278 
279     /* Local variables */
280 
281     /* Sanity check */
282     HDassert(dblk_page);
283 
284     /* Unprotect the data block page */
285     if(H5AC_unprotect(dblk_page->hdr->f, H5AC_EARRAY_DBLK_PAGE, dblk_page->addr, dblk_page, cache_flags) < 0)
286         H5E_THROW(H5E_CANTUNPROTECT, "unable to unprotect extensible array data block page, address = %llu", (unsigned long long)dblk_page->addr)
287 
288 CATCH
289 
290 END_FUNC(PKG)   /* end H5EA__dblk_page_unprotect() */
291 
292 
293 /*-------------------------------------------------------------------------
294  * Function:	H5EA__dblk_page_dest
295  *
296  * Purpose:	Destroys an extensible array data block page in memory.
297  *
298  * Return:	Non-negative on success/Negative on failure
299  *
300  * Programmer:	Quincey Koziol
301  *		koziol@hdfgroup.org
302  *		Nov 20 2008
303  *
304  *-------------------------------------------------------------------------
305  */
306 BEGIN_FUNC(PKG, ERR,
307 herr_t, SUCCEED, FAIL,
308 H5EA__dblk_page_dest(H5EA_dblk_page_t *dblk_page))
309 
310     /* Sanity check */
311     HDassert(dblk_page);
312     HDassert(!dblk_page->has_hdr_depend);
313 
314     /* Check if header field has been initialized */
315     if(dblk_page->hdr) {
316         /* Check if buffer for data block page elements has been initialized */
317         if(dblk_page->elmts) {
318             /* Free buffer for data block page elements */
319             if(H5EA__hdr_free_elmts(dblk_page->hdr, dblk_page->hdr->dblk_page_nelmts, dblk_page->elmts) < 0)
320                 H5E_THROW(H5E_CANTFREE, "unable to free extensible array data block element buffer")
321             dblk_page->elmts = NULL;
322         } /* end if */
323 
324         /* Decrement reference count on shared info */
325         if(H5EA__hdr_decr(dblk_page->hdr) < 0)
326             H5E_THROW(H5E_CANTDEC, "can't decrement reference count on shared array header")
327         dblk_page->hdr = NULL;
328     } /* end if */
329 
330     /* Sanity check */
331     HDassert(NULL == dblk_page->top_proxy);
332 
333     /* Free the data block page itself */
334     dblk_page = H5FL_FREE(H5EA_dblk_page_t, dblk_page);
335 
336 CATCH
337 
338 END_FUNC(PKG)   /* end H5EA__dblk_page_dest() */
339 
340