Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/en/tutorial-09-http_file_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public:
~~~

Both pread and pwrite return WFFileIOTask. We do not distinguish between sort and psort, and we do not distinguish between client and server task. They all follow the same principle.
In addition to these two interfaces, preadv and pwritev return WFFileVIOTask; fsync and fdsync return WFFileSyncTask. You can see the details in the header file.
In addition to these two interfaces, preadv and pwritev return WFFileVIOTask; fsync and fdatasync return WFFileSyncTask. You can see the details in the header file.
The example uses the user\_data field of the task to save the global data of the service. For larger services, we recommend to use series context. You can see the [proxy examples](/tutorial/tutorial-05-http_proxy.cc) for details.

# Handling file reading results
Expand Down Expand Up @@ -199,4 +199,4 @@ Linux operating system supports a set of asynchronous IO system calls with high
We have implemented a set of posix aio interfaces to support other UNIX systems, and used the sigevent notification method of threads, but it is no longer in use because of its low efficiency.
Currently, for non-Linux systems, asynchronous IO is always simulated by multi-threading. When an IO task arrives, a thread is created in real time to execute IO tasks, and then a callback is used to return to the handler thread pool.
Multi-threaded IO is also the only choice in macOS, because macOS does not have good sigevent support and posix aio will not work in macOS.
Some UNIX systems do not support fdatasync. In this case, an fdsync task is equivalent to an fsync task.
Some UNIX systems do not support fdatasync. In this case, an fdatasync task is equivalent to an fsync task.
4 changes: 2 additions & 2 deletions docs/tutorial-09-http_file_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public:
};
~~~
无论是pread还是pwrite,返回的都是WFFileIOTask。这与不区分sort或psort,不区分client或server task是一个道理。
除这两个接口还有preadv和pwritev,返回WFFileVIOTask,以及fsync,fdsync,返回WFFileSyncTask。可以在头文件里查看。
除这两个接口还有preadv和pwritev,返回WFFileVIOTask,以及fsync,fdatasync,返回WFFileSyncTask。可以在头文件里查看。
示例用了task的user_data域保存服务的全局数据。但对于大服务,我们推荐使用series context。可以参考前面的[proxy示例](../tutorial/tutorial-05-http_proxy.cc)。

# 处理读文件结果
Expand Down Expand Up @@ -195,5 +195,5 @@ Linux操作系统支持一套效率很高,CPU占用非常少的异步IO系统
我们曾经实现过一套posix aio接口用于支持其它UNIX系统,并使用线程的sigevent通知方式,但由于其效率太低,已经不再使用了。
目前,对于非Linux系统,异步IO一律是用多线程实现,在IO任务到达时,实时创建线程执行IO任务,callback回到handler线程池。
多线程IO也是macOS下的唯一选择,因为macOS没有良好的sigevent支持,posix aio行不通。
某些UNIX系统不支持fdatasync调用,这种情况下,fdsync任务将等价于fsync任务
某些UNIX系统不支持fdatasync调用,这种情况下,fdatasync任务将等价于fsync任务

16 changes: 8 additions & 8 deletions src/factory/FileTaskImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ class WFFilefsyncTask : public WFFileSyncTask
}
};

class WFFilefdsyncTask : public WFFileSyncTask
class WFFilefdatasyncTask : public WFFileSyncTask
{
public:
WFFilefdsyncTask(int fd, IOService *service, fsync_callback_t&& cb) :
WFFilefdatasyncTask(int fd, IOService *service, fsync_callback_t&& cb) :
WFFileSyncTask(service, std::move(cb))
{
this->args.fd = fd;
Expand All @@ -140,7 +140,7 @@ class WFFilefdsyncTask : public WFFileSyncTask
protected:
virtual int prepare()
{
this->prep_fdsync(this->args.fd);
this->prep_fdatasync(this->args.fd);
return 0;
}
};
Expand Down Expand Up @@ -344,12 +344,12 @@ WFFileSyncTask *WFTaskFactory::create_fsync_task(int fd,
std::move(callback));
}

WFFileSyncTask *WFTaskFactory::create_fdsync_task(int fd,
fsync_callback_t callback)
WFFileSyncTask *WFTaskFactory::create_fdatasync_task(int fd,
fsync_callback_t callback)
{
return new WFFilefdsyncTask(fd,
WFGlobal::get_io_service(),
std::move(callback));
return new WFFilefdatasyncTask(fd,
WFGlobal::get_io_service(),
std::move(callback));
}

/* Factory functions with path name. */
Expand Down
6 changes: 2 additions & 4 deletions src/factory/WFTaskFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,8 @@ class WFTaskFactory
static WFFileSyncTask *create_fsync_task(int fd,
fsync_callback_t callback);

/* On systems that do not support fdatasync(), like macOS,
* fdsync task is equal to fsync task. */
static WFFileSyncTask *create_fdsync_task(int fd,
fsync_callback_t callback);
static WFFileSyncTask *create_fdatasync_task(int fd,
fsync_callback_t callback);

/* File tasks with path name. */
public:
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/IOService_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ void IOSession::prep_fsync(int fd)
iocb->aio_lio_opcode = IO_CMD_FSYNC;
}

void IOSession::prep_fdsync(int fd)
void IOSession::prep_fdatasync(int fd)
{
struct iocb *iocb = (struct iocb *)this->iocb_buf;

Expand Down
2 changes: 1 addition & 1 deletion src/kernel/IOService_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class IOSession
void prep_pwritev(int fd, const struct iovec *iov, int iovcnt,
long long offset);
void prep_fsync(int fd);
void prep_fdsync(int fd);
void prep_fdatasync(int fd);

protected:
long get_res() const { return this->res; }
Expand Down
16 changes: 9 additions & 7 deletions src/kernel/IOService_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void IOSession::prep_fsync(int fd)
this->op = IO_CMD_FSYNC;
}

void IOSession::prep_fdsync(int fd)
void IOSession::prep_fdatasync(int fd)
{
this->fd = fd;
this->op = IO_CMD_FDSYNC;
Expand All @@ -104,6 +104,12 @@ int IOService::init(int maxevents)
return -1;
}

p = dlsym(RTLD_DEFAULT, "fdatasync");
if (p)
this->fdatasync = (int (*)(int))p;
else
this->fdatasync = fsync;

p = dlsym(RTLD_DEFAULT, "preadv");
if (p)
this->preadv = (ssize_t (*)(int, const struct iovec *, int, off_t))p;
Expand Down Expand Up @@ -216,15 +222,11 @@ void *IOService::io_routine(void *arg)
case IO_CMD_PWRITE:
ret = pwrite(fd, session->buf, session->count, session->offset);
break;
case IO_CMD_FSYNC:
ret = fsync(fd);
break;
case IO_CMD_FDSYNC:
#if _POSIX_SYNCHRONIZED_IO > 0
ret = fdatasync(fd);
break;
#endif
case IO_CMD_FSYNC:
ret = fsync(fd);
ret = service->fdatasync(fd);
break;
case IO_CMD_PREADV:
ret = service->preadv(fd, (const struct iovec *)session->buf,
Expand Down
9 changes: 6 additions & 3 deletions src/kernel/IOService_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class IOSession
void prep_pwritev(int fd, const struct iovec *iov, int iovcnt,
long long offset);
void prep_fsync(int fd);
void prep_fdsync(int fd);
void prep_fdatasync(int fd);

protected:
long get_res() const { return this->res; }
Expand Down Expand Up @@ -105,13 +105,16 @@ class IOService
static void *io_routine(void *arg);
static void *aio_finish(void *ptr, void *context);

private:
int (*fdatasync)(int);
ssize_t (*preadv)(int, const struct iovec *, int, off_t);
ssize_t (*pwritev)(int, const struct iovec *, int, off_t);

private:
static ssize_t preadv_emul(int fd, const struct iovec *iov, int iovcnt,
off_t offset);
static ssize_t pwritev_emul(int fd, const struct iovec *iov, int iovcnt,
off_t offset);
ssize_t (*preadv)(int, const struct iovec *, int, off_t);
ssize_t (*pwritev)(int, const struct iovec *, int, off_t);

public:
virtual ~IOService() { }
Expand Down
2 changes: 1 addition & 1 deletion src/manager/WFFacilities.inl
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ inline WFFuture<int> WFFacilities::async_fdatasync(int fd)
{
auto *pr = new WFPromise<int>();
auto fr = pr->get_future();
auto *task = WFTaskFactory::create_fdsync_task(fd, __fsync_future_callback);
auto *task = WFTaskFactory::create_fdatasync_task(fd, __fsync_future_callback);

task->user_data = pr;
task->start();
Expand Down