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:		H5HFtiny.c
17  *			Aug 14 2006
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Routines for "tiny" objects in fractal heap
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #define H5HF_PACKAGE		/*suppress error about including H5HFpkg  */
30 
31 
32 /***********/
33 /* Headers */
34 /***********/
35 #include "H5private.h"		/* Generic Functions			*/
36 #include "H5Eprivate.h"		/* Error handling		  	*/
37 #include "H5HFpkg.h"		/* Fractal heaps			*/
38 
39 
40 /****************/
41 /* Local Macros */
42 /****************/
43 
44 /* Tiny object length information */
45 #define H5HF_TINY_LEN_SHORT     16              /* Max. length able to be encoded in first heap ID byte */
46 #define H5HF_TINY_MASK_SHORT    0x0F            /* Mask for length in first heap ID byte */
47 #define H5HF_TINY_MASK_EXT      0x0FFF          /* Mask for length in two heap ID bytes */
48 #define H5HF_TINY_MASK_EXT_1    0x0F00          /* Mask for length in first byte of two heap ID bytes */
49 #define H5HF_TINY_MASK_EXT_2    0x00FF          /* Mask for length in second byte of two heap ID bytes */
50 
51 
52 /******************/
53 /* Local Typedefs */
54 /******************/
55 
56 
57 /********************/
58 /* Package Typedefs */
59 /********************/
60 
61 
62 /********************/
63 /* Local Prototypes */
64 /********************/
65 static herr_t H5HF_tiny_op_real(H5HF_hdr_t *hdr, const uint8_t *id,
66     H5HF_operator_t op, void *op_data);
67 
68 
69 /*********************/
70 /* Package Variables */
71 /*********************/
72 
73 
74 /*****************************/
75 /* Library Private Variables */
76 /*****************************/
77 
78 
79 /*******************/
80 /* Local Variables */
81 /*******************/
82 
83 
84 /*-------------------------------------------------------------------------
85  * Function:	H5HF_tiny_init
86  *
87  * Purpose:	Initialize information for tracking 'tiny' objects
88  *
89  * Return:	SUCCEED/FAIL
90  *
91  * Programmer:	Quincey Koziol
92  *		koziol@hdfgroup.org
93  *		Aug 14 2006
94  *
95  *-------------------------------------------------------------------------
96  */
97 herr_t
H5HF_tiny_init(H5HF_hdr_t * hdr)98 H5HF_tiny_init(H5HF_hdr_t *hdr)
99 {
100     FUNC_ENTER_NOAPI_NOINIT_NOERR
101 
102     /*
103      * Check arguments.
104      */
105     HDassert(hdr);
106 
107     /* Compute information about 'tiny' objects for the heap */
108 
109     /* Check if tiny objects need an extra byte for their length */
110     /* (account for boundary condition when length of an object would need an
111      *  extra byte, but using that byte means that the extra length byte is
112      *  unnecessary)
113      */
114     if((hdr->id_len - 1) <= H5HF_TINY_LEN_SHORT) {
115         hdr->tiny_max_len = hdr->id_len - 1;
116         hdr->tiny_len_extended = FALSE;
117     } /* end if */
118     else if((hdr->id_len - 1) == (H5HF_TINY_LEN_SHORT + 1)) {
119         hdr->tiny_max_len = H5HF_TINY_LEN_SHORT;
120         hdr->tiny_len_extended = FALSE;
121     } /* end if */
122     else {
123         hdr->tiny_max_len = hdr->id_len - 2;
124         hdr->tiny_len_extended = TRUE;
125     } /* end else */
126 
127     FUNC_LEAVE_NOAPI(SUCCEED)
128 } /* end H5HF_tiny_init() */
129 
130 
131 /*-------------------------------------------------------------------------
132  * Function:	H5HF_tiny_insert
133  *
134  * Purpose:	Pack a 'tiny' object in a heap ID
135  *
136  * Return:	SUCCEED/FAIL
137  *
138  * Programmer:	Quincey Koziol
139  *		koziol@hdfgroup.org
140  *		Aug 14 2006
141  *
142  *-------------------------------------------------------------------------
143  */
144 herr_t
H5HF_tiny_insert(H5HF_hdr_t * hdr,size_t obj_size,const void * obj,void * _id)145 H5HF_tiny_insert(H5HF_hdr_t *hdr, size_t obj_size, const void *obj, void *_id)
146 {
147     uint8_t *id = (uint8_t *)_id;       /* Pointer to ID buffer */
148     size_t enc_obj_size;                /* Encoded object size */
149     herr_t ret_value = SUCCEED;         /* Return value */
150 
151     FUNC_ENTER_NOAPI_NOINIT
152 #ifdef QAK
153 HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
154 #endif /* QAK */
155 
156     /*
157      * Check arguments.
158      */
159     HDassert(hdr);
160     HDassert(obj_size <= hdr->tiny_max_len);
161     HDassert(obj_size <= (H5HF_TINY_MASK_EXT + 1));
162     HDassert(obj);
163     HDassert(id);
164 
165     /* Adjust object's size for encoding it */
166     enc_obj_size = obj_size - 1;
167 
168     /* Encode object into ID */
169     if(!hdr->tiny_len_extended) {
170         *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_TINY |
171                 (enc_obj_size & H5HF_TINY_MASK_SHORT);
172     } /* end if */
173     else {
174         *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_TINY |
175                 ((enc_obj_size & H5HF_TINY_MASK_EXT_1) >> 8);
176         *id++ = enc_obj_size & H5HF_TINY_MASK_EXT_2;
177     } /* end else */
178     HDmemcpy(id, obj, obj_size);
179 #ifdef H5_CLEAR_MEMORY
180 HDmemset(id + obj_size, 0, (hdr->id_len - (1 + hdr->tiny_len_extended + obj_size)));
181 #endif /* H5_CLEAR_MEMORY */
182 
183     /* Update statistics about heap */
184     hdr->tiny_size += obj_size;
185     hdr->tiny_nobjs++;
186 
187     /* Mark heap header as modified */
188     if(H5HF_hdr_dirty(hdr) < 0)
189         HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
190 
191 done:
192     FUNC_LEAVE_NOAPI(ret_value)
193 } /* end H5HF_tiny_insert() */
194 
195 
196 /*-------------------------------------------------------------------------
197  * Function:	H5HF_tiny_get_obj_len
198  *
199  * Purpose:	Get the size of a 'tiny' object in a fractal heap
200  *
201  * Return:	SUCCEED/FAIL
202  *
203  * Programmer:	Quincey Koziol
204  *		koziol@hdfgroup.org
205  *		Aug 14 2006
206  *
207  *-------------------------------------------------------------------------
208  */
209 herr_t
H5HF_tiny_get_obj_len(H5HF_hdr_t * hdr,const uint8_t * id,size_t * obj_len_p)210 H5HF_tiny_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p)
211 {
212     size_t enc_obj_size;                /* Encoded object size */
213 
214     FUNC_ENTER_NOAPI_NOINIT_NOERR
215 
216     /*
217      * Check arguments.
218      */
219     HDassert(hdr);
220     HDassert(id);
221     HDassert(obj_len_p);
222 
223     /* Check if 'tiny' object ID is in extended form, and retrieve encoded size */
224     if(!hdr->tiny_len_extended)
225         enc_obj_size = *id & H5HF_TINY_MASK_SHORT;
226     else
227 	/* (performed in this odd way to avoid compiler bug on tg-login3 with
228 	 *  gcc 3.2.2 - QAK)
229 	 */
230         enc_obj_size = *(id + 1) | ((*id & H5HF_TINY_MASK_EXT_1) << 8);
231 
232     /* Set the object's length */
233     *obj_len_p = enc_obj_size + 1;
234 
235     FUNC_LEAVE_NOAPI(SUCCEED)
236 } /* end H5HF_tiny_get_obj_len() */
237 
238 
239 /*-------------------------------------------------------------------------
240  * Function:	H5HF_tiny_op_real
241  *
242  * Purpose:	Internal routine to perform operation on 'tiny' object
243  *
244  * Return:	SUCCEED/FAIL
245  *
246  * Programmer:	Quincey Koziol
247  *		koziol@hdfgroup.org
248  *		Sep 11 2006
249  *
250  *-------------------------------------------------------------------------
251  */
252 static herr_t
H5HF_tiny_op_real(H5HF_hdr_t * hdr,const uint8_t * id,H5HF_operator_t op,void * op_data)253 H5HF_tiny_op_real(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
254     void *op_data)
255 {
256     size_t enc_obj_size;                /* Encoded object size */
257     herr_t ret_value = SUCCEED;         /* Return value */
258 
259     FUNC_ENTER_NOAPI_NOINIT
260 
261     /*
262      * Check arguments.
263      */
264     HDassert(hdr);
265     HDassert(id);
266     HDassert(op);
267 
268     /* Check if 'tiny' object ID is in extended form */
269     if(!hdr->tiny_len_extended) {
270         /* Retrieve the object's encoded length */
271         enc_obj_size = *id & H5HF_TINY_MASK_SHORT;
272 
273         /* Advance past flag byte(s) */
274         id++;
275     } /* end if */
276     else {
277         /* Retrieve the object's encoded length */
278 	/* (performed in this odd way to avoid compiler bug on tg-login3 with
279 	 *  gcc 3.2.2 - QAK)
280 	 */
281         enc_obj_size = *(id + 1) | ((*id & H5HF_TINY_MASK_EXT_1) << 8);
282 
283         /* Advance past flag byte(s) */
284 	/* (performed in two steps to avoid compiler bug on tg-login3 with
285 	 *  gcc 3.2.2 - QAK)
286 	 */
287         id++; id++;
288     } /* end else */
289 
290     /* Call the user's 'op' callback */
291     if(op(id, (enc_obj_size + 1), op_data) < 0)
292         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
293 
294 done:
295     FUNC_LEAVE_NOAPI(ret_value)
296 } /* end H5HF_tiny_op_real() */
297 
298 
299 /*-------------------------------------------------------------------------
300  * Function:	H5HF_tiny_read
301  *
302  * Purpose:	Read a 'tiny' object from the heap
303  *
304  * Return:	SUCCEED/FAIL
305  *
306  * Programmer:	Quincey Koziol
307  *		koziol@hdfgroup.org
308  *		Aug  8 2006
309  *
310  *-------------------------------------------------------------------------
311  */
312 herr_t
H5HF_tiny_read(H5HF_hdr_t * hdr,const uint8_t * id,void * obj)313 H5HF_tiny_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj)
314 {
315     herr_t ret_value = SUCCEED;         /* Return value */
316 
317     FUNC_ENTER_NOAPI_NOINIT
318 
319     /*
320      * Check arguments.
321      */
322     HDassert(hdr);
323     HDassert(id);
324     HDassert(obj);
325 
326     /* Call the internal 'op' routine */
327     if(H5HF_tiny_op_real(hdr, id, H5HF_op_read, obj) < 0)
328         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
329 
330 done:
331     FUNC_LEAVE_NOAPI(ret_value)
332 } /* end H5HF_tiny_read() */
333 
334 
335 /*-------------------------------------------------------------------------
336  * Function:	H5HF_tiny_op
337  *
338  * Purpose:	Operate directly on a 'tiny' object
339  *
340  * Return:	SUCCEED/FAIL
341  *
342  * Programmer:	Quincey Koziol
343  *		koziol@ncsa.uiuc.edu
344  *		Sept 11 2006
345  *
346  *-------------------------------------------------------------------------
347  */
348 herr_t
H5HF_tiny_op(H5HF_hdr_t * hdr,const uint8_t * id,H5HF_operator_t op,void * op_data)349 H5HF_tiny_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
350     void *op_data)
351 {
352     herr_t ret_value = SUCCEED;         /* Return value */
353 
354     FUNC_ENTER_NOAPI_NOINIT
355 
356     /*
357      * Check arguments.
358      */
359     HDassert(hdr);
360     HDassert(id);
361     HDassert(op);
362 
363     /* Call the internal 'op' routine routine */
364     if(H5HF_tiny_op_real(hdr, id, op, op_data) < 0)
365         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
366 
367 done:
368     FUNC_LEAVE_NOAPI(ret_value)
369 } /* end H5HF_tiny_op() */
370 
371 
372 /*-------------------------------------------------------------------------
373  * Function:	H5HF_tiny_remove
374  *
375  * Purpose:	Remove a 'tiny' object from the heap statistics
376  *
377  * Return:	SUCCEED/FAIL
378  *
379  * Programmer:	Quincey Koziol
380  *		koziol@hdfgroup.org
381  *		Aug 14 2006
382  *
383  *-------------------------------------------------------------------------
384  */
385 herr_t
H5HF_tiny_remove(H5HF_hdr_t * hdr,const uint8_t * id)386 H5HF_tiny_remove(H5HF_hdr_t *hdr, const uint8_t *id)
387 {
388     size_t enc_obj_size;                /* Encoded object size */
389     herr_t ret_value = SUCCEED;         /* Return value */
390 
391     FUNC_ENTER_NOAPI_NOINIT
392 
393     /*
394      * Check arguments.
395      */
396     HDassert(hdr);
397     HDassert(id);
398 
399     /* Check if 'tiny' object ID is in extended form */
400     if(!hdr->tiny_len_extended)
401         enc_obj_size = *id & H5HF_TINY_MASK_SHORT;
402     else
403 	/* (performed in this odd way to avoid compiler bug on tg-login3 with
404 	 *  gcc 3.2.2 - QAK)
405 	 */
406         enc_obj_size = *(id + 1) | ((*id & H5HF_TINY_MASK_EXT_1) << 8);
407 
408     /* Update statistics about heap */
409     hdr->tiny_size -= (enc_obj_size + 1);
410     hdr->tiny_nobjs--;
411 
412     /* Mark heap header as modified */
413     if(H5HF_hdr_dirty(hdr) < 0)
414         HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
415 
416 done:
417     FUNC_LEAVE_NOAPI(ret_value)
418 } /* end H5HF_tiny_remove() */
419 
420