Skip to content

Commit 3122c09

Browse files
committed
Set cframe variable-chunk flag and test fixed-size chunks
1 parent 25197eb commit 3122c09

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

blosc/frame.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ void *new_header_frame(blosc2_schunk *schunk, blosc2_frame_s *frame) {
115115
// General flags
116116
*h2p = BLOSC2_VERSION_FRAME_FORMAT; // version
117117
*h2p += 0x10; // 64-bit offsets. We only support this for now.
118+
if (schunk->chunksize == 0) {
119+
*h2p |= FRAME_VARIABLE_CHUNKS;
120+
}
118121
h2p += 1;
119122
if (h2p - h2 >= FRAME_HEADER_MINLEN) {
120123
return NULL;
@@ -1098,6 +1101,12 @@ int64_t frame_from_schunk(blosc2_schunk *schunk, blosc2_frame_s *frame) {
10981101

10991102
// Now that we know them, fill the chunksize and frame length in header
11001103
to_big(h2 + FRAME_CHUNKSIZE, &chunksize, sizeof(chunksize));
1104+
if (chunksize == 0) {
1105+
h2[FRAME_FLAGS] |= FRAME_VARIABLE_CHUNKS;
1106+
}
1107+
else {
1108+
h2[FRAME_FLAGS] &= (uint8_t)~FRAME_VARIABLE_CHUNKS;
1109+
}
11011110
frame->len = h2len + cbytes + off_cbytes + FRAME_TRAILER_MINLEN;
11021111
if (frame->sframe) {
11031112
frame->len = h2len + off_cbytes + FRAME_TRAILER_MINLEN;

blosc/frame.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323

2424
// Constants for metadata placement in header
25+
#define FRAME_VARIABLE_CHUNKS (1U << 6)
26+
2527
#define FRAME_HEADER_MAGIC 2
2628
#define FRAME_HEADER_LEN (FRAME_HEADER_MAGIC + 8 + 1) // 11
2729
#define FRAME_LEN (FRAME_HEADER_LEN + 4 + 1) // 16

tests/test_variable_chunks.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <stdio.h>
88
#include <string.h>
99

10+
#include "frame.h"
1011
#include "test_common.h"
1112

1213
int tests_run = 0;
@@ -36,6 +37,12 @@ static const char *updated_values[] = {
3637
"tiny",
3738
};
3839

40+
static const char *fixed_values[] = {
41+
"one",
42+
"two",
43+
"six",
44+
};
45+
3946
static int append_string_chunk(blosc2_schunk *schunk, const char *value) {
4047
int32_t nbytes = (int32_t)strlen(value) + 1;
4148
uint8_t *chunk = malloc((size_t)nbytes + BLOSC2_MAX_OVERHEAD);
@@ -72,6 +79,21 @@ static int assert_values(blosc2_schunk *schunk, const char *expected[], int nite
7279
return 0;
7380
}
7481

82+
static int assert_variable_chunk_flag(blosc2_schunk *schunk, bool expected) {
83+
uint8_t *cframe = NULL;
84+
bool needs_free = false;
85+
int64_t cframe_len = blosc2_schunk_to_buffer(schunk, &cframe, &needs_free);
86+
if (cframe_len < FRAME_HEADER_MINLEN || cframe == NULL) {
87+
return -1;
88+
}
89+
90+
bool actual = (cframe[FRAME_FLAGS] & FRAME_VARIABLE_CHUNKS) != 0;
91+
if (needs_free) {
92+
free(cframe);
93+
}
94+
return actual == expected ? 0 : -2;
95+
}
96+
7597
static char *test_variable_chunks(void) {
7698
blosc2_remove_urlpath(tdata.urlpath);
7799

@@ -94,6 +116,8 @@ static char *test_variable_chunks(void) {
94116
}
95117

96118
mu_assert("ERROR: schunk should switch to variable chunksize mode", schunk->chunksize == 0);
119+
mu_assert("ERROR: frame should signal variable chunk sizes",
120+
assert_variable_chunk_flag(schunk, true) == 0);
97121
mu_assert("ERROR: chunk cannot be decompressed", assert_values(schunk, values, 3) == 0);
98122

99123
for (int i = 1; i < 3; ++i) {
@@ -102,6 +126,8 @@ static char *test_variable_chunks(void) {
102126
}
103127

104128
mu_assert("ERROR: schunk should keep variable chunksize mode", schunk->chunksize == 0);
129+
mu_assert("ERROR: updated frame should still signal variable chunk sizes",
130+
assert_variable_chunk_flag(schunk, true) == 0);
105131
mu_assert("ERROR: updated chunk cannot be decompressed", assert_values(schunk, updated_values, 3) == 0);
106132

107133
blosc2_schunk_free(schunk);
@@ -111,6 +137,8 @@ static char *test_variable_chunks(void) {
111137
mu_assert("ERROR: reopened schunk is NULL", reopened != NULL);
112138
mu_assert("ERROR: reopened schunk should keep variable chunksize mode", reopened->chunksize == 0);
113139
mu_assert("ERROR: reopened schunk nchunks mismatch", reopened->nchunks == 3);
140+
mu_assert("ERROR: reopened frame should signal variable chunk sizes",
141+
assert_variable_chunk_flag(reopened, true) == 0);
114142
mu_assert("ERROR: reopened chunk cannot be decompressed", assert_values(reopened, updated_values, 3) == 0);
115143
blosc2_schunk_free(reopened);
116144
}
@@ -119,10 +147,53 @@ static char *test_variable_chunks(void) {
119147
return EXIT_SUCCESS;
120148
}
121149

150+
static char *test_fixed_chunks_flag(void) {
151+
blosc2_remove_urlpath(tdata.urlpath);
152+
153+
blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
154+
cparams.typesize = 1;
155+
blosc2_dparams dparams = BLOSC2_DPARAMS_DEFAULTS;
156+
blosc2_storage storage = {
157+
.contiguous = tdata.contiguous,
158+
.urlpath = (char *)tdata.urlpath,
159+
.cparams = &cparams,
160+
.dparams = &dparams,
161+
};
162+
163+
blosc2_schunk *schunk = blosc2_schunk_new(&storage);
164+
mu_assert("ERROR: cannot create schunk", schunk != NULL);
165+
166+
for (int i = 0; i < 3; ++i) {
167+
int nchunks = append_string_chunk(schunk, fixed_values[i]);
168+
mu_assert("ERROR: fixed chunk cannot be appended", nchunks == i + 1);
169+
}
170+
171+
mu_assert("ERROR: schunk should keep a fixed chunksize", schunk->chunksize == 4);
172+
mu_assert("ERROR: frame should not signal variable chunk sizes",
173+
assert_variable_chunk_flag(schunk, false) == 0);
174+
mu_assert("ERROR: fixed chunk cannot be decompressed", assert_values(schunk, fixed_values, 3) == 0);
175+
176+
blosc2_schunk_free(schunk);
177+
178+
if (tdata.urlpath != NULL) {
179+
blosc2_schunk *reopened = blosc2_schunk_open(tdata.urlpath);
180+
mu_assert("ERROR: reopened schunk is NULL", reopened != NULL);
181+
mu_assert("ERROR: reopened schunk should keep a fixed chunksize", reopened->chunksize == 4);
182+
mu_assert("ERROR: reopened frame should not signal variable chunk sizes",
183+
assert_variable_chunk_flag(reopened, false) == 0);
184+
mu_assert("ERROR: reopened fixed chunk cannot be decompressed", assert_values(reopened, fixed_values, 3) == 0);
185+
blosc2_schunk_free(reopened);
186+
}
187+
188+
blosc2_remove_urlpath(tdata.urlpath);
189+
return EXIT_SUCCESS;
190+
}
191+
122192
static char *all_tests(void) {
123193
for (int i = 0; i < (int)ARRAY_SIZE(backends); ++i) {
124194
tdata = backends[i];
125195
mu_run_test(test_variable_chunks);
196+
mu_run_test(test_fixed_chunks_flag);
126197
}
127198
return EXIT_SUCCESS;
128199
}

0 commit comments

Comments
 (0)