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