mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
8bbdc947c4
Buffers that will be written to disk will now always be cleared since not doing this has huge security implications. Tested on: 64-bit Ubuntu 15.10 (Linux 4.2.0, x86_64) gcc 5.2.1 serial autotools parallel autotools (MPICH 3.1.4) serial CMake
407 lines
12 KiB
C
407 lines
12 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by The HDF Group. *
|
||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||
* All rights reserved. *
|
||
* *
|
||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||
* terms governing use, modification, and redistribution, is contained in *
|
||
* the files COPYING and Copyright.html. COPYING can be found at the root *
|
||
* of the source code distribution tree; Copyright.html can be found at the *
|
||
* root level of an installed copy of the electronic HDF5 document set and *
|
||
* is linked from the top-level documents page. It can also be found at *
|
||
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
|
||
* access to either file, you may request a copy from help@hdfgroup.org. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*-------------------------------------------------------------------------
|
||
*
|
||
* Created: H5HFtiny.c
|
||
* Aug 14 2006
|
||
* Quincey Koziol <koziol@hdfgroup.org>
|
||
*
|
||
* Purpose: Routines for "tiny" objects in fractal heap
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
|
||
/****************/
|
||
/* Module Setup */
|
||
/****************/
|
||
|
||
#include "H5HFmodule.h" /* This source code file is part of the H5HF module */
|
||
|
||
|
||
/***********/
|
||
/* Headers */
|
||
/***********/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5HFpkg.h" /* Fractal heaps */
|
||
|
||
|
||
/****************/
|
||
/* Local Macros */
|
||
/****************/
|
||
|
||
/* Tiny object length information */
|
||
#define H5HF_TINY_LEN_SHORT 16 /* Max. length able to be encoded in first heap ID byte */
|
||
#define H5HF_TINY_MASK_SHORT 0x0F /* Mask for length in first heap ID byte */
|
||
#define H5HF_TINY_MASK_EXT 0x0FFF /* Mask for length in two heap ID bytes */
|
||
#define H5HF_TINY_MASK_EXT_1 0x0F00 /* Mask for length in first byte of two heap ID bytes */
|
||
#define H5HF_TINY_MASK_EXT_2 0x00FF /* Mask for length in second byte of two heap ID bytes */
|
||
|
||
|
||
/******************/
|
||
/* Local Typedefs */
|
||
/******************/
|
||
|
||
|
||
/********************/
|
||
/* Package Typedefs */
|
||
/********************/
|
||
|
||
|
||
/********************/
|
||
/* Local Prototypes */
|
||
/********************/
|
||
static herr_t H5HF_tiny_op_real(H5HF_hdr_t *hdr, const uint8_t *id,
|
||
H5HF_operator_t op, void *op_data);
|
||
|
||
|
||
/*********************/
|
||
/* Package Variables */
|
||
/*********************/
|
||
|
||
|
||
/*****************************/
|
||
/* Library Private Variables */
|
||
/*****************************/
|
||
|
||
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_init
|
||
*
|
||
* Purpose: Initialize information for tracking 'tiny' objects
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Aug 14 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_init(H5HF_hdr_t *hdr)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
|
||
/* Compute information about 'tiny' objects for the heap */
|
||
|
||
/* Check if tiny objects need an extra byte for their length */
|
||
/* (account for boundary condition when length of an object would need an
|
||
* extra byte, but using that byte means that the extra length byte is
|
||
* unneccessary)
|
||
*/
|
||
if((hdr->id_len - 1) <= H5HF_TINY_LEN_SHORT) {
|
||
hdr->tiny_max_len = hdr->id_len - 1;
|
||
hdr->tiny_len_extended = FALSE;
|
||
} /* end if */
|
||
else if((hdr->id_len - 1) == (H5HF_TINY_LEN_SHORT + 1)) {
|
||
hdr->tiny_max_len = H5HF_TINY_LEN_SHORT;
|
||
hdr->tiny_len_extended = FALSE;
|
||
} /* end if */
|
||
else {
|
||
hdr->tiny_max_len = hdr->id_len - 2;
|
||
hdr->tiny_len_extended = TRUE;
|
||
} /* end else */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_tiny_init() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_insert
|
||
*
|
||
* Purpose: Pack a 'tiny' object in a heap ID
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Aug 14 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_insert(H5HF_hdr_t *hdr, size_t obj_size, const void *obj, void *_id)
|
||
{
|
||
uint8_t *id = (uint8_t *)_id; /* Pointer to ID buffer */
|
||
size_t enc_obj_size; /* Encoded object size */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
#ifdef QAK
|
||
HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
|
||
#endif /* QAK */
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(obj_size <= hdr->tiny_max_len);
|
||
HDassert(obj_size <= (H5HF_TINY_MASK_EXT + 1));
|
||
HDassert(obj);
|
||
HDassert(id);
|
||
|
||
/* Adjust object's size for encoding it */
|
||
enc_obj_size = obj_size - 1;
|
||
|
||
/* Encode object into ID */
|
||
if(!hdr->tiny_len_extended) {
|
||
*id++ = (uint8_t)(H5HF_ID_VERS_CURR | H5HF_ID_TYPE_TINY |
|
||
(enc_obj_size & H5HF_TINY_MASK_SHORT));
|
||
} /* end if */
|
||
else {
|
||
*id++ = (uint8_t)(H5HF_ID_VERS_CURR | H5HF_ID_TYPE_TINY |
|
||
((enc_obj_size & H5HF_TINY_MASK_EXT_1) >> 8));
|
||
*id++ = enc_obj_size & H5HF_TINY_MASK_EXT_2;
|
||
} /* end else */
|
||
|
||
HDmemcpy(id, obj, obj_size);
|
||
HDmemset(id + obj_size, 0, (hdr->id_len - ((size_t)1 + (size_t)hdr->tiny_len_extended + obj_size)));
|
||
|
||
/* Update statistics about heap */
|
||
hdr->tiny_size += obj_size;
|
||
hdr->tiny_nobjs++;
|
||
|
||
/* Mark heap header as modified */
|
||
if(H5HF_hdr_dirty(hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_tiny_insert() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_get_obj_len
|
||
*
|
||
* Purpose: Get the size of a 'tiny' object in a fractal heap
|
||
*
|
||
* Return: SUCCEED (Can't fail)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Aug 14 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_get_obj_len(H5HF_hdr_t *hdr, const uint8_t *id, size_t *obj_len_p)
|
||
{
|
||
size_t enc_obj_size; /* Encoded object size */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(id);
|
||
HDassert(obj_len_p);
|
||
|
||
/* Check if 'tiny' object ID is in extended form, and retrieve encoded size */
|
||
if(!hdr->tiny_len_extended)
|
||
enc_obj_size = *id & H5HF_TINY_MASK_SHORT;
|
||
else
|
||
/* (performed in this odd way to avoid compiler bug on tg-login3 with
|
||
* gcc 3.2.2 - QAK)
|
||
*/
|
||
enc_obj_size = (size_t)*(id + 1) | ((size_t)(*id & H5HF_TINY_MASK_EXT_1) << 8);
|
||
|
||
/* Set the object's length */
|
||
*obj_len_p = enc_obj_size + 1;
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_tiny_get_obj_len() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_op_real
|
||
*
|
||
* Purpose: Internal routine to perform operation on 'tiny' object
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Sep 11 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_tiny_op_real(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
|
||
void *op_data)
|
||
{
|
||
size_t enc_obj_size; /* Encoded object size */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(id);
|
||
HDassert(op);
|
||
|
||
/* Get the object's encoded length */
|
||
/* H5HF_tiny_obj_len can't fail */
|
||
ret_value = H5HF_tiny_get_obj_len(hdr, id, &enc_obj_size);
|
||
|
||
/* Advance past flag byte(s) */
|
||
if(!hdr->tiny_len_extended)
|
||
id++;
|
||
else {
|
||
/* (performed in two steps to avoid compiler bug on tg-login3 with
|
||
* gcc 3.2.2 - QAK)
|
||
*/
|
||
id++; id++;
|
||
}
|
||
|
||
/* Call the user's 'op' callback */
|
||
if(op(id, enc_obj_size, op_data) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_tiny_op_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_read
|
||
*
|
||
* Purpose: Read a 'tiny' object from the heap
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Aug 8 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_read(H5HF_hdr_t *hdr, const uint8_t *id, void *obj)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(id);
|
||
HDassert(obj);
|
||
|
||
/* Call the internal 'op' routine */
|
||
if(H5HF_tiny_op_real(hdr, id, H5HF_op_read, obj) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_tiny_read() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_op
|
||
*
|
||
* Purpose: Operate directly on a 'tiny' object
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Sept 11 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_op(H5HF_hdr_t *hdr, const uint8_t *id, H5HF_operator_t op,
|
||
void *op_data)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(id);
|
||
HDassert(op);
|
||
|
||
/* Call the internal 'op' routine routine */
|
||
if(H5HF_tiny_op_real(hdr, id, op, op_data) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_tiny_op() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_tiny_remove
|
||
*
|
||
* Purpose: Remove a 'tiny' object from the heap statistics
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* Aug 14 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_tiny_remove(H5HF_hdr_t *hdr, const uint8_t *id)
|
||
{
|
||
size_t enc_obj_size; /* Encoded object size */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(id);
|
||
|
||
/* Get the object's encoded length */
|
||
/* H5HF_tiny_obj_len can't fail */
|
||
ret_value = H5HF_tiny_get_obj_len(hdr, id, &enc_obj_size);
|
||
|
||
/* Update statistics about heap */
|
||
hdr->tiny_size -= enc_obj_size;
|
||
hdr->tiny_nobjs--;
|
||
|
||
/* Mark heap header as modified */
|
||
if(H5HF_hdr_dirty(hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_tiny_remove() */
|