1 /*
2 * Copyright (C) 2018 Francesc Alted, Aleix Alcacer.
3 * Copyright (C) 2019-present Blosc Development team <blosc@blosc.org>
4 * All rights reserved.
5 *
6 * This source code is licensed under both the BSD-style license (found in the
7 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
8 * in the COPYING file in the root directory of this source tree).
9 * You may select, at your option, one of the above-listed licenses.
10 */
11
12 #include <caterva.h>
13
14 #include "caterva_utils.h"
15
16
caterva_ctx_new(caterva_config_t * cfg,caterva_ctx_t ** ctx)17 int caterva_ctx_new(caterva_config_t *cfg, caterva_ctx_t **ctx) {
18 CATERVA_ERROR_NULL(cfg);
19 CATERVA_ERROR_NULL(ctx);
20
21 (*ctx) = (caterva_ctx_t *) cfg->alloc(sizeof(caterva_ctx_t));
22 CATERVA_ERROR_NULL(ctx);
23 if (!(*ctx)) {
24 CATERVA_TRACE_ERROR("Allocation fails");
25 return CATERVA_ERR_NULL_POINTER;
26 }
27
28 (*ctx)->cfg = (caterva_config_t *) cfg->alloc(sizeof(caterva_config_t));
29 CATERVA_ERROR_NULL((*ctx)->cfg);
30 if (!(*ctx)->cfg) {
31 CATERVA_TRACE_ERROR("Allocation fails");
32 return CATERVA_ERR_NULL_POINTER;
33 }
34 memcpy((*ctx)->cfg, cfg, sizeof(caterva_config_t));
35
36 return CATERVA_SUCCEED;
37 }
38
caterva_ctx_free(caterva_ctx_t ** ctx)39 int caterva_ctx_free(caterva_ctx_t **ctx) {
40 CATERVA_ERROR_NULL(ctx);
41
42 void (*auxfree)(void *) = (*ctx)->cfg->free;
43 auxfree((*ctx)->cfg);
44 auxfree(*ctx);
45
46 return CATERVA_SUCCEED;
47 }
48
49 // Only for internal use
caterva_update_shape(caterva_array_t * array,int8_t ndim,int64_t * shape,int32_t * chunkshape,int32_t * blockshape)50 int caterva_update_shape(caterva_array_t *array, int8_t ndim, int64_t *shape,
51 int32_t *chunkshape, int32_t *blockshape) {
52 array->ndim = ndim;
53 array->nitems = 1;
54 array->extnitems = 1;
55 array->extchunknitems = 1;
56 array->chunknitems = 1;
57 array->blocknitems = 1;
58 for (int i = 0; i < CATERVA_MAX_DIM; ++i) {
59 if (i < ndim) {
60 array->shape[i] = shape[i];
61 array->chunkshape[i] = chunkshape[i];
62 array->blockshape[i] = blockshape[i];
63 if (shape[i] != 0) {
64 if (shape[i] % array->chunkshape[i] == 0) {
65 array->extshape[i] = shape[i];
66 } else {
67 array->extshape[i] = shape[i] + chunkshape[i] - shape[i] % chunkshape[i];
68 }
69 if (chunkshape[i] % blockshape[i] == 0) {
70 array->extchunkshape[i] = chunkshape[i];
71 } else {
72 array->extchunkshape[i] =
73 chunkshape[i] + blockshape[i] - chunkshape[i] % blockshape[i];
74 }
75 } else {
76 array->extchunkshape[i] = 0;
77 array->extshape[i] = 0;
78 }
79 } else {
80 array->blockshape[i] = 1;
81 array->chunkshape[i] = 1;
82 array->extshape[i] = 1;
83 array->extchunkshape[i] = 1;
84 array->shape[i] = 1;
85 }
86 array->nitems *= array->shape[i];
87 array->extnitems *= array->extshape[i];
88 array->extchunknitems *= array->extchunkshape[i];
89 array->chunknitems *= array->chunkshape[i];
90 array->blocknitems *= array->blockshape[i];
91 }
92
93
94 if (array->sc) {
95 uint8_t *smeta = NULL;
96 // Serialize the dimension info ...
97 int32_t smeta_len =
98 serialize_meta(array->ndim, array->shape, array->chunkshape, array->blockshape,
99 &smeta);
100 if (smeta_len < 0) {
101 fprintf(stderr, "error during serializing dims info for Caterva");
102 return -1;
103 }
104 // ... and update it in its metalayer
105 if (blosc2_meta_exists(array->sc, "caterva") < 0) {
106 if (blosc2_meta_add(array->sc, "caterva", smeta, (uint32_t) smeta_len) < 0) {
107 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
108 }
109 } else {
110 if (blosc2_meta_update(array->sc, "caterva", smeta, (uint32_t) smeta_len) < 0) {
111 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
112 }
113 }
114 free(smeta);
115 }
116
117 return CATERVA_SUCCEED;
118 }
119
120 // Only for internal use
caterva_array_without_schunk(caterva_ctx_t * ctx,caterva_params_t * params,caterva_storage_t * storage,caterva_array_t ** array)121 int caterva_array_without_schunk(caterva_ctx_t *ctx, caterva_params_t *params,
122 caterva_storage_t *storage, caterva_array_t **array) {
123 /* Create a caterva_array_t buffer */
124 (*array) = (caterva_array_t *) ctx->cfg->alloc(sizeof(caterva_array_t));
125 CATERVA_ERROR_NULL(*array);
126
127 (*array)->cfg = (caterva_config_t *) ctx->cfg->alloc(sizeof(caterva_config_t));
128 memcpy((*array)->cfg, ctx->cfg, sizeof(caterva_config_t));
129
130 (*array)->sc = NULL;
131
132 (*array)->ndim = params->ndim;
133 (*array)->itemsize = params->itemsize;
134
135 int64_t *shape = params->shape;
136 int32_t *chunkshape = storage->chunkshape;
137 int32_t *blockshape = storage->blockshape;
138
139 caterva_update_shape(*array, params->ndim, shape, chunkshape, blockshape);
140
141 // The partition cache (empty initially)
142 (*array)->chunk_cache.data = NULL;
143 (*array)->chunk_cache.nchunk = -1; // means no valid cache yet
144
145 if ((*array)->nitems != 0) {
146 (*array)->nchunks = (*array)->extnitems / (*array)->chunknitems;
147 } else {
148 (*array)->nchunks = 0;
149 }
150
151 return CATERVA_SUCCEED;
152 }
153
154 // Only for internal use
caterva_blosc_array_new(caterva_ctx_t * ctx,caterva_params_t * params,caterva_storage_t * storage,int special_value,caterva_array_t ** array)155 int caterva_blosc_array_new(caterva_ctx_t *ctx, caterva_params_t *params,
156 caterva_storage_t *storage,
157 int special_value, caterva_array_t **array) {
158 CATERVA_ERROR(caterva_array_without_schunk(ctx, params, storage, array));
159 blosc2_storage b_storage;
160 blosc2_cparams b_cparams;
161 blosc2_dparams b_dparams;
162 CATERVA_ERROR(create_blosc_params(ctx, params, storage, &b_cparams, &b_dparams, &b_storage));
163
164 blosc2_schunk *sc = blosc2_schunk_new(&b_storage);
165 if (sc == NULL) {
166 CATERVA_TRACE_ERROR("Pointer is NULL");
167 return CATERVA_ERR_BLOSC_FAILED;
168 }
169
170 // Serialize the dimension info
171 if (sc->nmetalayers >= BLOSC2_MAX_METALAYERS) {
172 CATERVA_TRACE_ERROR("the number of metalayers for this schunk has been exceeded");
173 return CATERVA_ERR_BLOSC_FAILED;
174 }
175 uint8_t *smeta = NULL;
176 int32_t smeta_len = serialize_meta(params->ndim,
177 (*array)->shape,
178 (*array)->chunkshape,
179 (*array)->blockshape, &smeta);
180 if (smeta_len < 0) {
181 CATERVA_TRACE_ERROR("error during serializing dims info for Caterva");
182 return CATERVA_ERR_BLOSC_FAILED;
183 }
184
185 // And store it in caterva metalayer
186 if (blosc2_meta_add(sc, "caterva", smeta, (uint32_t) smeta_len) < 0) {
187 return CATERVA_ERR_BLOSC_FAILED;
188 }
189
190 free(smeta);
191
192 for (int i = 0; i < storage->nmetalayers; ++i) {
193 char *name = storage->metalayers[i].name;
194 uint8_t *data = storage->metalayers[i].sdata;
195 int32_t size = storage->metalayers[i].size;
196 if (blosc2_meta_add(sc, name, data, size) < 0) {
197 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
198 }
199 }
200
201 // Fill schunk with uninit values
202 if ((*array)->nitems != 0) {
203 int32_t chunksize = (int32_t) (*array)->extchunknitems * (*array)->itemsize;
204 int64_t nchunks = (*array)->extnitems / (*array)->chunknitems;
205 int64_t nitems = nchunks * (*array)->extchunknitems;
206 // blosc2_schunk_fill_special(sc, nitems, BLOSC2_SPECIAL_ZERO, chunksize);
207 blosc2_schunk_fill_special(sc, nitems, special_value, chunksize);
208 }
209 (*array)->sc = sc;
210 (*array)->nchunks = sc->nchunks;
211
212 return CATERVA_SUCCEED;
213 }
214
caterva_empty(caterva_ctx_t * ctx,caterva_params_t * params,caterva_storage_t * storage,caterva_array_t ** array)215 int caterva_empty(caterva_ctx_t *ctx, caterva_params_t *params,
216 caterva_storage_t *storage, caterva_array_t **array) {
217 CATERVA_ERROR_NULL(ctx);
218 CATERVA_ERROR_NULL(params);
219 CATERVA_ERROR_NULL(storage);
220 CATERVA_ERROR_NULL(array);
221
222 // CATERVA_ERROR(caterva_blosc_array_new(ctx, params, storage, BLOSC2_SPECIAL_UNINIT, array));
223 // Avoid variable cratios
224 CATERVA_ERROR(caterva_blosc_array_new(ctx, params, storage, BLOSC2_SPECIAL_ZERO, array));
225
226 return CATERVA_SUCCEED;
227 }
228
caterva_zeros(caterva_ctx_t * ctx,caterva_params_t * params,caterva_storage_t * storage,caterva_array_t ** array)229 int caterva_zeros(caterva_ctx_t *ctx, caterva_params_t *params,
230 caterva_storage_t *storage, caterva_array_t **array) {
231 CATERVA_ERROR_NULL(ctx);
232 CATERVA_ERROR_NULL(params);
233 CATERVA_ERROR_NULL(storage);
234 CATERVA_ERROR_NULL(array);
235
236 CATERVA_ERROR(caterva_blosc_array_new(ctx, params, storage, BLOSC2_SPECIAL_ZERO, array));
237
238 return CATERVA_SUCCEED;
239 }
240
caterva_full(caterva_ctx_t * ctx,caterva_params_t * params,caterva_storage_t * storage,void * fill_value,caterva_array_t ** array)241 int caterva_full(caterva_ctx_t *ctx, caterva_params_t *params,
242 caterva_storage_t *storage, void *fill_value, caterva_array_t **array) {
243 CATERVA_ERROR_NULL(ctx);
244 CATERVA_ERROR_NULL(params);
245 CATERVA_ERROR_NULL(storage);
246 CATERVA_ERROR_NULL(array);
247
248 CATERVA_ERROR(caterva_empty(ctx, params, storage, array));
249
250 int64_t chunkbytes = (*array)->extchunknitems * (*array)->itemsize;
251
252 blosc2_cparams *cparams;
253 if (blosc2_schunk_get_cparams((*array)->sc, &cparams) != 0) {
254 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
255 }
256
257 int32_t chunksize = BLOSC_EXTENDED_HEADER_LENGTH + (*array)->itemsize;
258 uint8_t *chunk = malloc(chunksize);
259 if (blosc2_chunk_repeatval(*cparams, chunkbytes, chunk, chunksize, fill_value) < 0) {
260 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
261 }
262 free(cparams);
263
264 for (int i = 0; i < (*array)->sc->nchunks; ++i) {
265 if (blosc2_schunk_update_chunk((*array)->sc, i, chunk, true) < 0) {
266 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
267 }
268 }
269 free(chunk);
270
271 return CATERVA_SUCCEED;
272 }
273
caterva_from_schunk(caterva_ctx_t * ctx,blosc2_schunk * schunk,caterva_array_t ** array)274 int caterva_from_schunk(caterva_ctx_t *ctx, blosc2_schunk *schunk, caterva_array_t **array) {
275 CATERVA_ERROR_NULL(ctx);
276 CATERVA_ERROR_NULL(schunk);
277 CATERVA_ERROR_NULL(array);
278
279 if (ctx == NULL) {
280 CATERVA_TRACE_ERROR("Context is null");
281 return CATERVA_ERR_NULL_POINTER;
282 }
283 if (schunk == NULL) {
284 CATERVA_TRACE_ERROR("Schunk is null");
285 return CATERVA_ERR_NULL_POINTER;
286 }
287
288 blosc2_cparams *cparams;
289 if (blosc2_schunk_get_cparams(schunk, &cparams) < 0) {
290 CATERVA_TRACE_ERROR("Blosc error");
291 return CATERVA_ERR_NULL_POINTER;
292 }
293 uint8_t itemsize = (int8_t) cparams->typesize;
294 free(cparams);
295
296 caterva_params_t params = {0};
297 params.itemsize = itemsize;
298 caterva_storage_t storage = {0};
299 storage.urlpath = schunk->storage->urlpath;
300 storage.sequencial = schunk->storage->contiguous;
301
302 // Deserialize the caterva metalayer
303 uint8_t *smeta;
304 uint32_t smeta_len;
305 if (blosc2_meta_get(schunk, "caterva", &smeta, &smeta_len) < 0) {
306 CATERVA_TRACE_ERROR("Blosc error");
307 return CATERVA_ERR_BLOSC_FAILED;
308 }
309 deserialize_meta(smeta, smeta_len, ¶ms.ndim,
310 params.shape,
311 storage.chunkshape,
312 storage.blockshape);
313 free(smeta);
314
315 caterva_config_t cfg = CATERVA_CONFIG_DEFAULTS;
316 caterva_config_from_schunk(ctx, schunk, &cfg);
317
318 caterva_ctx_t *ctx_sc;
319 caterva_ctx_new(&cfg, &ctx_sc);
320
321 caterva_array_without_schunk(ctx_sc, ¶ms, &storage, array);
322
323 caterva_ctx_free(&ctx_sc);
324
325 (*array)->sc = schunk;
326
327 if ((*array) == NULL) {
328 CATERVA_TRACE_ERROR("Error creating a caterva container from a frame");
329 return CATERVA_ERR_NULL_POINTER;
330 }
331
332 return CATERVA_SUCCEED;
333 }
334
caterva_from_serial_schunk(caterva_ctx_t * ctx,uint8_t * serial_schunk,int64_t len,caterva_array_t ** array)335 int caterva_from_serial_schunk(caterva_ctx_t *ctx, uint8_t *serial_schunk, int64_t len,
336 caterva_array_t **array) {
337 CATERVA_ERROR_NULL(ctx);
338 CATERVA_ERROR_NULL(serial_schunk);
339 CATERVA_ERROR_NULL(array);
340
341 blosc2_schunk *sc = blosc2_schunk_from_buffer(serial_schunk, len, true);
342 if (sc == NULL) {
343 CATERVA_TRACE_ERROR("Blosc error");
344 return CATERVA_ERR_BLOSC_FAILED;
345 }
346 // ...and create a caterva array out of it
347 CATERVA_ERROR(caterva_from_schunk(ctx, sc, array));
348
349 return CATERVA_SUCCEED;
350 }
351
caterva_open(caterva_ctx_t * ctx,const char * urlpath,caterva_array_t ** array)352 int caterva_open(caterva_ctx_t *ctx, const char *urlpath, caterva_array_t **array) {
353 CATERVA_ERROR_NULL(ctx);
354 CATERVA_ERROR_NULL(urlpath);
355 CATERVA_ERROR_NULL(array);
356
357 blosc2_schunk *sc = blosc2_schunk_open(urlpath);
358
359 // ...and create a caterva array out of it
360 CATERVA_ERROR(caterva_from_schunk(ctx, sc, array));
361
362 return CATERVA_SUCCEED;
363 }
364
caterva_free(caterva_ctx_t * ctx,caterva_array_t ** array)365 int caterva_free(caterva_ctx_t *ctx, caterva_array_t **array) {
366 CATERVA_ERROR_NULL(ctx);
367 CATERVA_ERROR_NULL(array);
368 void (*free)(void *) = (*array)->cfg->free;
369
370 free((*array)->cfg);
371 if (*array) {
372 if ((*array)->sc != NULL) {
373 blosc2_schunk_free((*array)->sc);
374 }
375 free(*array);
376 }
377 return CATERVA_SUCCEED;
378 }
379
caterva_from_buffer(caterva_ctx_t * ctx,void * buffer,int64_t buffersize,caterva_params_t * params,caterva_storage_t * storage,caterva_array_t ** array)380 int caterva_from_buffer(caterva_ctx_t *ctx, void *buffer, int64_t buffersize,
381 caterva_params_t *params, caterva_storage_t *storage,
382 caterva_array_t **array) {
383 CATERVA_ERROR_NULL(ctx);
384 CATERVA_ERROR_NULL(params);
385 CATERVA_ERROR_NULL(storage);
386 CATERVA_ERROR_NULL(buffer);
387 CATERVA_ERROR_NULL(array);
388
389 CATERVA_ERROR(caterva_empty(ctx, params, storage, array));
390
391 if (buffersize < (int64_t)(*array)->nitems * (*array)->itemsize) {
392 CATERVA_TRACE_ERROR("The buffersize (%lld) is smaller than the array size (%lld)",
393 buffersize, (int64_t)(*array)->nitems * (*array)->itemsize);
394 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
395 }
396
397 if ((*array)->nitems == 0) {
398 return CATERVA_SUCCEED;
399 }
400
401 int64_t start[CATERVA_MAX_DIM] = {0};
402 int64_t *stop = (*array)->shape;
403 int64_t *shape = (*array)->shape;
404 CATERVA_ERROR(caterva_set_slice_buffer(ctx, buffer, shape, buffersize, start, stop, *array));
405
406 return CATERVA_SUCCEED;
407 }
408
caterva_to_buffer(caterva_ctx_t * ctx,caterva_array_t * array,void * buffer,int64_t buffersize)409 int caterva_to_buffer(caterva_ctx_t *ctx, caterva_array_t *array, void *buffer,
410 int64_t buffersize) {
411 CATERVA_ERROR_NULL(ctx);
412 CATERVA_ERROR_NULL(array);
413 CATERVA_ERROR_NULL(buffer);
414
415 if (buffersize < (int64_t) array->nitems * array->itemsize) {
416 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
417 }
418
419 if (array->nitems == 0) {
420 return CATERVA_SUCCEED;
421 }
422
423 int64_t start[CATERVA_MAX_DIM] = {0};
424 int64_t *stop = array->shape;
425 CATERVA_ERROR(caterva_get_slice_buffer(ctx, array, start, stop,
426 buffer, array->shape, buffersize));
427 return CATERVA_SUCCEED;
428 }
429
430
431 // Only for internal use: It is used for setting slices and for getting slices.
caterva_blosc_slice(caterva_ctx_t * ctx,void * buffer,int64_t buffersize,int64_t * start,int64_t * stop,int64_t * shape,caterva_array_t * array,bool set_slice)432 int caterva_blosc_slice(caterva_ctx_t *ctx, void *buffer,
433 int64_t buffersize, int64_t *start, int64_t *stop, int64_t *shape,
434 caterva_array_t *array, bool set_slice) {
435 CATERVA_ERROR_NULL(ctx);
436 CATERVA_ERROR_NULL(buffer);
437 CATERVA_ERROR_NULL(start);
438 CATERVA_ERROR_NULL(stop);
439 CATERVA_ERROR_NULL(array);
440 if (buffersize < 0) {
441 CATERVA_TRACE_ERROR("buffersize is < 0");
442 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
443 }
444
445 uint8_t *buffer_b = (uint8_t *) buffer;
446 int64_t *buffer_start = start;
447 int64_t *buffer_stop = stop;
448 int64_t *buffer_shape = shape;
449
450 int8_t ndim = array->ndim;
451 int64_t nchunks = array->extnitems / array->chunknitems;
452
453 // 0-dim case
454 if (ndim == 0) {
455 if (set_slice) {
456 uint32_t chunk_size = array->itemsize + BLOSC_MAX_OVERHEAD;
457 uint8_t *chunk = malloc(chunk_size);
458 if (blosc2_compress_ctx(array->sc->cctx, buffer_b, array->itemsize, chunk, chunk_size) < 0) {
459 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
460 }
461 if (blosc2_schunk_update_chunk(array->sc, 0, chunk, false) < 0) {
462 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
463 }
464
465 } else {
466 if (blosc2_schunk_decompress_chunk(array->sc, 0, buffer_b, array->itemsize) < 0) {
467 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
468 }
469 }
470 return CATERVA_SUCCEED;
471 }
472
473 int32_t data_nbytes = array->extchunknitems * array->itemsize;
474 uint8_t *data = malloc(data_nbytes);
475
476 int64_t chunks_in_array[CATERVA_MAX_DIM] = {0};
477 for (int i = 0; i < ndim; ++i) {
478 chunks_in_array[i] = array->extshape[i] / array->chunkshape[i];
479 }
480
481 int64_t chunks_in_array_strides[CATERVA_MAX_DIM];
482 chunks_in_array_strides[ndim - 1] = 1;
483 for (int i = ndim - 2; i >= 0; --i) {
484 chunks_in_array_strides[i] = chunks_in_array_strides[i + 1] * chunks_in_array[i + 1];
485 }
486
487 int64_t blocks_in_chunk[CATERVA_MAX_DIM] = {0};
488 for (int i = 0; i < ndim; ++i) {
489 blocks_in_chunk[i] = array->extchunkshape[i] / array->blockshape[i];
490 }
491
492 // Compute the number of chunks to update
493 int64_t update_start[CATERVA_MAX_DIM];
494 int64_t update_shape[CATERVA_MAX_DIM];
495
496 int64_t update_nchunks = 1;
497 for (int i = 0; i < ndim; ++i) {
498 int64_t pos = 0;
499 while (pos <= buffer_start[i]) {
500 pos += array->chunkshape[i];
501 }
502 update_start[i] = pos / array->chunkshape[i] - 1;
503 while (pos < buffer_stop[i]) {
504 pos += array->chunkshape[i];
505 }
506 update_shape[i] = pos / array->chunkshape[i] - update_start[i];
507 update_nchunks *= update_shape[i];
508 }
509
510 for (int update_nchunk = 0; update_nchunk < update_nchunks; ++update_nchunk) {
511 int64_t nchunk_ndim[CATERVA_MAX_DIM] = {0};
512 index_unidim_to_multidim(ndim, update_shape, update_nchunk, nchunk_ndim);
513 for (int i = 0; i < ndim; ++i) {
514 nchunk_ndim[i] += update_start[i];
515 }
516 int64_t nchunk;
517 index_multidim_to_unidim(nchunk_ndim, ndim, chunks_in_array_strides, &nchunk);
518
519 // check if the chunk needs to be updated
520 int64_t chunk_start[CATERVA_MAX_DIM] = {0};
521 int64_t chunk_stop[CATERVA_MAX_DIM] = {0};
522 for (int i = 0; i < ndim; ++i) {
523 chunk_start[i] = nchunk_ndim[i] * array->chunkshape[i];
524 chunk_stop[i] = chunk_start[i] + array->chunkshape[i];
525 if (chunk_stop[i] > array->shape[i]) {
526 chunk_stop[i] = array->shape[i];
527 }
528 }
529 bool chunk_empty = false;
530 for (int i = 0; i < ndim; ++i) {
531 chunk_empty |= (chunk_stop[i] <= buffer_start[i] || chunk_start[i] >= buffer_stop[i]);
532 }
533 if (chunk_empty) {
534 continue;
535 }
536
537 int64_t nblocks = array->extchunknitems / array->blocknitems;
538
539
540
541 if (set_slice) {
542 // Check if all the chunk is going to be updated and avoid the decompression
543 bool decompress_chunk = false;
544 for (int i = 0; i < ndim; ++i) {
545 decompress_chunk |= (chunk_start[i] < buffer_start[i] || chunk_stop[i] > buffer_stop[i]);
546 }
547
548 if (decompress_chunk) {
549 int err = blosc2_schunk_decompress_chunk(array->sc, nchunk, data, data_nbytes);
550 if (err < 0) {
551 CATERVA_TRACE_ERROR("Error decompressing chunk");
552 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
553 }
554 } else {
555 // memset(data, 0, data_nbytes);
556 }
557 } else {
558 bool *block_maskout = ctx->cfg->alloc(nblocks);
559 CATERVA_ERROR_NULL(block_maskout);
560 for (int nblock = 0; nblock < nblocks; ++nblock) {
561 int64_t nblock_ndim[CATERVA_MAX_DIM] = {0};
562 index_unidim_to_multidim(ndim, blocks_in_chunk, nblock, nblock_ndim);
563
564 // check if the block needs to be updated
565 int64_t block_start[CATERVA_MAX_DIM] = {0};
566 int64_t block_stop[CATERVA_MAX_DIM] = {0};
567 for (int i = 0; i < ndim; ++i) {
568 block_start[i] = nblock_ndim[i] * array->blockshape[i];
569 block_stop[i] = block_start[i] + array->blockshape[i];
570 block_start[i] += chunk_start[i];
571 block_stop[i] += chunk_start[i];
572
573 if (block_start[i] > chunk_stop[i]) {
574 block_start[i] = chunk_stop[i];
575 }
576 if (block_stop[i] > chunk_stop[i]) {
577 block_stop[i] = chunk_stop[i];
578 }
579 }
580
581 bool block_empty = false;
582 for (int i = 0; i < ndim; ++i) {
583 block_empty |= (block_stop[i] <= start[i] || block_start[i] >= stop[i]);
584 }
585 block_maskout[nblock] = block_empty ? true : false;
586 }
587
588 if (blosc2_set_maskout(array->sc->dctx, block_maskout, nblocks) != BLOSC2_ERROR_SUCCESS) {
589 CATERVA_TRACE_ERROR("Error setting the maskout");
590 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
591 }
592
593 int err = blosc2_schunk_decompress_chunk(array->sc, nchunk, data, data_nbytes);
594 if (err < 0) {
595 CATERVA_TRACE_ERROR("Error decompressing chunk");
596 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
597 }
598
599 ctx->cfg->free(block_maskout);
600 }
601
602 // Iterate over blocks
603
604 for (int nblock = 0; nblock < nblocks; ++nblock) {
605 int64_t nblock_ndim[CATERVA_MAX_DIM] = {0};
606 index_unidim_to_multidim(ndim, blocks_in_chunk, nblock, nblock_ndim);
607
608 // check if the block needs to be updated
609 int64_t block_start[CATERVA_MAX_DIM] = {0};
610 int64_t block_stop[CATERVA_MAX_DIM] = {0};
611 for (int i = 0; i < ndim; ++i) {
612 block_start[i] = nblock_ndim[i] * array->blockshape[i];
613 block_stop[i] = block_start[i] + array->blockshape[i];
614 block_start[i] += chunk_start[i];
615 block_stop[i] += chunk_start[i];
616
617 if (block_start[i] > chunk_stop[i]) {
618 block_start[i] = chunk_stop[i];
619 }
620 if (block_stop[i] > chunk_stop[i]) {
621 block_stop[i] = chunk_stop[i];
622 }
623 }
624 int64_t block_shape[CATERVA_MAX_DIM] = {0};
625 for (int i = 0; i < ndim; ++i) {
626 block_shape[i] = block_stop[i] - block_start[i];
627 }
628 bool block_empty = false;
629 for (int i = 0; i < ndim; ++i) {
630 block_empty |= (block_stop[i] <= start[i] || block_start[i] >= stop[i]);
631 }
632 if (block_empty) {
633 continue;
634 }
635
636 // compute the start of the slice inside the block
637 int64_t slice_start[CATERVA_MAX_DIM] = {0};
638 for (int i = 0; i < ndim; ++i) {
639 if (block_start[i] < buffer_start[i]) {
640 slice_start[i] = buffer_start[i] - block_start[i];
641 } else {
642 slice_start[i] = 0;
643 }
644 slice_start[i] += block_start[i];
645 }
646
647 int64_t slice_stop[CATERVA_MAX_DIM] = {0};
648 for (int i = 0; i < ndim; ++i) {
649 if (block_stop[i] > buffer_stop[i]) {
650 slice_stop[i] = block_shape[i] - (block_stop[i] - buffer_stop[i]);
651 } else {
652 slice_stop[i] = block_stop[i] - block_start[i];
653 }
654 slice_stop[i] += block_start[i];
655 }
656
657 int64_t slice_shape[CATERVA_MAX_DIM] = {0};
658 for (int i = 0; i < ndim; ++i) {
659 slice_shape[i] = slice_stop[i] - slice_start[i];
660 }
661
662
663 uint8_t *src = &buffer_b[0];
664 int64_t *src_pad_shape = buffer_shape;
665
666 int64_t src_start[CATERVA_MAX_DIM] = {0};
667 int64_t src_stop[CATERVA_MAX_DIM] = {0};
668 for (int i = 0; i < ndim; ++i) {
669 src_start[i] = slice_start[i] - buffer_start[i];
670 src_stop[i] = slice_stop[i] - buffer_start[i];
671 }
672
673 uint8_t *dst = &data[nblock * array->blocknitems * array->itemsize];
674 int64_t dst_pad_shape[CATERVA_MAX_DIM];
675 for (int i = 0; i < ndim; ++i) {
676 dst_pad_shape[i] = array->blockshape[i];
677 }
678
679 int64_t dst_start[CATERVA_MAX_DIM] = {0};
680 int64_t dst_stop[CATERVA_MAX_DIM] = {0};
681 for (int i = 0; i < ndim; ++i) {
682 dst_start[i] = slice_start[i] - block_start[i];
683 dst_stop[i] = dst_start[i] + slice_shape[i];
684 }
685
686 if (set_slice) {
687 caterva_copy_buffer(ndim, array->itemsize,
688 src, src_pad_shape, src_start, src_stop,
689 dst, dst_pad_shape, dst_start);
690 } else {
691 caterva_copy_buffer(ndim, array->itemsize,
692 dst, dst_pad_shape, dst_start, dst_stop,
693 src, src_pad_shape, src_start);
694 }
695 }
696
697 if (set_slice) {
698 // Recompress the data
699 int32_t chunk_nbytes = data_nbytes + BLOSC_MAX_OVERHEAD;
700 uint8_t *chunk = malloc(chunk_nbytes);
701 int brc;
702 brc = blosc2_compress_ctx(array->sc->cctx, data, data_nbytes, chunk, chunk_nbytes);
703 if (brc < 0) {
704 CATERVA_TRACE_ERROR("Blosc can not compress the data");
705 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
706 }
707 brc = blosc2_schunk_update_chunk(array->sc, nchunk, chunk, false);
708 if (brc < 0) {
709 CATERVA_TRACE_ERROR("Blosc can not update the chunk");
710 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
711 }
712 }
713 }
714
715 free(data);
716
717
718 return CATERVA_SUCCEED;
719 }
720
caterva_get_slice_buffer(caterva_ctx_t * ctx,caterva_array_t * array,int64_t * start,int64_t * stop,void * buffer,int64_t * buffershape,int64_t buffersize)721 int caterva_get_slice_buffer(caterva_ctx_t *ctx,
722 caterva_array_t *array,
723 int64_t *start, int64_t *stop,
724 void *buffer, int64_t *buffershape, int64_t buffersize) {
725 CATERVA_ERROR_NULL(ctx);
726 CATERVA_ERROR_NULL(array);
727 CATERVA_ERROR_NULL(start);
728 CATERVA_ERROR_NULL(stop);
729 CATERVA_ERROR_NULL(buffershape);
730 CATERVA_ERROR_NULL(buffer);
731
732 int64_t size = array->itemsize;
733 for (int i = 0; i < array->ndim; ++i) {
734 if (stop[i] - start[i] > buffershape[i]) {
735 CATERVA_TRACE_ERROR("The buffer shape can not be smaller than the slice shape");
736 return CATERVA_ERR_INVALID_ARGUMENT;
737 }
738 size *= buffershape[i];
739 }
740
741 if (array->nitems == 0) {
742 return CATERVA_SUCCEED;
743 }
744
745 if (buffersize < size) {
746 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
747 }
748 CATERVA_ERROR(caterva_blosc_slice(ctx, buffer, buffersize, start, stop, buffershape, array, false));
749
750 return CATERVA_SUCCEED;
751 }
752
caterva_set_slice_buffer(caterva_ctx_t * ctx,void * buffer,int64_t * buffershape,int64_t buffersize,int64_t * start,int64_t * stop,caterva_array_t * array)753 int caterva_set_slice_buffer(caterva_ctx_t *ctx,
754 void *buffer, int64_t *buffershape, int64_t buffersize,
755 int64_t *start, int64_t *stop,
756 caterva_array_t *array) {
757 CATERVA_ERROR_NULL(ctx);
758 CATERVA_ERROR_NULL(buffer);
759 CATERVA_ERROR_NULL(start);
760 CATERVA_ERROR_NULL(stop);
761 CATERVA_ERROR_NULL(array);
762
763 int64_t size = array->itemsize;
764 for (int i = 0; i < array->ndim; ++i) {
765 size *= stop[i] - start[i];
766 }
767
768 if (buffersize < size) {
769 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
770 }
771
772 if (array->nitems == 0) {
773 return CATERVA_SUCCEED;
774 }
775
776 CATERVA_ERROR(caterva_blosc_slice(ctx, buffer, buffersize, start, stop, buffershape, array, true));
777
778 return CATERVA_SUCCEED;
779 }
780
caterva_get_slice(caterva_ctx_t * ctx,caterva_array_t * src,int64_t * start,int64_t * stop,caterva_storage_t * storage,caterva_array_t ** array)781 int caterva_get_slice(caterva_ctx_t *ctx, caterva_array_t *src, int64_t *start,
782 int64_t *stop, caterva_storage_t *storage, caterva_array_t **array) {
783 CATERVA_ERROR_NULL(ctx);
784 CATERVA_ERROR_NULL(storage);
785 CATERVA_ERROR_NULL(src);
786 CATERVA_ERROR_NULL(start);
787 CATERVA_ERROR_NULL(stop);
788 CATERVA_ERROR_NULL(array);
789
790 caterva_params_t params;
791 params.ndim = src->ndim;
792 params.itemsize = src->itemsize;
793 for (int i = 0; i < src->ndim; ++i) {
794 params.shape[i] = stop[i] - start[i];
795 }
796
797 // Add data
798 CATERVA_ERROR(caterva_empty(ctx, ¶ms, storage, array));
799
800 if ((*array)->nitems == 0) {
801 return CATERVA_SUCCEED;
802 }
803
804 uint8_t ndim = (*array)->ndim;
805 int64_t chunks_in_array[CATERVA_MAX_DIM] = {0};
806 for (int i = 0; i < ndim; ++i) {
807 chunks_in_array[i] = (*array)->extshape[i] / (*array)->chunkshape[i];
808 }
809 int64_t nchunks = (*array)->sc->nchunks;
810 for (int nchunk = 0; nchunk < nchunks; ++nchunk) {
811 int64_t nchunk_ndim[CATERVA_MAX_DIM] = {0};
812 index_unidim_to_multidim(ndim, chunks_in_array, nchunk, nchunk_ndim);
813
814 // check if the chunk needs to be updated
815 int64_t chunk_start[CATERVA_MAX_DIM] = {0};
816 int64_t chunk_stop[CATERVA_MAX_DIM] = {0};
817 int64_t chunk_shape[CATERVA_MAX_DIM] = {0};
818 for (int i = 0; i < ndim; ++i) {
819 chunk_start[i] = nchunk_ndim[i] * (*array)->chunkshape[i];
820 chunk_stop[i] = chunk_start[i] + (*array)->chunkshape[i];
821 if (chunk_stop[i] > (*array)->shape[i]) {
822 chunk_stop[i] = (*array)->shape[i];
823 }
824 chunk_shape[i] = chunk_stop[i] - chunk_start[i];
825 }
826
827 int64_t src_start[CATERVA_MAX_DIM] = {0};
828 int64_t src_stop[CATERVA_MAX_DIM] = {0};
829 for (int i = 0; i < ndim; ++i) {
830 src_start[i] = chunk_start[i] + start[i];
831 src_stop[i] = chunk_stop[i] + start[i];
832 }
833 int64_t buffersize = params.itemsize;
834 for (int i = 0; i < ndim; ++i) {
835 buffersize *= chunk_shape[i];
836 }
837 uint8_t *buffer = ctx->cfg->alloc(buffersize);
838 CATERVA_ERROR(caterva_get_slice_buffer(ctx, src, src_start, src_stop, buffer, chunk_shape,
839 buffersize));
840 CATERVA_ERROR(caterva_set_slice_buffer(ctx, buffer, chunk_shape, buffersize, chunk_start,
841 chunk_stop, *array));
842 ctx->cfg->free(buffer);
843 }
844
845 return CATERVA_SUCCEED;
846 }
847
caterva_squeeze(caterva_ctx_t * ctx,caterva_array_t * array)848 int caterva_squeeze(caterva_ctx_t *ctx, caterva_array_t *array) {
849 CATERVA_ERROR_NULL(ctx);
850 CATERVA_ERROR_NULL(array);
851
852 bool index[CATERVA_MAX_DIM];
853
854 for (int i = 0; i < array->ndim; ++i) {
855 if (array->shape[i] != 1) {
856 index[i] = false;
857 } else {
858 index[i] = true;
859 }
860 }
861 CATERVA_ERROR(caterva_squeeze_index(ctx, array, index));
862
863 return CATERVA_SUCCEED;
864 }
865
caterva_squeeze_index(caterva_ctx_t * ctx,caterva_array_t * array,bool * index)866 int caterva_squeeze_index(caterva_ctx_t *ctx, caterva_array_t *array, bool *index) {
867 CATERVA_ERROR_NULL(ctx);
868 CATERVA_ERROR_NULL(array);
869
870 uint8_t nones = 0;
871 int64_t newshape[CATERVA_MAX_DIM];
872 int32_t newchunkshape[CATERVA_MAX_DIM];
873 int32_t newblockshape[CATERVA_MAX_DIM];
874
875 for (int i = 0; i < array->ndim; ++i) {
876 if (index[i] == true) {
877 if (array->shape[i] != 1) {
878 CATERVA_ERROR(CATERVA_ERR_INVALID_INDEX);
879 }
880 } else {
881 newshape[nones] = array->shape[i];
882 newchunkshape[nones] = array->chunkshape[i];
883 newblockshape[nones] = array->blockshape[i];
884 nones += 1;
885 }
886 }
887
888 for (int i = 0; i < CATERVA_MAX_DIM; ++i) {
889 if (i < nones) {
890 array->chunkshape[i] = newchunkshape[i];
891 array->blockshape[i] = newblockshape[i];
892 } else {
893 array->chunkshape[i] = 1;
894 array->blockshape[i] = 1;
895 }
896 }
897
898 CATERVA_ERROR(caterva_update_shape(array, nones, newshape, newchunkshape, newblockshape));
899
900 return CATERVA_SUCCEED;
901 }
902
caterva_copy(caterva_ctx_t * ctx,caterva_array_t * src,caterva_storage_t * storage,caterva_array_t ** array)903 int caterva_copy(caterva_ctx_t *ctx, caterva_array_t *src, caterva_storage_t *storage,
904 caterva_array_t **array) {
905 CATERVA_ERROR_NULL(ctx);
906 CATERVA_ERROR_NULL(src);
907 CATERVA_ERROR_NULL(storage);
908 CATERVA_ERROR_NULL(array);
909
910
911 caterva_params_t params;
912 params.itemsize = src->itemsize;
913 params.ndim = src->ndim;
914 for (int i = 0; i < src->ndim; ++i) {
915 params.shape[i] = src->shape[i];
916 }
917
918 bool equals = true;
919 for (int i = 0; i < src->ndim; ++i) {
920 if (src->chunkshape[i] != storage->chunkshape[i]) {
921 equals = false;
922 break;
923 }
924 if (src->blockshape[i] != storage->blockshape[i]) {
925 equals = false;
926 break;
927 }
928 }
929
930 if (equals) {
931 CATERVA_ERROR(caterva_array_without_schunk(ctx, ¶ms, storage, array));
932 blosc2_storage b_storage;
933 blosc2_cparams cparams;
934 blosc2_dparams dparams;
935 CATERVA_ERROR(
936 create_blosc_params(ctx, ¶ms, storage, &cparams, &dparams, &b_storage));
937 blosc2_schunk *new_sc = blosc2_schunk_copy(src->sc, &b_storage);
938
939 if (new_sc == NULL) {
940 return CATERVA_ERR_BLOSC_FAILED;
941 }
942 (*array)->sc = new_sc;
943
944 } else {
945 int64_t start[CATERVA_MAX_DIM] = {0, 0, 0, 0, 0, 0, 0, 0};
946
947 int64_t stop[CATERVA_MAX_DIM];
948 for (int i = 0; i < src->ndim; ++i) {
949 stop[i] = src->shape[i];
950 }
951 // Copy metalayers
952 caterva_storage_t storage_meta;
953 memcpy(&storage_meta, storage, sizeof(storage_meta));
954 int j = 0;
955
956 for (int i = 0; i < src->sc->nmetalayers; ++i) {
957 if (strcmp(src->sc->metalayers[i]->name, "caterva") == 0) {
958 continue;
959 }
960 caterva_metalayer_t *meta = &storage_meta.metalayers[j];
961 meta->name = src->sc->metalayers[i]->name;
962 meta->sdata = src->sc->metalayers[i]->content;
963 meta->size = src->sc->metalayers[i]->content_len;
964 j++;
965 }
966 storage_meta.nmetalayers = j;
967
968 // Copy data
969 CATERVA_ERROR(caterva_get_slice(ctx, src, start, stop, &storage_meta, array));
970
971 // Copy vlmetayers
972 for (int i = 0; i < src->sc->nvlmetalayers; ++i) {
973 uint8_t *content;
974 uint32_t content_len;
975 if (blosc2_vlmeta_get(src->sc, src->sc->vlmetalayers[i]->name, &content,
976 &content_len) < 0) {
977 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
978 }
979 caterva_metalayer_t vlmeta;
980 vlmeta.name = src->sc->vlmetalayers[i]->name;
981 vlmeta.sdata = content;
982 vlmeta.size = (int32_t) content_len;
983 CATERVA_ERROR(caterva_vlmeta_add(ctx, *array, &vlmeta));
984 free(content);
985 }
986
987 }
988 return CATERVA_SUCCEED;
989 }
990
caterva_save(caterva_ctx_t * ctx,caterva_array_t * array,char * urlpath)991 int caterva_save(caterva_ctx_t *ctx, caterva_array_t *array, char *urlpath) {
992 CATERVA_ERROR_NULL(ctx);
993 CATERVA_ERROR_NULL(array);
994 CATERVA_ERROR_NULL(urlpath);
995
996 caterva_array_t *tmp;
997 caterva_storage_t storage;
998 storage.urlpath = urlpath;
999 storage.sequencial = array->sc->storage->contiguous;
1000
1001 for (int i = 0; i < array->ndim; ++i) {
1002 storage.chunkshape[i] = array->chunkshape[i];
1003 storage.blockshape[i] = array->blockshape[i];
1004 }
1005
1006 caterva_copy(ctx, array, &storage, &tmp);
1007 caterva_free(ctx, &tmp);
1008
1009 return CATERVA_SUCCEED;
1010 }
1011
caterva_remove(caterva_ctx_t * ctx,char * urlpath)1012 int caterva_remove(caterva_ctx_t *ctx, char *urlpath) {
1013 CATERVA_ERROR_NULL(ctx);
1014 CATERVA_ERROR_NULL(urlpath);
1015
1016 int rc = blosc2_remove_urlpath(urlpath);
1017 if (rc != BLOSC2_ERROR_SUCCESS) {
1018 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1019 }
1020 return CATERVA_SUCCEED;
1021 }
1022
1023
caterva_vlmeta_add(caterva_ctx_t * ctx,caterva_array_t * array,caterva_metalayer_t * vlmeta)1024 int caterva_vlmeta_add(caterva_ctx_t *ctx, caterva_array_t *array, caterva_metalayer_t *vlmeta) {
1025 CATERVA_ERROR_NULL(ctx);
1026 CATERVA_ERROR_NULL(array);
1027 CATERVA_ERROR_NULL(vlmeta);
1028 CATERVA_ERROR_NULL(vlmeta->name);
1029 CATERVA_ERROR_NULL(vlmeta->sdata);
1030 if (vlmeta->size < 0) {
1031 CATERVA_TRACE_ERROR("metalayer size must be hgreater than 0");
1032 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
1033 }
1034 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
1035 if (blosc2_vlmeta_add(array->sc, vlmeta->name, vlmeta->sdata, vlmeta->size, &cparams) < 0) {
1036 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1037 }
1038
1039 return CATERVA_SUCCEED;
1040 }
1041
1042
caterva_vlmeta_get(caterva_ctx_t * ctx,caterva_array_t * array,const char * name,caterva_metalayer_t * vlmeta)1043 int caterva_vlmeta_get(caterva_ctx_t *ctx, caterva_array_t *array,
1044 const char *name, caterva_metalayer_t *vlmeta) {
1045 CATERVA_ERROR_NULL(ctx);
1046 CATERVA_ERROR_NULL(array);
1047 CATERVA_ERROR_NULL(name);
1048 CATERVA_ERROR_NULL(vlmeta);
1049
1050 if (blosc2_vlmeta_get(array->sc, name, &vlmeta->sdata, &vlmeta->size) < 0) {
1051 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1052 }
1053 vlmeta->name = strdup(name);
1054
1055 return CATERVA_SUCCEED;
1056 }
1057
caterva_vlmeta_exists(caterva_ctx_t * ctx,caterva_array_t * array,const char * name,bool * exists)1058 int caterva_vlmeta_exists(caterva_ctx_t *ctx, caterva_array_t *array,
1059 const char *name, bool *exists) {
1060 CATERVA_ERROR_NULL(ctx);
1061 CATERVA_ERROR_NULL(array);
1062 CATERVA_ERROR_NULL(name);
1063 CATERVA_ERROR_NULL(exists);
1064
1065 if (blosc2_vlmeta_exists(array->sc, name) < 0) {
1066 *exists = false;
1067 } else {
1068 *exists = true;
1069 }
1070
1071 return CATERVA_SUCCEED;
1072 }
1073
1074
caterva_vlmeta_update(caterva_ctx_t * ctx,caterva_array_t * array,caterva_metalayer_t * vlmeta)1075 int caterva_vlmeta_update(caterva_ctx_t *ctx, caterva_array_t *array,
1076 caterva_metalayer_t *vlmeta) {
1077 CATERVA_ERROR_NULL(ctx);
1078 CATERVA_ERROR_NULL(array);
1079 CATERVA_ERROR_NULL(vlmeta);
1080 CATERVA_ERROR_NULL(vlmeta->name);
1081 CATERVA_ERROR_NULL(vlmeta->sdata);
1082 if (vlmeta->size < 0) {
1083 CATERVA_TRACE_ERROR("metalayer size must be hgreater than 0");
1084 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
1085 }
1086
1087 blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
1088 if (blosc2_vlmeta_update(array->sc, vlmeta->name, vlmeta->sdata, vlmeta->size, &cparams) < 0) {
1089 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1090 }
1091
1092 return CATERVA_SUCCEED;
1093 }
1094
caterva_meta_get(caterva_ctx_t * ctx,caterva_array_t * array,const char * name,caterva_metalayer_t * meta)1095 int caterva_meta_get(caterva_ctx_t *ctx, caterva_array_t *array,
1096 const char *name, caterva_metalayer_t *meta) {
1097 CATERVA_ERROR_NULL(ctx);
1098 CATERVA_ERROR_NULL(array);
1099 CATERVA_ERROR_NULL(name);
1100 CATERVA_ERROR_NULL(meta);
1101
1102 if (blosc2_meta_get(array->sc, name, &meta->sdata, &meta->size) < 0) {
1103 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1104 }
1105 meta->name = strdup(name);
1106 return CATERVA_SUCCEED;
1107 }
1108
caterva_meta_exists(caterva_ctx_t * ctx,caterva_array_t * array,const char * name,bool * exists)1109 int caterva_meta_exists(caterva_ctx_t *ctx, caterva_array_t *array,
1110 const char *name, bool *exists) {
1111 CATERVA_ERROR_NULL(ctx);
1112 CATERVA_ERROR_NULL(array);
1113 CATERVA_ERROR_NULL(name);
1114 CATERVA_ERROR_NULL(exists);
1115
1116 if (blosc2_meta_exists(array->sc, name) < 0) {
1117 *exists = false;
1118 } else {
1119 *exists = true;
1120 }
1121 return CATERVA_SUCCEED;
1122 }
1123
1124
caterva_meta_update(caterva_ctx_t * ctx,caterva_array_t * array,caterva_metalayer_t * meta)1125 int caterva_meta_update(caterva_ctx_t *ctx, caterva_array_t *array,
1126 caterva_metalayer_t *meta) {
1127 CATERVA_ERROR_NULL(ctx);
1128 CATERVA_ERROR_NULL(array);
1129 CATERVA_ERROR_NULL(meta);
1130 CATERVA_ERROR_NULL(meta->name);
1131 CATERVA_ERROR_NULL(meta->sdata);
1132 if (meta->size < 0) {
1133 CATERVA_TRACE_ERROR("metalayer size must be hgreater than 0");
1134 CATERVA_ERROR(CATERVA_ERR_INVALID_ARGUMENT);
1135 }
1136
1137 if (blosc2_meta_update(array->sc, meta->name, meta->sdata, meta->size) < 0) {
1138 CATERVA_ERROR(CATERVA_ERR_BLOSC_FAILED);
1139 }
1140 return CATERVA_SUCCEED;
1141 }
1142