/src/c-blosc2/blosc/sframe.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************* |
2 | | Blosc - Blocked Shuffling and Compression Library |
3 | | |
4 | | Copyright (c) 2021 Blosc Development Team <blosc@blosc.org> |
5 | | https://blosc.org |
6 | | License: BSD 3-Clause (see LICENSE.txt) |
7 | | |
8 | | See LICENSE.txt for details about copyright and rights to use. |
9 | | **********************************************************************/ |
10 | | |
11 | | #include "frame.h" |
12 | | #include "blosc2.h" |
13 | | |
14 | | #include <stdio.h> |
15 | | #include <stdint.h> |
16 | | #include <stdlib.h> |
17 | | #include <string.h> |
18 | | |
19 | | |
20 | | /* If C11 is supported, use it's built-in aligned allocation. */ |
21 | | #if __STDC_VERSION__ >= 201112L |
22 | | #include <stdalign.h> |
23 | | #endif |
24 | | |
25 | | |
26 | | /* Open sparse frame index chunk */ |
27 | 0 | void* sframe_open_index(const char* urlpath, const char* mode, const blosc2_io *io) { |
28 | 0 | void* fp = NULL; |
29 | 0 | char* index_path = malloc(strlen(urlpath) + strlen("/chunks.b2frame") + 1); |
30 | 0 | if (index_path) { |
31 | 0 | sprintf(index_path, "%s/chunks.b2frame", urlpath); |
32 | 0 | blosc2_io_cb *io_cb = blosc2_get_io_cb(io->id); |
33 | 0 | if (io_cb == NULL) { |
34 | 0 | BLOSC_TRACE_ERROR("Error getting the input/output API"); |
35 | 0 | return NULL; |
36 | 0 | } |
37 | 0 | fp = io_cb->open(index_path, mode, io->params); |
38 | 0 | if (fp == NULL) |
39 | 0 | BLOSC_TRACE_ERROR("Error creating index path in: %s", index_path); |
40 | 0 | free(index_path); |
41 | 0 | } |
42 | 0 | return fp; |
43 | 0 | } |
44 | | |
45 | | /* Open directory/nchunk.chunk with 8 zeros of padding */ |
46 | 0 | void* sframe_open_chunk(const char* urlpath, int64_t nchunk, const char* mode, const blosc2_io *io) { |
47 | 0 | void* fp = NULL; |
48 | 0 | char* chunk_path = malloc(strlen(urlpath) + 1 + 8 + strlen(".chunk") + 1); |
49 | 0 | if (chunk_path) { |
50 | 0 | sprintf(chunk_path, "%s/%08X.chunk", urlpath, (unsigned int)nchunk); |
51 | 0 | blosc2_io_cb *io_cb = blosc2_get_io_cb(io->id); |
52 | 0 | if (io_cb == NULL) { |
53 | 0 | BLOSC_TRACE_ERROR("Error getting the input/output API"); |
54 | 0 | return NULL; |
55 | 0 | } |
56 | 0 | fp = io_cb->open(chunk_path, mode, io->params); |
57 | 0 | if (fp == NULL) |
58 | 0 | BLOSC_TRACE_ERROR("Error opening chunk path in: %s", chunk_path); |
59 | 0 | free(chunk_path); |
60 | 0 | } |
61 | 0 | return fp; |
62 | 0 | } |
63 | | |
64 | | /* Append an existing chunk into a sparse frame. */ |
65 | 0 | void* sframe_create_chunk(blosc2_frame_s* frame, uint8_t* chunk, int64_t nchunk, int64_t cbytes) { |
66 | 0 | void* fpc = sframe_open_chunk(frame->urlpath, nchunk, "wb", frame->schunk->storage->io); |
67 | 0 | if (fpc == NULL) { |
68 | 0 | BLOSC_TRACE_ERROR("Cannot open the chunkfile."); |
69 | 0 | return NULL; |
70 | 0 | } |
71 | 0 | blosc2_io_cb *io_cb = blosc2_get_io_cb(frame->schunk->storage->io->id); |
72 | 0 | if (io_cb == NULL) { |
73 | 0 | BLOSC_TRACE_ERROR("Error getting the input/output API"); |
74 | 0 | return NULL; |
75 | 0 | } |
76 | 0 | int64_t io_pos = 0; |
77 | 0 | int64_t wbytes = io_cb->write(chunk, 1, cbytes, io_pos, fpc); |
78 | 0 | io_cb->close(fpc); |
79 | 0 | if (wbytes != cbytes) { |
80 | 0 | BLOSC_TRACE_ERROR("Cannot write the full chunk."); |
81 | 0 | return NULL; |
82 | 0 | } |
83 | | |
84 | 0 | return frame; |
85 | 0 | } |
86 | | |
87 | | /* Append an existing chunk into a sparse frame. */ |
88 | 0 | int sframe_delete_chunk(const char *urlpath, int64_t nchunk) { |
89 | 0 | char* chunk_path = malloc(strlen(urlpath) + 1 + 8 + strlen(".chunk") + 1); |
90 | 0 | if (chunk_path) { |
91 | 0 | sprintf(chunk_path, "%s/%08X.chunk", urlpath, (unsigned int)nchunk); |
92 | 0 | int rc = remove(chunk_path); |
93 | 0 | free(chunk_path); |
94 | 0 | return rc; |
95 | 0 | } |
96 | 0 | return BLOSC2_ERROR_FILE_REMOVE; |
97 | 0 | } |
98 | | |
99 | | /* Get chunk from sparse frame. */ |
100 | 0 | int32_t sframe_get_chunk(blosc2_frame_s* frame, int64_t nchunk, uint8_t** chunk, bool* needs_free){ |
101 | 0 | void *fpc = sframe_open_chunk(frame->urlpath, nchunk, "rb", frame->schunk->storage->io); |
102 | 0 | if(fpc == NULL){ |
103 | 0 | BLOSC_TRACE_ERROR("Cannot open the chunkfile."); |
104 | 0 | return BLOSC2_ERROR_FILE_OPEN; |
105 | 0 | } |
106 | | |
107 | 0 | blosc2_io_cb *io_cb = blosc2_get_io_cb(frame->schunk->storage->io->id); |
108 | 0 | if (io_cb == NULL) { |
109 | 0 | BLOSC_TRACE_ERROR("Error getting the input/output API"); |
110 | 0 | return BLOSC2_ERROR_PLUGIN_IO; |
111 | 0 | } |
112 | | |
113 | 0 | int64_t chunk_cbytes = io_cb->size(fpc); |
114 | |
|
115 | 0 | if (io_cb->is_allocation_necessary) { |
116 | 0 | *chunk = malloc((size_t)chunk_cbytes); |
117 | 0 | *needs_free = true; |
118 | 0 | } |
119 | 0 | else { |
120 | 0 | *needs_free = false; |
121 | 0 | } |
122 | |
|
123 | 0 | int64_t io_pos = 0; |
124 | 0 | int64_t rbytes = io_cb->read((void**)chunk, 1, chunk_cbytes, io_pos, fpc); |
125 | 0 | io_cb->close(fpc); |
126 | 0 | if (rbytes != chunk_cbytes) { |
127 | 0 | BLOSC_TRACE_ERROR("Cannot read the chunk out of the chunkfile."); |
128 | 0 | return BLOSC2_ERROR_FILE_READ; |
129 | 0 | } |
130 | | |
131 | 0 | return (int32_t)chunk_cbytes; |
132 | 0 | } |