Skip to content

Commit 70f0a8f

Browse files
authored
修复HTTP服务Windows性能异常和中文路径相关Bug (#701)
* fix windows defaultStaticHandler abnormal performance fix http chinese name file cache bug support http index directory view chinese name add high-performance wchar_to_utf8 and utf8_to_wchar * FileCache Open Performance Optimization
1 parent 758b4c1 commit 70f0a8f

File tree

4 files changed

+63
-30
lines changed

4 files changed

+63
-30
lines changed

cpputil/hdir.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "hplatform.h"
44

55
#ifdef OS_WIN
6+
#include "hstring.h" // import hv::utf8_to_wchar hv::wchar_to_utf8
67
//FILETIME starts from 1601-01-01 UTC, epoch from 1970-01-01 UTC
78
//FILETIME unit (100ns)
89
#define FILETIME_EPOCH_DIFF 11644473600 // s
@@ -61,15 +62,15 @@ int listdir(const char* dir, std::list<hdir_t>& dirs) {
6162
#elif defined(OS_WIN)
6263
// FindFirstFile -> FindNextFile -> FindClose
6364
strcat(path, "*");
64-
WIN32_FIND_DATAA data;
65-
HANDLE h = FindFirstFileA(path, &data);
65+
WIN32_FIND_DATAW data;
66+
HANDLE h = FindFirstFileW(hv::utf8_to_wchar(path).c_str(), &data);
6667
if (h == NULL) {
6768
return -1;
6869
}
6970
hdir_t tmp;
7071
do {
7172
memset(&tmp, 0, sizeof(hdir_t));
72-
strncpy(tmp.name, data.cFileName, sizeof(tmp.name));
73+
strncpy(tmp.name, hv::wchar_to_utf8(data.cFileName).c_str(), sizeof(tmp.name));
7374
tmp.type = 'f';
7475
if (data.dwFileAttributes & _A_SUBDIR) {
7576
tmp.type = 'd';
@@ -80,7 +81,7 @@ int listdir(const char* dir, std::list<hdir_t>& dirs) {
8081
tmp.mtime = FileTime2Epoch(data.ftLastWriteTime);
8182
tmp.ctime = FileTime2Epoch(data.ftCreationTime);
8283
dirs.push_back(tmp);
83-
} while (FindNextFileA(h, &data));
84+
} while (FindNextFileW(h, &data));
8485
FindClose(h);
8586
#endif
8687
dirs.sort(less);

cpputil/hstring.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,25 @@ std::string NetAddr::to_string(const char* ip, int port) {
225225
return hv::asprintf(fmt, ip, port);
226226
}
227227

228+
#ifdef OS_WIN
229+
std::string wchar_to_utf8(const std::wstring &wstr) {
230+
std::string str(4 * wstr.size() + 1, '\0');
231+
str.resize(WideCharToMultiByte(
232+
CP_UTF8, 0,
233+
wstr.c_str(), wstr.size(),
234+
const_cast<char*>(str.data()), str.size(),
235+
NULL, NULL));
236+
return str;
237+
}
238+
239+
std::wstring utf8_to_wchar(const std::string &str) {
240+
std::wstring wstr(2 * str.size() + 1, '\0');
241+
wstr.resize(MultiByteToWideChar(
242+
CP_UTF8, 0,
243+
str.c_str(), str.size(),
244+
const_cast<wchar_t*>(wstr.data()), wstr.size()));
245+
return wstr;
246+
}
247+
#endif // OS_WIN
248+
228249
} // end namespace hv

cpputil/hstring.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ struct HV_EXPORT NetAddr {
8888
static std::string to_string(const char* ip, int port);
8989
};
9090

91+
// windows wchar and utf8 conver
92+
#ifdef OS_WIN
93+
HV_EXPORT std::string wchar_to_utf8(const std::wstring &wstr);
94+
HV_EXPORT std::wstring utf8_to_wchar(const std::string &str);
95+
#endif // OS_WIN
96+
9197
} // end namespace hv
9298

9399
#endif // HV_STRING_H_

http/server/FileCache.cpp

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include "httpdef.h" // import http_content_type_str_by_suffix
99
#include "http_page.h" // import make_index_of_page
1010

11-
#ifdef _MSC_VER
12-
#include <codecvt>
11+
#ifdef OS_WIN
12+
#include "hstring.h" // import hv::utf8_to_wchar
1313
#endif
1414

1515
#define ETAG_FMT "\"%zx-%zx\""
@@ -19,27 +19,26 @@ FileCache::FileCache() {
1919
expired_time = 60; // s
2020
}
2121

22-
static int hv_open(char const* filepath, int flags) {
23-
#ifdef _MSC_VER
24-
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv;
25-
auto wfilepath = conv.from_bytes(filepath);
26-
int fd = _wopen(wfilepath.c_str(), flags);
27-
#else
28-
int fd = open(filepath, flags);
29-
#endif
30-
return fd;
31-
}
32-
3322
file_cache_ptr FileCache::Open(const char* filepath, OpenParam* param) {
3423
std::lock_guard<std::mutex> locker(mutex_);
3524
file_cache_ptr fc = Get(filepath);
25+
#ifdef OS_WIN
26+
std::wstring wfilepath;
27+
#endif
3628
bool modified = false;
3729
if (fc) {
3830
time_t now = time(NULL);
3931
if (now - fc->stat_time > stat_interval) {
40-
modified = fc->is_modified();
4132
fc->stat_time = now;
4233
fc->stat_cnt++;
34+
#ifdef OS_WIN
35+
wfilepath = hv::utf8_to_wchar(filepath);
36+
now = fc->st.st_mtime;
37+
_wstat(wfilepath.c_str(), (struct _stat*)&fc->st);
38+
modified = now != fc->st.st_mtime;
39+
#else
40+
modified = fc->is_modified();
41+
#endif
4342
}
4443
if (param->need_read) {
4544
if (!modified && fc->is_complete()) {
@@ -48,31 +47,37 @@ file_cache_ptr FileCache::Open(const char* filepath, OpenParam* param) {
4847
}
4948
}
5049
if (fc == NULL || modified || param->need_read) {
50+
struct stat st;
5151
int flags = O_RDONLY;
5252
#ifdef O_BINARY
5353
flags |= O_BINARY;
5454
#endif
55-
int fd = hv_open(filepath, flags);
56-
if (fd < 0) {
55+
int fd = -1;
5756
#ifdef OS_WIN
57+
if(wfilepath.empty()) wfilepath = hv::utf8_to_wchar(filepath);
58+
if(_wstat(wfilepath.c_str(), (struct _stat*)&st) != 0) {
59+
param->error = ERR_OPEN_FILE;
60+
return NULL;
61+
}
62+
if(S_ISREG(st.st_mode)) {
63+
fd = _wopen(wfilepath.c_str(), flags);
64+
}else if (S_ISDIR(st.st_mode)) {
5865
// NOTE: open(dir) return -1 on windows
59-
if (!hv_isdir(filepath)) {
60-
param->error = ERR_OPEN_FILE;
61-
return NULL;
62-
}
66+
fd = 0;
67+
}
6368
#else
69+
if(stat(filepath, &st) != 0) {
6470
param->error = ERR_OPEN_FILE;
6571
return NULL;
72+
}
73+
fd = open(filepath, flags);
6674
#endif
75+
if (fd < 0) {
76+
param->error = ERR_OPEN_FILE;
77+
return NULL;
6778
}
6879
defer(if (fd > 0) { close(fd); })
6980
if (fc == NULL) {
70-
struct stat st;
71-
if (fd > 0) {
72-
fstat(fd, &st);
73-
} else {
74-
stat(filepath, &st);
75-
}
7681
if (S_ISREG(st.st_mode) ||
7782
(S_ISDIR(st.st_mode) &&
7883
filepath[strlen(filepath)-1] == '/')) {

0 commit comments

Comments
 (0)