add byte-wise i/o to tags open in sequential write-only mode

This commit is contained in:
2025-02-24 15:54:52 +00:00
parent 43f6ad2c8f
commit 10e031ba9e
2 changed files with 107 additions and 6 deletions

View File

@@ -8,6 +8,8 @@
#include <stdlib.h>
#include <string.h>
static enum ec3_status flush_seq_buffer(struct ec3_tag_ioctx *tag);
static enum ec3_status init_seq_write_temp_files(struct ec3_tag_ioctx *tag)
{
b_status status = b_file_open_temp(
@@ -78,6 +80,17 @@ enum ec3_status ec3_tag_ioctx_create(
enum ec3_status ec3_tag_ioctx_close(struct ec3_tag_ioctx *tag)
{
enum ec3_status status = EC3_SUCCESS;
if ((tag->io_mode & (EC3_TAG_IO_SEQUENTIAL))
&& tag->io_seq_data_ptr > 0) {
status = flush_seq_buffer(tag);
}
if (status != EC3_SUCCESS) {
return status;
}
enum ec3_tag_ioctx_mode mode = tag->io_mode;
tag->io_mode |= EC3_TAG_IO_CLOSED;
@@ -146,6 +159,12 @@ enum ec3_status ec3_tag_ioctx_read_cluster(
cluster_id,
&physical_cluster_id);
if (status == EC3_ERR_OUT_OF_BOUNDS) {
/* reached the end of the tag data */
*nr_read = 0;
return EC3_SUCCESS;
}
if (status != EC3_SUCCESS) {
return status;
}
@@ -166,7 +185,8 @@ enum ec3_status ec3_tag_ioctx_read_cluster(
return EC3_ERR_BAD_FORMAT;
}
size_t offset = tag->io_cluster_data_offset + cluster_info.c_base;
size_t offset = tag->io_parent->io_header.img_cluster_data_offset
+ cluster_info.c_base;
size_t r;
enum b_status status2 = b_file_read(
tag->io_f_image,
@@ -198,7 +218,7 @@ enum ec3_status ec3_tag_ioctx_read_cluster(
enum ec3_status ec3_tag_ioctx_write_cluster(
struct ec3_tag_ioctx *tag,
size_t cluster_id,
void *buf,
const void *buf,
size_t len,
size_t *nr_written)
{
@@ -210,7 +230,7 @@ enum ec3_status ec3_tag_ioctx_write_cluster(
if (!(tag->io_mode & EC3_TAG_IO_SEQUENTIAL)) {
status = cluster_cache_put(
tag->io_cluster_buf,
&tag->io_cache,
cluster_id,
buf,
len);
@@ -264,6 +284,79 @@ enum ec3_status ec3_tag_ioctx_write_cluster(
return EC3_SUCCESS;
}
static enum ec3_status flush_seq_buffer(struct ec3_tag_ioctx *tag)
{
size_t nr_written = 0;
enum ec3_status status = ec3_tag_ioctx_write_cluster(
tag,
tag->io_seq_cluster_id,
tag->io_cluster_buf,
tag->io_seq_data_ptr,
&nr_written);
if (status != EC3_SUCCESS) {
return status;
}
tag->io_seq_data_ptr = 0;
return status;
}
enum ec3_status ec3_tag_ioctx_write(
struct ec3_tag_ioctx *tag,
const void *p,
size_t len,
size_t *nr_written)
{
if (!(tag->io_mode & EC3_TAG_IO_WRITE)) {
return EC3_ERR_NOT_SUPPORTED;
}
if (!(tag->io_mode & EC3_TAG_IO_SEQUENTIAL)) {
return EC3_ERR_NOT_SUPPORTED;
}
enum ec3_status status = EC3_SUCCESS;
size_t cluster_size = tag->io_parent->io_header.img_cluster_size;
const unsigned char *buf = p;
size_t written = 0;
while (len > 0) {
size_t space_remaining = cluster_size - tag->io_seq_data_ptr;
size_t to_copy = len;
if (to_copy > space_remaining) {
to_copy = space_remaining;
}
const unsigned char *src = buf + written;
unsigned char *dest
= tag->io_cluster_buf + tag->io_seq_data_ptr;
memcpy(dest, src, to_copy);
tag->io_seq_data_ptr += to_copy;
written += to_copy;
len -= to_copy;
space_remaining -= to_copy;
if (space_remaining == 0) {
status = flush_seq_buffer(tag);
}
if (status != EC3_SUCCESS) {
return status;
}
}
*nr_written = written;
return EC3_SUCCESS;
}
enum ec3_status ec3_tag_ioctx_get_nr_clusters(
struct ec3_tag_ioctx *tag,
size_t *out_nr_clusters)

View File

@@ -36,8 +36,6 @@ struct ec3_tag_ioctx {
/* temp buffer of cluster size, used for pipeline operations */
void *io_cluster_buf;
/* the offset to the start of the cluster table in io_f_rotag */
size_t io_cluster_data_offset;
/* this points to memory belonging to ec3_image_ioctx */
struct ec3_tag_info io_tag_info;
@@ -82,6 +80,10 @@ struct ec3_tag_ioctx {
struct cluster_table io_cluster_table;
/* how many clusters have been written sequentially to this tag */
size_t io_seq_cluster_id;
/* how many bytes have been written to io_cluster_buf using
* ec3_tag_ioctx_write. when this reaches the cluster size (or
* ec3_tag_ioctx_close is called) this is reset to 0. */
size_t io_seq_data_ptr;
};
extern enum ec3_status ec3_tag_ioctx_create(
@@ -98,7 +100,13 @@ extern enum ec3_status ec3_tag_ioctx_read_cluster(
extern enum ec3_status ec3_tag_ioctx_write_cluster(
struct ec3_tag_ioctx *tag,
size_t cluster_id,
void *buf,
const void *buf,
size_t len,
size_t *nr_written);
extern enum ec3_status ec3_tag_ioctx_write(
struct ec3_tag_ioctx *tag,
const void *buf,
size_t len,
size_t *nr_written);