mirror of
https://github.com/AltraMayor/f3.git
synced 2025-08-03 18:46:00 -04:00
Merge pull request #190 from AltraMayor/wbuf
Add dynamic buffers to f3write
This commit is contained in:
commit
a7c13b1311
16
f3read.c
16
f3read.c
@ -191,15 +191,16 @@ static ssize_t read_all(int fd, char *buf, size_t count)
|
|||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t check_chunk(int fd, uint64_t *p_expected_offset,
|
static ssize_t check_chunk(struct dynamic_buffer *dbuf, int fd,
|
||||||
uint64_t chunk_size, struct file_stats *stats)
|
uint64_t *p_expected_offset, uint64_t chunk_size,
|
||||||
|
struct file_stats *stats)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE];
|
char *buf = dbuf_get_buf(dbuf, chunk_size);
|
||||||
|
size_t len = dbuf_get_len(dbuf);
|
||||||
ssize_t tot_bytes_read = 0;
|
ssize_t tot_bytes_read = 0;
|
||||||
|
|
||||||
while (chunk_size > 0) {
|
while (chunk_size > 0) {
|
||||||
size_t turn_size = chunk_size <= MAX_BUFFER_SIZE
|
size_t turn_size = chunk_size <= len ? chunk_size : len;
|
||||||
? chunk_size : MAX_BUFFER_SIZE;
|
|
||||||
ssize_t bytes_read = read_all(fd, buf, turn_size);
|
ssize_t bytes_read = read_all(fd, buf, turn_size);
|
||||||
|
|
||||||
if (bytes_read < 0) {
|
if (bytes_read < 0) {
|
||||||
@ -235,6 +236,7 @@ static void validate_file(const char *path, int number, struct flow *fw,
|
|||||||
int fd, saved_errno;
|
int fd, saved_errno;
|
||||||
ssize_t bytes_read;
|
ssize_t bytes_read;
|
||||||
uint64_t expected_offset;
|
uint64_t expected_offset;
|
||||||
|
struct dynamic_buffer dbuf;
|
||||||
|
|
||||||
zero_fstats(stats);
|
zero_fstats(stats);
|
||||||
|
|
||||||
@ -263,11 +265,12 @@ static void validate_file(const char *path, int number, struct flow *fw,
|
|||||||
/* Help the kernel to help us. */
|
/* Help the kernel to help us. */
|
||||||
assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL));
|
assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL));
|
||||||
|
|
||||||
|
dbuf_init(&dbuf);
|
||||||
saved_errno = 0;
|
saved_errno = 0;
|
||||||
expected_offset = (uint64_t)number * GIGABYTES;
|
expected_offset = (uint64_t)number * GIGABYTES;
|
||||||
start_measurement(fw);
|
start_measurement(fw);
|
||||||
while (true) {
|
while (true) {
|
||||||
bytes_read = check_chunk(fd, &expected_offset,
|
bytes_read = check_chunk(&dbuf, fd, &expected_offset,
|
||||||
get_rem_chunk_size(fw), stats);
|
get_rem_chunk_size(fw), stats);
|
||||||
if (bytes_read == 0)
|
if (bytes_read == 0)
|
||||||
break;
|
break;
|
||||||
@ -297,6 +300,7 @@ static void validate_file(const char *path, int number, struct flow *fw,
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
dbuf_free(&dbuf);
|
||||||
close(fd);
|
close(fd);
|
||||||
free(full_fn);
|
free(full_fn);
|
||||||
}
|
}
|
||||||
|
14
f3write.c
14
f3write.c
@ -150,13 +150,14 @@ static int write_all(int fd, const char *buf, size_t count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_chunk(int fd, size_t chunk_size, uint64_t *poffset)
|
static int write_chunk(struct dynamic_buffer *dbuf, int fd, size_t chunk_size,
|
||||||
|
uint64_t *poffset)
|
||||||
{
|
{
|
||||||
char buf[MAX_BUFFER_SIZE];
|
char *buf = dbuf_get_buf(dbuf, chunk_size);
|
||||||
|
size_t len = dbuf_get_len(dbuf);
|
||||||
|
|
||||||
while (chunk_size > 0) {
|
while (chunk_size > 0) {
|
||||||
size_t turn_size = chunk_size <= MAX_BUFFER_SIZE
|
size_t turn_size = chunk_size <= len ? chunk_size : len;
|
||||||
? chunk_size : MAX_BUFFER_SIZE;
|
|
||||||
int ret;
|
int ret;
|
||||||
chunk_size -= turn_size;
|
chunk_size -= turn_size;
|
||||||
*poffset = fill_buffer(buf, turn_size, *poffset);
|
*poffset = fill_buffer(buf, turn_size, *poffset);
|
||||||
@ -177,6 +178,7 @@ static int create_and_fill_file(const char *path, long number, size_t size,
|
|||||||
int fd, saved_errno;
|
int fd, saved_errno;
|
||||||
size_t remaining;
|
size_t remaining;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
|
struct dynamic_buffer dbuf;
|
||||||
|
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
assert(size % fw->block_size == 0);
|
assert(size % fw->block_size == 0);
|
||||||
@ -198,6 +200,7 @@ static int create_and_fill_file(const char *path, long number, size_t size,
|
|||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
|
|
||||||
/* Write content. */
|
/* Write content. */
|
||||||
|
dbuf_init(&dbuf);
|
||||||
saved_errno = 0;
|
saved_errno = 0;
|
||||||
offset = (uint64_t)number * GIGABYTES;
|
offset = (uint64_t)number * GIGABYTES;
|
||||||
remaining = size;
|
remaining = size;
|
||||||
@ -206,7 +209,7 @@ static int create_and_fill_file(const char *path, long number, size_t size,
|
|||||||
uint64_t write_size = get_rem_chunk_size(fw);
|
uint64_t write_size = get_rem_chunk_size(fw);
|
||||||
if (write_size > remaining)
|
if (write_size > remaining)
|
||||||
write_size = remaining;
|
write_size = remaining;
|
||||||
saved_errno = write_chunk(fd, write_size, &offset);
|
saved_errno = write_chunk(&dbuf, fd, write_size, &offset);
|
||||||
if (saved_errno)
|
if (saved_errno)
|
||||||
break;
|
break;
|
||||||
remaining -= write_size;
|
remaining -= write_size;
|
||||||
@ -220,6 +223,7 @@ static int create_and_fill_file(const char *path, long number, size_t size,
|
|||||||
if (!saved_errno)
|
if (!saved_errno)
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
}
|
}
|
||||||
|
dbuf_free(&dbuf);
|
||||||
close(fd);
|
close(fd);
|
||||||
free(full_fn);
|
free(full_fn);
|
||||||
|
|
||||||
|
42
libflow.c
42
libflow.c
@ -366,3 +366,45 @@ out:
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void __dbuf_free(struct dynamic_buffer *dbuf)
|
||||||
|
{
|
||||||
|
if (dbuf->buf != dbuf->backup_buf)
|
||||||
|
free(dbuf->buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_free(struct dynamic_buffer *dbuf)
|
||||||
|
{
|
||||||
|
__dbuf_free(dbuf);
|
||||||
|
dbuf->buf = NULL;
|
||||||
|
dbuf->len = 0;
|
||||||
|
dbuf->max_buf = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dbuf_get_buf(struct dynamic_buffer *dbuf, size_t size)
|
||||||
|
{
|
||||||
|
/* If enough buffer, or it's already the largest buffer, return it. */
|
||||||
|
if (size <= dbuf->len || dbuf->max_buf)
|
||||||
|
return dbuf->buf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a new buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__dbuf_free(dbuf);
|
||||||
|
do {
|
||||||
|
dbuf->buf = malloc(size);
|
||||||
|
if (dbuf->buf != NULL) {
|
||||||
|
dbuf->len = size;
|
||||||
|
return dbuf->buf;
|
||||||
|
} else {
|
||||||
|
dbuf->max_buf = true;
|
||||||
|
}
|
||||||
|
size /= 2;
|
||||||
|
} while (size > sizeof(dbuf->backup_buf));
|
||||||
|
|
||||||
|
/* A larger buffer is not available; failsafe. */
|
||||||
|
dbuf->buf = dbuf->backup_buf;
|
||||||
|
dbuf->len = sizeof(dbuf->backup_buf);
|
||||||
|
return dbuf->buf;
|
||||||
|
}
|
||||||
|
28
libflow.h
28
libflow.h
@ -2,6 +2,7 @@
|
|||||||
#define HEADER_LIBFLOW_H
|
#define HEADER_LIBFLOW_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct flow;
|
struct flow;
|
||||||
|
|
||||||
@ -90,6 +91,31 @@ static inline uint64_t get_rem_chunk_size(struct flow *fw)
|
|||||||
return (fw->blocks_per_delay - fw->processed_blocks) * fw->block_size;
|
return (fw->blocks_per_delay - fw->processed_blocks) * fw->block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_BUFFER_SIZE (1<<21) /* 2MB */
|
struct dynamic_buffer {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
bool max_buf;
|
||||||
|
char backup_buf[1 << 21]; /* 2MB */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void dbuf_init(struct dynamic_buffer *dbuf)
|
||||||
|
{
|
||||||
|
dbuf->buf = dbuf->backup_buf;
|
||||||
|
dbuf->len = sizeof(dbuf->backup_buf);
|
||||||
|
dbuf->max_buf = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbuf_free(struct dynamic_buffer *dbuf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Although the returned buffer may be smaller than @size,
|
||||||
|
* this function never returns NULL.
|
||||||
|
*/
|
||||||
|
char *dbuf_get_buf(struct dynamic_buffer *dbuf, size_t size);
|
||||||
|
|
||||||
|
static inline size_t dbuf_get_len(const struct dynamic_buffer *dbuf)
|
||||||
|
{
|
||||||
|
return dbuf->len;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HEADER_LIBFLOW_H */
|
#endif /* HEADER_LIBFLOW_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user