Files
tromcho.net/src/test/test_atomic.cpp
T

109 lines
3.4 KiB
C++

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdexcept>
#include "addr_util.h"
#include "ringloop.h"
#include "epoll_manager.h"
#include "messenger.h"
int main(int narg, char *args[])
{
if (narg < 2)
{
fprintf(stderr, "USAGE: ./test_atomic <device> [--verify]\n");
return 1;
}
uint64_t write_size = 128*1024;
ring_consumer_t looper;
ring_loop_t *ringloop = new ring_loop_t(RINGLOOP_DEFAULT_SIZE);
uint8_t *buf = (uint8_t*)memalign_or_die(4096, write_size);
memset(buf, 0xA7, write_size);
int fd = open(args[1], O_DIRECT|O_RDWR|O_EXCL);
if (fd < 0)
{
perror("open");
return 1;
}
bool verify = narg >= 3 && !strcmp(args[2], "--verify");
fprintf(stderr, "%s %s\n", verify ? "Verifying" : "Writing", args[1]);
int inflight = 0;
uint64_t offset = 0;
uint64_t prev_offset = 0;
looper.loop = [&]()
{
while (inflight < 16 && offset < (uint64_t)50*1000*1024*1024-write_size)
{
io_uring_sqe *sqe = ringloop->get_sqe();
ring_data_t *data = (ring_data_t*)sqe->user_data;
if (!verify)
{
data->iov = { buf, write_size };
io_uring_prep_writev(sqe, fd, &data->iov, 1, offset);
data->callback = [&, offset](ring_data_t *data)
{
if (data->res != write_size)
{
fprintf(stderr, "Error writing at offset %lu: %s (code %d)\n", offset, strerror(-data->res), -data->res);
exit(1);
}
inflight--;
};
}
else
{
uint8_t *buf2 = (uint8_t*)memalign_or_die(4096, write_size);
memset(buf2, 0, write_size);
data->iov = { buf2, write_size };
io_uring_prep_readv(sqe, fd, &data->iov, 1, offset);
data->callback = [&, buf2, offset](ring_data_t *data)
{
if (data->res != write_size)
{
fprintf(stderr, "Error reading at offset %ju: %s (code %d)\n", offset, strerror(-data->res), -data->res);
exit(1);
}
for (uint64_t i = 0; i < write_size; i++)
{
if (buf2[i] != buf2[0])
{
fprintf(stderr, "Atomicity broken at offset %ju+%ju: byte is %02x\n", offset, i, buf2[i]);
exit(1);
}
}
free(buf2);
inflight--;
if (offset >= prev_offset+1024*1024*1024)
{
fprintf(stderr, "Verified at %ju\n", offset);
prev_offset = offset;
}
};
}
offset += write_size + 4096;
inflight++;
}
ringloop->submit();
};
ringloop->register_consumer(&looper);
while (true)
{
ringloop->loop();
ringloop->wait();
}
close(fd);
free(buf);
delete ringloop;
return 0;
}