summaryrefslogtreecommitdiffstats
path: root/hl/src/H5DO.c
blob: 8db6768227ee3bb33ce8f82c74ef3e5b1e2dcd7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 COPYING file, which can be found at the root of the source code       *
 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

/* High-level library internal header file */
#include "H5HLprivate2.h"

/* public LT prototypes			*/
#include "H5DOpublic.h"



/*-------------------------------------------------------------------------
 * Function:	H5DOwrite_chunk
 *
 * Purpose:     Writes an entire chunk to the file directly.	
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Raymond Lu
 *		30 July 2012
 *
 *-------------------------------------------------------------------------
 */
herr_t
H5DOwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *offset, 
         size_t data_size, const void *buf)
{
    hbool_t created_dxpl = FALSE;       /* Whether we created a DXPL */
    hbool_t do_direct_write = TRUE;     /* Flag for direct writes */
    uint32_t data_size_32;              /* Chunk data size (limited to 32-bits currently) */
    herr_t  ret_value = FAIL;           /* Return value */
    
    /* Check arguments */
    if(dset_id < 0)
        goto done;
    if(!buf)
        goto done;
    if(!offset)
        goto done;
    if(!data_size)
        goto done;
    data_size_32 = (uint32_t)data_size;
    if(data_size != (size_t)data_size_32)
        goto done;

    /* If the user passed in a default DXPL, create one to pass to H5Dwrite() */
    if(H5P_DEFAULT == dxpl_id) {
	if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
            goto done;
        created_dxpl = TRUE;
    } /* end if */

    /* Set direct write parameters */
    if(H5Pset(dxpl_id, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &do_direct_write) < 0)
        goto done;
    if(H5Pset(dxpl_id, H5D_XFER_DIRECT_CHUNK_WRITE_FILTERS_NAME, &filters) < 0)
        goto done;
    if(H5Pset(dxpl_id, H5D_XFER_DIRECT_CHUNK_WRITE_OFFSET_NAME, &offset) < 0)
        goto done;
    if(H5Pset(dxpl_id, H5D_XFER_DIRECT_CHUNK_WRITE_DATASIZE_NAME, &data_size_32) < 0)
        goto done;

    /* Write chunk */
    if(H5Dwrite(dset_id, 0, H5S_ALL, H5S_ALL, dxpl_id, buf) < 0)
        goto done;

    /* Indicate success */
    ret_value = SUCCEED;

done:
    if(created_dxpl) {
        if(H5Pclose(dxpl_id) < 0)
            ret_value = FAIL;
    } /* end if */
    else
        /* Reset the direct write flag on user DXPL */
        if(H5Pset(dxpl_id, H5D_XFER_DIRECT_CHUNK_WRITE_FLAG_NAME, &do_direct_write) < 0)
            ret_value = FAIL;

    return(ret_value);
} /* end H5DOwrite_chunk() */


/*
 * Function:	H5DOappend()
 *
 * Purpose:     To append elements to a dataset.
 *		axis: the dataset dimension (zero-based) for the append
 *		extension: the # of elements to append for the axis-th dimension
 *		memtype: the datatype
 *		buf: buffer with data for the append
 *
 * Return:	Non-negative on success/Negative on failure
 *
 * Programmer:	Vailin Choi; Jan 2014
 *
 * Note:
 * 	This routine is copied from the fast forward feature branch: features/hdf5_ff
 *	src/H5FF.c:H5DOappend() with the following modifications:
 * 	1) Remove and replace macro calls such as
 *		FUNC_ENTER_API, H5TRACE, HGOTO_ERROR 
 * 	   accordingly because hl does not have these macros
 *	2) Replace H5I_get_type() by H5Iget_type()
 *	3) Replace H5P_isa_class() by H5Pisa_class()
 *	4) Fix a bug in the following: replace extension by size[axis]
 *		if(extension < old_size) {
 *		  ret_value = FAIL;
 *		  goto done;
 *   		}
 */
herr_t
H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension, 
           hid_t memtype, const void *buf)
{
    hbool_t created_dxpl = FALSE;       /* Whether we created a DXPL */
    hsize_t size[H5S_MAX_RANK];		/* The new size (after extension */
    hsize_t old_size = 0; 		/* The size of the dimension to be extended */
    int sndims; 			/* Number of dimensions in dataspace (signed) */
    unsigned ndims; 			/* Number of dimensions in dataspace */
    hid_t space_id = FAIL; 		/* Old file space */
    hid_t new_space_id = FAIL; 		/* New file space (after extension) */
    hid_t mem_space_id = FAIL; 		/* Memory space for data buffer */
    hssize_t snelmts; 			/* Number of elements in selection (signed) */
    hsize_t nelmts; 			/* Number of elements in selection */
    hid_t dapl = FAIL;			/* Dataset access property list */

    hsize_t start[H5S_MAX_RANK];	/* H5Sselect_Hyperslab: starting offset */
    hsize_t count[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of blocks to select */
    hsize_t stride[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of elements to move when selecting */
    hsize_t block[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of elements in a block */

    hsize_t *boundary = NULL;		/* Boundary set in append flush property */
    H5D_append_cb_t append_cb;		/* Callback function set in append flush property */
    void *udata;			/* User data set in append flush property */
    hbool_t hit = FALSE;		/* Boundary is hit or not */
    hsize_t k;				/* Local index variable */
    unsigned u; 		        /* Local index variable */
    herr_t ret_value = FAIL;		/* Return value */

    /* check arguments */
    if(H5I_DATASET != H5Iget_type(dset_id))
	goto done;

    /* If the user passed in a default DXPL, create one to pass to H5Dwrite() */
    if(H5P_DEFAULT == dxpl_id) {
        if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
            goto done;
        created_dxpl = TRUE;
    } /* end if */
    else if(TRUE != H5Pisa_class(dxpl_id, H5P_DATASET_XFER))
	goto done;

    /* Get the dataspace of the dataset */
    if(FAIL == (space_id = H5Dget_space(dset_id)))
	goto done;

    /* Get the rank of this dataspace */
    if((sndims = H5Sget_simple_extent_ndims(space_id)) < 0)
	goto done;
    ndims = (unsigned)sndims;

    /* Verify correct axis */
    if(axis >= ndims)
	goto done;

    /* Get the dimensions sizes of the dataspace */
    if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0)
	goto done;

    /* Adjust the dimension size of the requested dimension, 
       but first record the old dimension size */
    old_size = size[axis];
    size[axis] += extension;
    if(size[axis] < old_size)
	goto done;

    /* Set the extent of the dataset to the new dimension */
    if(H5Dset_extent(dset_id, size) < 0)
	goto done;

    /* Get the new dataspace of the dataset */
    if(FAIL == (new_space_id = H5Dget_space(dset_id)))
	goto done;

    /* Select a hyperslab corresponding to the append operation */
    for(u = 0 ; u < ndims ; u++) {
        start[u] = 0;
        stride[u] = 1;
        count[u] = size[u];
        block[u] = 1;
        if(u == axis) {
            count[u] = extension;
            start[u] = old_size;
        } /* end if */
    } /* end for */
    if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block))
	goto done;

    /* The # of elemnts in the new extended dataspace */
    if((snelmts = H5Sget_select_npoints(new_space_id)) < 0)
	goto done;
    nelmts = (hsize_t)snelmts;

    /* create a memory space */
    if(FAIL == (mem_space_id = H5Screate_simple(1, &nelmts, NULL)))
	goto done;

    /* Write the data */
    if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0)
	goto done;

    /* Obtain the dataset's access property list */
    if((dapl = H5Dget_access_plist(dset_id)) < 0)
	goto done;

    /* Allocate the boundary array */
    boundary = (hsize_t *)HDmalloc(ndims * sizeof(hsize_t));

    /* Retrieve the append flush property */
    if(H5Pget_append_flush(dapl, ndims, boundary, &append_cb, &udata) < 0)
	goto done;

    /* No boundary for this axis */
    if(boundary[axis] != 0) {

	/* Determine whether a boundary is hit or not */
	for(k = start[axis]; k < size[axis]; k++)
	    if(!((k + 1) % boundary[axis])) {
		hit = TRUE;
		break;
	    }

	if(hit) { /* Hit the boundary */
	    /* Invoke callback if there is one */
	    if(append_cb && append_cb(dset_id, size, udata) < 0)
		goto done;

	    /* Do a dataset flush */
	    if(H5Dflush(dset_id) < 0)
		goto done;
	} /* end if */
    } /* end if */

    /* Indicate success */
    ret_value = SUCCEED;

done:
    /* Close dxpl if we created it vs. one was passed in */
    if(created_dxpl) {
        if(H5Pclose(dxpl_id) < 0)
            ret_value = FAIL;
    } /* end if */

    /* Close old dataspace */
    if(space_id != FAIL && H5Sclose(space_id) < 0)
	ret_value = FAIL;

    /* Close new dataspace */
    if(new_space_id != FAIL && H5Sclose(new_space_id) < 0)
	ret_value = FAIL;

    /* Close memory dataspace */
    if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0)
	ret_value = FAIL;

    /* Close the dataset access property list */
    if(dapl != FAIL && H5Pclose(dapl) < 0)
	ret_value = FAIL;

    if(boundary)
	HDfree(boundary);

    return ret_value;
} /* H5DOappend() */