Skip to content
Snippets Groups Projects
Commit e38375a8 authored by Florian Fischer's avatar Florian Fischer Committed by Florian Schmaus
Browse files

[IO] add support for openat and open

parent 234c4037
No related branches found
No related tags found
No related merge requests found
......@@ -9,9 +9,11 @@
#include "emper.h" // for fiber, cps, bps, runtime
#ifdef EMPER_IO
#include <fcntl.h>
#include <sys/socket.h> // for socklen_t
#include <sys/types.h> // for off_t
#include <cstdarg>
#include <cstddef> // for size_t
#include "io.hpp" // for emper::io::emper_*
......@@ -139,5 +141,33 @@ auto emper_writev(int fildes, const struct iovec* iov, int iovcnt) -> ssize_t {
return emper::io::writevAndWait(fildes, iov, iovcnt);
}
// C function overloading inspired by
// http://locklessinc.com/articles/overloading
auto emper_open(const char* pathname, int flags, ...) -> int {
if (flags | O_CREAT || flags | O_TMPFILE) {
va_list v;
va_start(v, flags);
mode_t mode = va_arg(v, mode_t);
va_end(v);
return emper::io::openAndWait(pathname, flags, mode);
}
return emper::io::openAndWait(pathname, flags);
}
auto emper_openat(int dirfd, const char* pathname, int flags, ...) -> int {
if (flags | O_CREAT || flags | O_TMPFILE) {
va_list v;
va_start(v, flags);
mode_t mode = va_arg(v, mode_t);
va_end(v);
return emper::io::openatAndWait(dirfd, pathname, flags, mode);
}
return emper::io::openatAndWait(dirfd, pathname, flags);
}
auto emper_close(int fd) -> int { return emper::io::closeAndWait(fd); }
#endif
......@@ -2,12 +2,14 @@
// Copyright © 2020 Florian Schmaus, Florian Fischer
#pragma once
#include <stdarg.h> // NOLINT(modernize-deprecated-headers)
#include <stddef.h> // NOLINT(modernize-deprecated-headers)
#include "emper-common.h"
#include "emper-config.h"
#include "stddef.h" // NOLINT(modernize-deprecated-headers)
#ifdef EMPER_IO
#include "sys/socket.h"
#include <sys/socket.h>
#endif
typedef struct runtime runtime; // NOLINT(modernize-use-using)
......@@ -88,6 +90,12 @@ ssize_t emper_write_file(int fildes, const void* buf, size_t nbyte, off_t offset
// NOLINTNEXTLINE(modernize-use-trailing-return-type)
ssize_t emper_writev(int fildes, const struct iovec* iov, int iovcnt);
// NOLINTNEXTLINE(modernize-use-trailing-return-type)
int emper_open(const char* pathname, int flags, ...);
// NOLINTNEXTLINE(modernize-use-trailing-return-type)
int emper_openat(int dirfd, const char* pathname, int flags, ...);
// NOLINTNEXTLINE(modernize-use-trailing-return-type)
int emper_close(int fd);
#endif
......
......@@ -2,6 +2,7 @@
// Copyright © 2020-2021 Florian Fischer
#pragma once
#include <fcntl.h>
#include <sys/socket.h> // for socklen_t
#include <sys/types.h> // for ssize_t, off_t
......@@ -334,6 +335,81 @@ inline auto writevAndWait(int fildes, const struct iovec *iov, int iovcnt) -> ss
return future.waitAndSetErrno();
}
/**
* @brief asynchronous openat mimicking POSIX openat(3)
*
* This method must be called from inside the emper runtime because it uses
* the worker-local IoContext
*
* @param dirfd directory the pathname is interpreted relative to
* @param pathname path to the file to open
* @param flags specify access mode
* @param mode in which the file should be created
*
* @return Future object which signals the completion of the openat request
*/
inline auto openat(int dirfd, const char *pathname, int flags, mode_t mode = 0)
-> std::unique_ptr<Future> {
auto future = std::make_unique<OpenatFuture>(dirfd, pathname, flags, mode);
future->submit();
return future;
}
/**
* @brief synchronous openat mimicking POSIX openat(3)
*
* This method must be called from inside the emper runtime because it uses
* the worker-local IoContext
*
* @param dirfd directory the pathname is interpreted relative to
* @param pathname path to the file to open
* @param flags specify access mode
* @param mode in which the file should be created
*
* @return fd on success, -1 on error
*/
inline auto openatAndWait(int dirfd, const char *pathname, int flags, mode_t mode = 0) -> size_t {
OpenatFuture future(dirfd, pathname, flags, mode);
future.submit();
return future.waitAndSetErrno();
}
/**
* @brief asynchronous open mimicking POSIX open(3)
*
* This method must be called from inside the emper runtime because it uses
* the worker-local IoContext
*
* @param pathname path to the file to open
* @param flags specify access mode
* @param mode in which the file should be created
*
* @return Future object which signals the completion of the open request
*/
inline auto open(const char *pathname, int flags, mode_t mode = 0) -> std::unique_ptr<Future> {
auto future = std::make_unique<OpenatFuture>(AT_FDCWD, pathname, flags, mode);
future->submit();
return future;
}
/**
* @brief synchronous open mimicking POSIX open(3)
*
* This method must be called from inside the emper runtime because it uses
* the worker-local IoContext
*
* @param pathname path to the file to open
* @param flags specify access mode
* @param mode in which the file should be created
*
* @return fd on success, -1 on error
*/
inline auto openAndWait(const char *pathname, int flags, mode_t mode = 0) -> size_t {
OpenatFuture future(AT_FDCWD, pathname, flags, mode);
future.submit();
return future.waitAndSetErrno();
}
/**
* @brief Non-blocking close mimicking POSIX close(3)
*
......
......@@ -421,6 +421,16 @@ class ReadFuture : public PartialCompletableFuture {
read_all ? ENABLE_PARTIAL_COMPLETION : DISABLE_PARTIAL_COMPLETION){};
};
class OpenatFuture : public Future {
void prepareSqe(io_uring_sqe* sqe) override {
io_uring_prep_openat(sqe, fd, reinterpret_cast<const char*>(buf), len, offsetOrFlags);
}
public:
OpenatFuture(int dirfd, const void* pathname, int flags, mode_t mode = 0)
: Future(Operation::OPENAT, dirfd, const_cast<void*>(pathname), flags, mode){};
};
class WriteFuture : public PartialCompletableFuture {
void prepareSqe(io_uring_sqe* sqe) override {
if (partialCompletion == DISABLE_PARTIAL_COMPLETION) {
......
......@@ -20,6 +20,9 @@ auto operator<<(std::ostream& os, const Operation& op) -> std::ostream& {
case Operation::ACCEPT:
os << "accept";
break;
case Operation::OPENAT:
os << "openat";
break;
case Operation::READ:
os << "read";
break;
......
......@@ -11,6 +11,7 @@ enum class Operation {
RECV,
CONNECT,
ACCEPT,
OPENAT,
READ,
WRITE,
WRITEV,
......
......@@ -63,7 +63,7 @@ static void server_func(int sockfd) {
}
close(file_fd);
file_fd = open(file_name, O_RDONLY);
file_fd = emper::io::openAndWait(file_name, O_RDONLY);
if (file_fd == -1) {
DIE_MSG_ERRNO("open failed");
}
......@@ -113,7 +113,7 @@ static void server_func(int sockfd) {
}
close(file_fd);
file_fd = open(file2_name, O_RDONLY);
file_fd = emper::io::openAndWait(file2_name, O_RDONLY);
if (file_fd == -1) {
DIE_MSG_ERRNO("open failed");
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment