Skip to content

Commit b6bef2b

Browse files
optimize file operation and http coroutine client (#5829)
1 parent 5d95c4c commit b6bef2b

File tree

15 files changed

+441
-365
lines changed

15 files changed

+441
-365
lines changed

.github/workflows/core.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747

4848
- name: build
4949
run: |
50-
cmake . -D CODE_COVERAGE=ON -D enable_thread=1 -D verbose=1 || exit 1
50+
cmake . -D CODE_COVERAGE=ON -D enable_thread=1 -D verbose=1 -D async_io=1 || exit 1
5151
make VERBOSE=1 -j $(nproc) core-tests || exit 1
5252
5353
- name: run tests

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ if (DEFINED enable_thread)
127127
add_definitions(-DSW_THREAD)
128128
endif()
129129

130+
if (DEFINED async_io)
131+
# This macro is exclusively used for kernel unit testing to
132+
# verify the asynchronous operation functionality of the file thread pool.
133+
add_definitions(-DSW_USE_ASYNC)
134+
endif()
135+
130136
if (DEFINED verbose)
131137
add_definitions(-DSW_VERBOSE)
132138
endif()

core-tests/src/coroutine/file.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Swoole |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 2.0 of the Apache license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.apache.org/licenses/LICENSE-2.0.html |
9+
| If you did not receive a copy of the Apache2.0 license and are unable|
10+
| to obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: NathanFreeman <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include <sys/file.h>
18+
#include <sys/stat.h>
19+
#include "test_coroutine.h"
20+
#include "swoole_file.h"
21+
22+
using namespace std;
23+
using namespace swoole;
24+
using swoole::coroutine::System;
25+
26+
TEST(coroutine_async_file, async_file) {
27+
coroutine::run([](void *arg) {
28+
string filename = "/tmp/file.txt";
29+
auto file = new AsyncFile(filename, O_CREAT | O_RDWR, 0666);
30+
ON_SCOPE_EXIT {
31+
delete file;
32+
};
33+
ASSERT_EQ(file->ready(), true);
34+
ASSERT_EQ(file->truncate(0), true);
35+
ASSERT_EQ(file->set_offset(0), 0);
36+
ASSERT_EQ(file->get_offset(), 0);
37+
38+
const char *data = "Hello World!";
39+
size_t length = strlen(data);
40+
ASSERT_EQ(file->write((void *) data, length), static_cast<ssize_t>(length));
41+
42+
ASSERT_EQ(file->sync(), true);
43+
ASSERT_EQ(file->set_offset(0), 0);
44+
45+
char buf[1024];
46+
ASSERT_EQ(file->read((void *) buf, 1024), static_cast<ssize_t>(length));
47+
buf[length] = '\0';
48+
ASSERT_STREQ(data, buf);
49+
50+
struct stat statbuf {};
51+
ASSERT_EQ(file->stat(&statbuf), true);
52+
ASSERT_TRUE(statbuf.st_size > 0);
53+
});
54+
}

core-tests/src/coroutine/hook.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ void static test_file_hook() {
4545
ASSERT_EQ(swoole_coroutine_fsync(fd), 0);
4646
ASSERT_EQ(swoole_coroutine_fdatasync(fd), 0);
4747

48-
swoole_coroutine_close_file(fd);
48+
swoole_coroutine_close(fd);
4949

5050
fd = swoole_coroutine_open(test_file, O_RDONLY, 0);
5151
char data[8192];
5252
ASSERT_EQ(swoole_coroutine_read(fd, data, n_buf), n_buf);
5353
ASSERT_EQ(std::string(buf, n_buf), std::string(data, n_buf));
54-
swoole_coroutine_close_file(fd);
54+
swoole_coroutine_close(fd);
5555

5656
struct stat statbuf;
5757
swoole_coroutine_stat(test_file, &statbuf);
@@ -735,3 +735,17 @@ TEST(coroutine_hook, freopen) {
735735
coroutine::run([&](void *arg) { test_freopen(); });
736736
test_freopen();
737737
}
738+
739+
TEST(coroutine_hook, ftruncate) {
740+
coroutine::run([&](void *arg) {
741+
int fd = swoole_coroutine_open("/tmp/123.txt", O_CREAT | O_RDWR, 0);
742+
ASSERT_TRUE(fd > 0);
743+
744+
const char *data = "aaaaaaaaaaaaaaaaaaaaaaa";
745+
size_t length = strlen(data);
746+
ssize_t write_length = swoole_coroutine_write(fd, (const void *) data, length);
747+
ASSERT_TRUE(write_length == static_cast<ssize_t>(length));
748+
ASSERT_TRUE(swoole_coroutine_ftruncate(fd, 0) == 0);
749+
swoole_coroutine_close(fd);
750+
});
751+
}

core-tests/src/coroutine/iouring.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,53 +46,53 @@ TEST(iouring, list_all_opcode) {
4646
TEST(iouring, open_and_close) {
4747
coroutine::run([](void *arg) {
4848
const char *test_file = "/tmp/file_1";
49-
int fd = swoole_coroutine_iouring_open(test_file, O_CREAT, 0666);
49+
int fd = Iouring::open(test_file, O_CREAT, 0666);
5050
ASSERT_TRUE(fd > 0);
5151

52-
int result = swoole_coroutine_iouring_close_file(fd);
52+
int result = Iouring::close(fd);
5353
ASSERT_TRUE(result == 0);
5454

55-
result = swoole_coroutine_iouring_unlink(test_file);
55+
result = Iouring::unlink(test_file);
5656
ASSERT_TRUE(result == 0);
5757
});
5858
}
5959

6060
TEST(iouring, mkdir_and_rmdir) {
6161
coroutine::run([](void *arg) {
6262
const char *directory = "/tmp/aaaa";
63-
int result = swoole_coroutine_iouring_mkdir(directory, 0755);
63+
int result = Iouring::mkdir(directory, 0755);
6464
ASSERT_TRUE(result == 0);
6565

66-
result = swoole_coroutine_iouring_rmdir(directory);
66+
result = Iouring::rmdir(directory);
6767
ASSERT_TRUE(result == 0);
6868
});
6969
}
7070

7171
TEST(iouring, write_and_read) {
7272
coroutine::run([](void *arg) {
7373
const char *test_file = "/tmp/file_2";
74-
int fd = swoole_coroutine_iouring_open(test_file, O_CREAT | O_RDWR, 0666);
74+
int fd = Iouring::open(test_file, O_CREAT | O_RDWR, 0666);
7575
ASSERT_TRUE(fd > 0);
7676

7777
const char *data = "aaaaaaaaaaaaaaaaaaaaaaa";
7878
size_t length = strlen(data);
79-
ssize_t result = swoole_coroutine_iouring_write(fd, (const void *) data, length);
79+
ssize_t result = Iouring::write(fd, (const void *) data, length);
8080
ASSERT_TRUE(result > 0);
8181
ASSERT_TRUE(result == static_cast<ssize_t>(length));
8282

8383
lseek(fd, 0, SEEK_SET);
8484

8585
char buf[128];
86-
result = swoole_coroutine_iouring_read(fd, (void *) buf, 128);
86+
result = Iouring::read(fd, (void *) buf, 128);
8787
ASSERT_TRUE(result > 0);
8888
ASSERT_TRUE(result == static_cast<ssize_t>(length));
8989
buf[result] = '\0';
9090
ASSERT_STREQ(data, buf);
9191

92-
result = swoole_coroutine_iouring_close_file(fd);
92+
result = Iouring::close(fd);
9393
ASSERT_TRUE(result == 0);
9494

95-
result = swoole_coroutine_iouring_unlink(test_file);
95+
result = Iouring::unlink(test_file);
9696
ASSERT_TRUE(result == 0);
9797
});
9898
}
@@ -101,64 +101,85 @@ TEST(iouring, rename) {
101101
coroutine::run([](void *arg) {
102102
const char *oldpath = "/tmp/file_2";
103103
const char *newpath = "/tmp/file_3";
104-
int fd = swoole_coroutine_iouring_open(oldpath, O_CREAT | O_RDWR, 0666);
104+
int fd = Iouring::open(oldpath, O_CREAT | O_RDWR, 0666);
105105
ASSERT_TRUE(fd > 0);
106106

107-
int result = swoole_coroutine_iouring_close_file(fd);
107+
int result = Iouring::close(fd);
108108
ASSERT_TRUE(result == 0);
109109

110-
result = swoole_coroutine_iouring_rename(oldpath, newpath);
110+
result = Iouring::rename(oldpath, newpath);
111111
ASSERT_TRUE(result == 0);
112112

113-
result = swoole_coroutine_iouring_unlink(newpath);
113+
result = Iouring::unlink(newpath);
114114
ASSERT_TRUE(result == 0);
115115
});
116116
}
117117

118+
#ifdef HAVE_IOURING_STATX
118119
TEST(iouring, fstat_and_stat) {
119120
coroutine::run([](void *arg) {
120121
struct stat statbuf {};
121-
int fd = swoole_coroutine_iouring_open(TEST_TMP_FILE, O_RDWR, 0666);
122+
int fd = Iouring::open(TEST_TMP_FILE, O_RDWR, 0666);
122123
ASSERT_TRUE(fd > 0);
123-
int result = swoole_coroutine_iouring_fstat(fd, &statbuf);
124+
int result = Iouring::fstat(fd, &statbuf);
124125
ASSERT_TRUE(result == 0);
125126
ASSERT_TRUE(statbuf.st_size > 0);
126127

127-
result = swoole_coroutine_iouring_close_file(fd);
128+
result = Iouring::close(fd);
128129
ASSERT_TRUE(result == 0);
129130

130131
statbuf = {};
131-
result = swoole_coroutine_iouring_stat(TEST_TMP_FILE, &statbuf);
132+
result = Iouring::stat(TEST_TMP_FILE, &statbuf);
132133
ASSERT_TRUE(result == 0);
133134
ASSERT_TRUE(statbuf.st_size > 0);
134135
});
135136
}
137+
#endif
136138

137139
TEST(iouring, fsync_and_fdatasync) {
138140
coroutine::run([](void *arg) {
139141
const char *test_file = "/tmp/file_2";
140-
int fd = swoole_coroutine_iouring_open(test_file, O_CREAT | O_RDWR, 0666);
142+
int fd = Iouring::open(test_file, O_CREAT | O_RDWR, 0666);
141143
ASSERT_TRUE(fd > 0);
142144

143145
const char *data = "aaaaaaaaaaaaaaaaaaaaaaa";
144146
size_t length = strlen(data);
145-
ssize_t write_length = swoole_coroutine_iouring_write(fd, (const void *) data, length);
147+
ssize_t write_length = Iouring::write(fd, (const void *) data, length);
146148
ASSERT_TRUE(write_length == static_cast<ssize_t>(length));
147149

148-
int result = swoole_coroutine_iouring_fsync(fd);
150+
int result = Iouring::fsync(fd);
149151
ASSERT_TRUE(result == 0);
150152

151-
write_length = swoole_coroutine_iouring_write(fd, (const void *) data, length);
153+
write_length = Iouring::write(fd, (const void *) data, length);
152154
ASSERT_TRUE(write_length == static_cast<ssize_t>(length));
153155

154-
result = swoole_coroutine_iouring_fdatasync(fd);
156+
result = Iouring::fdatasync(fd);
157+
ASSERT_TRUE(result == 0);
158+
159+
result = Iouring::close(fd);
155160
ASSERT_TRUE(result == 0);
156161

157-
result = swoole_coroutine_iouring_close_file(fd);
162+
result = Iouring::unlink(test_file);
158163
ASSERT_TRUE(result == 0);
164+
});
165+
}
166+
167+
#ifdef HAVE_IOURING_FTRUNCATE
168+
TEST(iouring, ftruncate) {
169+
coroutine::run([&](void *arg) {
170+
const char *test_file = "/tmp/file_3";
171+
int fd = Iouring::open(test_file, O_CREAT | O_RDWR, 0666);
172+
ASSERT_TRUE(fd > 0);
173+
174+
const char *data = "aaaaaaaaaaaaaaaaaaaaaaa";
175+
size_t length = strlen(data);
176+
ssize_t write_length = Iouring::write(fd, (const void *) data, length);
177+
ASSERT_TRUE(write_length == static_cast<ssize_t>(length));
159178

160-
result = swoole_coroutine_iouring_unlink(test_file);
179+
int result = Iouring::ftruncate(fd, 0);
161180
ASSERT_TRUE(result == 0);
181+
Iouring::close(fd);
162182
});
163183
}
164184
#endif
185+
#endif

ext-src/swoole_http_client_coro.cc

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ SW_EXTERN_C_BEGIN
3636
#include "ext/standard/base64.h"
3737

3838
SW_EXTERN_C_END
39-
using swoole::File;
39+
using swoole::AsyncFile;
4040
using swoole::String;
4141
using swoole::coroutine::Socket;
4242
using swoole::network::Address;
@@ -126,8 +126,8 @@ class Client {
126126
bool in_callback = false;
127127
bool has_upload_files = false;
128128

129-
std::shared_ptr<File> download_file; // save http response to file
130-
zend::String download_file_name; // unlink the file on error
129+
std::shared_ptr<AsyncFile> download_file; // save http response to file
130+
zend::String download_file_name; // unlink the file on error
131131
zend_long download_offset = 0;
132132

133133
/* safety zval */
@@ -486,14 +486,6 @@ static int http_parser_on_headers_complete(llhttp_t *parser) {
486486
return 0;
487487
}
488488

489-
static inline ssize_t http_client_co_write(int sockfd, const void *buf, size_t count) {
490-
#ifdef SW_USE_IOURING
491-
return swoole_coroutine_iouring_write(sockfd, buf, count);
492-
#else
493-
return swoole_coroutine_write(sockfd, buf, count);
494-
#endif
495-
}
496-
497489
static int http_parser_on_body(llhttp_t *parser, const char *at, size_t length) {
498490
auto *http = static_cast<Client *>(parser->data);
499491
if (http->write_func) {
@@ -525,7 +517,7 @@ static int http_parser_on_body(llhttp_t *parser, const char *at, size_t length)
525517
if (http->download_file_name.get() && http->body->length > 0) {
526518
if (http->download_file == nullptr) {
527519
char *download_file_name = http->download_file_name.val();
528-
std::shared_ptr<File> fp = std::make_shared<File>(download_file_name, O_CREAT | O_WRONLY, 0664);
520+
auto fp = std::make_shared<AsyncFile>(download_file_name, O_CREAT | O_WRONLY, 0664);
529521
if (!fp->ready()) {
530522
swoole_sys_warning("open(%s, O_CREAT | O_WRONLY) failed", download_file_name);
531523
return -1;
@@ -543,8 +535,7 @@ static int http_parser_on_body(llhttp_t *parser, const char *at, size_t length)
543535
}
544536
http->download_file = fp;
545537
}
546-
if (http_client_co_write(http->download_file->get_fd(), SW_STRINGL(http->body)) !=
547-
(ssize_t) http->body->length) {
538+
if (http->download_file->write(SW_STRINGL(http->body)) != (ssize_t) http->body->length) {
548539
return -1;
549540
}
550541
http->body->clear();

ext-src/swoole_runtime.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ static zend::ConcurrencyHashMap<std::string, zend_internal_arg_info *> ori_func_
238238
SW_EXTERN_C_BEGIN
239239
#include "ext/standard/file.h"
240240
#include "thirdparty/php/streams/plain_wrapper.c"
241+
#undef close
241242
SW_EXTERN_C_END
242243

243244
void php_swoole_runtime_minit(int module_number) {

0 commit comments

Comments
 (0)