diff --git a/docs/en/tutorial-09-http_file_server.md b/docs/en/tutorial-09-http_file_server.md index f966d405f2..2c67468c71 100644 --- a/docs/en/tutorial-09-http_file_server.md +++ b/docs/en/tutorial-09-http_file_server.md @@ -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 @@ -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. diff --git a/docs/tutorial-09-http_file_server.md b/docs/tutorial-09-http_file_server.md index e0913b5afe..f38bc81e5e 100644 --- a/docs/tutorial-09-http_file_server.md +++ b/docs/tutorial-09-http_file_server.md @@ -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)。 # 处理读文件结果 @@ -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任务。 diff --git a/src/factory/FileTaskImpl.cc b/src/factory/FileTaskImpl.cc index 5d9de0a3b1..8be46d7a4b 100644 --- a/src/factory/FileTaskImpl.cc +++ b/src/factory/FileTaskImpl.cc @@ -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; @@ -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; } }; @@ -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. */ diff --git a/src/factory/WFTaskFactory.h b/src/factory/WFTaskFactory.h index 7719b97d83..7ebdaa5d3e 100644 --- a/src/factory/WFTaskFactory.h +++ b/src/factory/WFTaskFactory.h @@ -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: diff --git a/src/kernel/IOService_linux.cc b/src/kernel/IOService_linux.cc index 81acb0f0fc..1c4e0d9725 100644 --- a/src/kernel/IOService_linux.cc +++ b/src/kernel/IOService_linux.cc @@ -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; diff --git a/src/kernel/IOService_linux.h b/src/kernel/IOService_linux.h index 11103ea6c7..1693599c8f 100644 --- a/src/kernel/IOService_linux.h +++ b/src/kernel/IOService_linux.h @@ -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; } diff --git a/src/kernel/IOService_thread.cc b/src/kernel/IOService_thread.cc index 9e59a6fdfa..c29ce39a34 100644 --- a/src/kernel/IOService_thread.cc +++ b/src/kernel/IOService_thread.cc @@ -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; @@ -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; @@ -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, diff --git a/src/kernel/IOService_thread.h b/src/kernel/IOService_thread.h index 29bebaddbb..55c72c4ea2 100644 --- a/src/kernel/IOService_thread.h +++ b/src/kernel/IOService_thread.h @@ -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; } @@ -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() { } diff --git a/src/manager/WFFacilities.inl b/src/manager/WFFacilities.inl index 32a05a04d8..9df01bab28 100644 --- a/src/manager/WFFacilities.inl +++ b/src/manager/WFFacilities.inl @@ -131,7 +131,7 @@ inline WFFuture WFFacilities::async_fdatasync(int fd) { auto *pr = new WFPromise(); 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();