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 #include "H5HFmodule.h" /* This source code file is part of the H5HF module */
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++ = (uint8_t)(H5HF_ID_VERS_CURR | H5HF_ID_TYPE_TINY |
171 (enc_obj_size & H5HF_TINY_MASK_SHORT));
172 } /* end if */
173 else {
174 *id++ = (uint8_t)(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
179 HDmemcpy(id, obj, obj_size);
180 HDmemset(id + obj_size, 0, (hdr->id_len - ((size_t)1 + (size_t)hdr->tiny_len_extended + obj_size)));
181
182 /* Update statistics about heap */
183 hdr->tiny_size += obj_size;
184 hdr->tiny_nobjs++;
185
186 /* Mark heap header as modified */
187 if(H5HF_hdr_dirty(hdr) < 0)
188 HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
189
190 done:
191 FUNC_LEAVE_NOAPI(ret_value)
192 } /* end H5HF_tiny_insert() */
193
194
195 /*-------------------------------------------------------------------------
196 * Function: H5HF_tiny_get_obj_len
197 *
198 * Purpose: Get the size of a 'tiny' object in a fractal heap
199 *
200 * Return: SUCCEED (Can't fail)
201 *
202 * Programmer: Quincey Koziol
203 * koziol@hdfgroup.org
204 * Aug 14 2006
205 *
206 *-------------------------------------------------------------------------
207 */
208 herr_t
H5HF_tiny_get_obj_len(H5HF_hdr_t * hdr,const uint8_t * id,size_t * obj_len_p)209 H5HF_tiny_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p)
210 {
211 size_t enc_obj_size; /* Encoded object size */
212
213 FUNC_ENTER_NOAPI_NOINIT_NOERR
214
215 /*
216 * Check arguments.
217 */
218 HDassert(hdr);
219 HDassert(id);
220 HDassert(obj_len_p);
221
222 /* Check if 'tiny' object ID is in extended form, and retrieve encoded size */
223 if(!hdr->tiny_len_extended)
224 enc_obj_size = *id & H5HF_TINY_MASK_SHORT;
225 else
226 /* (performed in this odd way to avoid compiler bug on tg-login3 with
227 * gcc 3.2.2 - QAK)
228 */
229 enc_obj_size = (size_t)*(id + 1) | ((size_t)(*id & H5HF_TINY_MASK_EXT_1) << 8);
230
231 /* Set the object's length */
232 *obj_len_p = enc_obj_size + 1;
233
234 FUNC_LEAVE_NOAPI(SUCCEED)
235 } /* end H5HF_tiny_get_obj_len() */
236
237
238 /*-------------------------------------------------------------------------
239 * Function: H5HF_tiny_op_real
240 *
241 * Purpose: Internal routine to perform operation on 'tiny' object
242 *
243 * Return: SUCCEED/FAIL
244 *
245 * Programmer: Quincey Koziol
246 * koziol@hdfgroup.org
247 * Sep 11 2006
248 *
249 *-------------------------------------------------------------------------
250 */
251 static herr_t
H5HF_tiny_op_real(H5HF_hdr_t * hdr,const uint8_t * id,H5HF_operator_t op,void * op_data)252 H5HF_tiny_op_real(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
253 void *op_data)
254 {
255 size_t enc_obj_size; /* Encoded object size */
256 herr_t ret_value = SUCCEED; /* Return value */
257
258 FUNC_ENTER_NOAPI_NOINIT
259
260 /*
261 * Check arguments.
262 */
263 HDassert(hdr);
264 HDassert(id);
265 HDassert(op);
266
267 /* Get the object's encoded length */
268 /* H5HF_tiny_obj_len can't fail */
269 ret_value = H5HF_tiny_get_obj_len(hdr, id, &enc_obj_size);
270
271 /* Advance past flag byte(s) */
272 if(!hdr->tiny_len_extended)
273 id++;
274 else {
275 /* (performed in two steps to avoid compiler bug on tg-login3 with
276 * gcc 3.2.2 - QAK)
277 */
278 id++; id++;
279 }
280
281 /* Call the user's 'op' callback */
282 if(op(id, enc_obj_size, op_data) < 0)
283 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
284
285 done:
286 FUNC_LEAVE_NOAPI(ret_value)
287 } /* end H5HF_tiny_op_real() */
288
289
290 /*-------------------------------------------------------------------------
291 * Function: H5HF_tiny_read
292 *
293 * Purpose: Read a 'tiny' object from the heap
294 *
295 * Return: SUCCEED/FAIL
296 *
297 * Programmer: Quincey Koziol
298 * koziol@hdfgroup.org
299 * Aug 8 2006
300 *
301 *-------------------------------------------------------------------------
302 */
303 herr_t
H5HF_tiny_read(H5HF_hdr_t * hdr,const uint8_t * id,void * obj)304 H5HF_tiny_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj)
305 {
306 herr_t ret_value = SUCCEED; /* Return value */
307
308 FUNC_ENTER_NOAPI_NOINIT
309
310 /*
311 * Check arguments.
312 */
313 HDassert(hdr);
314 HDassert(id);
315 HDassert(obj);
316
317 /* Call the internal 'op' routine */
318 if(H5HF_tiny_op_real(hdr, id, H5HF_op_read, obj) < 0)
319 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
320
321 done:
322 FUNC_LEAVE_NOAPI(ret_value)
323 } /* end H5HF_tiny_read() */
324
325
326 /*-------------------------------------------------------------------------
327 * Function: H5HF_tiny_op
328 *
329 * Purpose: Operate directly on a 'tiny' object
330 *
331 * Return: SUCCEED/FAIL
332 *
333 * Programmer: Quincey Koziol
334 * koziol@hdfgroup.org
335 * Sept 11 2006
336 *
337 *-------------------------------------------------------------------------
338 */
339 herr_t
H5HF_tiny_op(H5HF_hdr_t * hdr,const uint8_t * id,H5HF_operator_t op,void * op_data)340 H5HF_tiny_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
341 void *op_data)
342 {
343 herr_t ret_value = SUCCEED; /* Return value */
344
345 FUNC_ENTER_NOAPI_NOINIT
346
347 /*
348 * Check arguments.
349 */
350 HDassert(hdr);
351 HDassert(id);
352 HDassert(op);
353
354 /* Call the internal 'op' routine routine */
355 if(H5HF_tiny_op_real(hdr, id, op, op_data) < 0)
356 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
357
358 done:
359 FUNC_LEAVE_NOAPI(ret_value)
360 } /* end H5HF_tiny_op() */
361
362
363 /*-------------------------------------------------------------------------
364 * Function: H5HF_tiny_remove
365 *
366 * Purpose: Remove a 'tiny' object from the heap statistics
367 *
368 * Return: SUCCEED/FAIL
369 *
370 * Programmer: Quincey Koziol
371 * koziol@hdfgroup.org
372 * Aug 14 2006
373 *
374 *-------------------------------------------------------------------------
375 */
376 herr_t
H5HF_tiny_remove(H5HF_hdr_t * hdr,const uint8_t * id)377 H5HF_tiny_remove(H5HF_hdr_t *hdr, const uint8_t *id)
378 {
379 size_t enc_obj_size; /* Encoded object size */
380 herr_t ret_value = SUCCEED; /* Return value */
381
382 FUNC_ENTER_NOAPI_NOINIT
383
384 /*
385 * Check arguments.
386 */
387 HDassert(hdr);
388 HDassert(id);
389
390 /* Get the object's encoded length */
391 /* H5HF_tiny_obj_len can't fail */
392 ret_value = H5HF_tiny_get_obj_len(hdr, id, &enc_obj_size);
393
394 /* Update statistics about heap */
395 hdr->tiny_size -= enc_obj_size;
396 hdr->tiny_nobjs--;
397
398 /* Mark heap header as modified */
399 if(H5HF_hdr_dirty(hdr) < 0)
400 HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
401
402 done:
403 FUNC_LEAVE_NOAPI(ret_value)
404 } /* end H5HF_tiny_remove() */
405