From a19db3a3f74146b5a5c1bc6a03825ab869642f3b Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 29 Jun 2020 12:16:53 +0800 Subject: [PATCH 1/3] :bug: fix bug --- code/buffer/buffer.cpp | 22 +++++++++++----------- code/buffer/buffer.h | 10 ++-------- code/http/httpconn.cpp | 6 +----- code/http/httpconn.h | 1 - code/http/httprequest.cpp | 9 +++++---- code/http/httpresponse.cpp | 10 +++++----- code/http/httpresponse.h | 2 +- code/main.cpp | 7 ------- code/server/webserver.cpp | 2 +- code/timer/heaptimer.cpp | 3 ++- 10 files changed, 28 insertions(+), 44 deletions(-) diff --git a/code/buffer/buffer.cpp b/code/buffer/buffer.cpp index 8893abd..6100295 100644 --- a/code/buffer/buffer.cpp +++ b/code/buffer/buffer.cpp @@ -5,7 +5,7 @@ */ #include "buffer.h" -Buffer::Buffer() : buffer_(INIT_BUFF_SIZE), readPos_(0), writePos_(0) {} +Buffer::Buffer(int initBuffSize) : buffer_(initBuffSize), readPos_(0), writePos_(0) {} size_t Buffer::ReadableBytes() const { return writePos_ - readPos_; @@ -22,10 +22,6 @@ const char* Buffer::Peek() const { return BeginPtr_() + readPos_; } -char* Buffer::Peek(){ - return BeginPtr_() + readPos_; -} - void Buffer::Retrieve(size_t len) { assert(len <= ReadableBytes()); readPos_ += len; @@ -37,6 +33,7 @@ void Buffer::RetrieveUntil(const char* end) { } void Buffer::RetrieveAll() { + bzero(&buffer_[0], buffer_.size()); readPos_ = 0; writePos_ = 0; } @@ -62,16 +59,19 @@ void Buffer::HasWritten(size_t len) { void Buffer::Append(const std::string& str) { Append(str.data(), str.length()); } -void Buffer::Append(const char* data, size_t len) { - EnsureWriteable(len); - std::copy(data, data + len, BeginWrite()); - HasWritten(len); -} void Buffer::Append(const void* data, size_t len) { + assert(data); Append(static_cast(data), len); } +void Buffer::Append(const char* str, size_t len) { + assert(str); + EnsureWriteable(len); + std::copy(str, str + len, BeginWrite()); + HasWritten(len); +} + void Buffer::Append(const Buffer& buff) { Append(buff.Peek(), buff.ReadableBytes()); } @@ -84,7 +84,7 @@ void Buffer::EnsureWriteable(size_t len) { } ssize_t Buffer::ReadFd(int fd, int* saveErrno) { - char buff[MAX_BUFF_SIZE]; + char buff[65535]; struct iovec iov[2]; const size_t writable = WritableBytes(); /* 分散读, 保证数据全部读完 */ diff --git a/code/buffer/buffer.h b/code/buffer/buffer.h index 3691ab5..b340aa5 100644 --- a/code/buffer/buffer.h +++ b/code/buffer/buffer.h @@ -13,11 +13,9 @@ #include //readv #include #include - - class Buffer { public: - Buffer(); + Buffer(int initBuffSize = 1024); ~Buffer() = default; size_t WritableBytes() const; @@ -25,7 +23,6 @@ class Buffer { size_t PrependableBytes() const; const char* Peek() const; - char* Peek(); void EnsureWriteable(size_t len); void HasWritten(size_t len); @@ -39,7 +36,7 @@ class Buffer { char* BeginWrite(); void Append(const std::string& str); - void Append(const char* data, size_t len); + void Append(const char* str, size_t len); void Append(const void* data, size_t len); void Append(const Buffer& buff); @@ -47,9 +44,6 @@ class Buffer { ssize_t WriteFd(int fd, int* Errno); private: - const size_t MAX_BUFF_SIZE = 65535; - const size_t INIT_BUFF_SIZE = 512; - char* BeginPtr_(); const char* BeginPtr_() const; void MakeSpace_(size_t len); diff --git a/code/http/httpconn.cpp b/code/http/httpconn.cpp index 0854200..df15f02 100644 --- a/code/http/httpconn.cpp +++ b/code/http/httpconn.cpp @@ -40,10 +40,6 @@ void HttpConn::Close() { } } -bool HttpConn::IsClose() const { - return isClose_; -}; - int HttpConn::GetFd() const { return fd_; }; @@ -116,7 +112,7 @@ void HttpConn::process() { LOG_DEBUG("Parse code: %d, %s", response_.Code(), request_.path().c_str()); response_.MakeResponse(writeBuff_); - iov_[0].iov_base = writeBuff_.Peek(); + iov_[0].iov_base = const_cast(writeBuff_.Peek()); iov_[0].iov_len = writeBuff_.ReadableBytes(); iovCnt_ = 1; diff --git a/code/http/httpconn.h b/code/http/httpconn.h index ff0ab5c..41a0e65 100644 --- a/code/http/httpconn.h +++ b/code/http/httpconn.h @@ -30,7 +30,6 @@ class HttpConn { ssize_t write(int* saveErrno); void Close(); - bool IsClose() const; int GetFd() const; int GetPort() const; diff --git a/code/http/httprequest.cpp b/code/http/httprequest.cpp index 556c928..714dd25 100644 --- a/code/http/httprequest.cpp +++ b/code/http/httprequest.cpp @@ -29,12 +29,12 @@ bool HttpRequest::IsKeepAlive() const { } bool HttpRequest::parse(Buffer& buff) { - const char* CRLF = "\r\n"; + const char CRLF[] = "\r\n"; if(buff.ReadableBytes() <= 0) { return false; } while(buff.ReadableBytes() && state_ != FINISH) { - char* lineEnd = search(buff.Peek(), buff.BeginWrite(), CRLF, CRLF + 2); + const char* lineEnd = search(buff.Peek(), buff.BeginWriteConst(), CRLF, CRLF + 2); std::string line(buff.Peek(), lineEnd); switch(state_) { @@ -192,7 +192,7 @@ bool HttpRequest::UserVerify(const string &name, const string &pwd, bool isLogin if(!isLogin) { flag = true; } /* 查询用户及密码 */ - snprintf(order, 128, "SELECT username, password FROM user WHERE username='%s' LIMIT 1", name.c_str()); + snprintf(order, 256, "SELECT username, password FROM user WHERE username='%s' LIMIT 1", name.c_str()); LOG_DEBUG("%s", order); if(mysql_query(sql, order)) { @@ -224,7 +224,8 @@ bool HttpRequest::UserVerify(const string &name, const string &pwd, bool isLogin /* 注册行为 且 用户名未被使用*/ if(!isLogin && flag == true) { LOG_DEBUG("regirster!"); - snprintf(order, 128,"INSERT INTO user(username, password) VALUES('%s','%s')", name.c_str(), pwd.c_str()); + bzero(order, 256); + snprintf(order, 256,"INSERT INTO user(username, password) VALUES('%s','%s')", name.c_str(), pwd.c_str()); LOG_DEBUG( "%s", order); if(mysql_query(sql, order)) { LOG_DEBUG( "Insert error!"); diff --git a/code/http/httpresponse.cpp b/code/http/httpresponse.cpp index 4003c1f..6648fd0 100644 --- a/code/http/httpresponse.cpp +++ b/code/http/httpresponse.cpp @@ -74,8 +74,8 @@ void HttpResponse::MakeResponse(Buffer& buff) { else if(!(mmFileStat_.st_mode & S_IROTH)) { code_ = 403; } - else if(code_ <= 200) { - code_ = 200; + else if(code_ == -1) { + code_ = 200; } ErrorHtml_(); AddStateLine_(buff); @@ -87,7 +87,7 @@ char* HttpResponse::File() { return mmFile_; } -int HttpResponse::FileLen() const { +size_t HttpResponse::FileLen() const { return mmFileStat_.st_size; } @@ -114,7 +114,7 @@ void HttpResponse::AddHeader_(Buffer& buff) { buff.Append("Connection: "); if(isKeepAlive_) { buff.Append("Keep-Alive\r\n"); - buff.Append("Keep-Alive: timeout=3000\r\n"); + buff.Append("Keep-Alive: timeout=10000\r\n"); } else{ buff.Append("close\r\n"); } @@ -174,7 +174,7 @@ void HttpResponse::ErrorContent(Buffer& buff, string message) } body += to_string(code_) + " : " + status + "\n"; body += "

" + message + "

"; - body += "
TinyWebServer server"; + body += "
TinyWebServer"; buff.Append("Content-length: " + to_string(body.size()) + "\r\n\r\n"); buff.Append(body); diff --git a/code/http/httpresponse.h b/code/http/httpresponse.h index f5ea6cf..ee80f9f 100644 --- a/code/http/httpresponse.h +++ b/code/http/httpresponse.h @@ -24,7 +24,7 @@ class HttpResponse { void MakeResponse(Buffer& buff); void UnmapFile(); char* File(); - int FileLen() const; + size_t FileLen() const; void ErrorContent(Buffer& buff, std::string message); int Code() const { return code_; } diff --git a/code/main.cpp b/code/main.cpp index 0b35519..a0b44d5 100644 --- a/code/main.cpp +++ b/code/main.cpp @@ -15,10 +15,3 @@ int main() { 1, 6, true, 2, 5000); /* 连接池数量 线程池数量 日志开关 日志等级 日志异步队列容量 */ server.Start(); } - - - - - - - diff --git a/code/server/webserver.cpp b/code/server/webserver.cpp index 4b5b950..505249f 100644 --- a/code/server/webserver.cpp +++ b/code/server/webserver.cpp @@ -18,7 +18,7 @@ WebServer::WebServer( { srcDir_ = getcwd(nullptr, 256); assert(srcDir_); - strcat(srcDir_, "/resources/html"); + strncat(srcDir_, "/resources/html", 16); HttpConn::userCount = 0; HttpConn::srcDir = srcDir_; SqlConnPool::Instance()->Init("localhost", sqlPort, sqlUser, sqlPwd, dbName, connPoolNum); diff --git a/code/timer/heaptimer.cpp b/code/timer/heaptimer.cpp index 0695e69..a299cf2 100644 --- a/code/timer/heaptimer.cpp +++ b/code/timer/heaptimer.cpp @@ -8,7 +8,8 @@ void HeapTimer::siftup_(size_t i) { assert(i >= 0 && i < heap_.size()); size_t j = (i - 1) / 2; - while(j >= 0 && heap_[i] < heap_[j]) { + while(j >= 0) { + if(heap_[j] < heap_[i]) { break; } SwapNode_(i, j); i = j; j = (i - 1) / 2; From 225dd3c38637174f52890843a3c13823c63bf121 Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 29 Jun 2020 12:17:55 +0800 Subject: [PATCH 2/3] :bug: fix log async bug --- code/log/log.cpp | 110 +++++++++++++++++++++++++---------------------- code/log/log.h | 8 ++-- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/code/log/log.cpp b/code/log/log.cpp index 11d3d4f..a6a6956 100644 --- a/code/log/log.cpp +++ b/code/log/log.cpp @@ -12,7 +12,6 @@ Log::Log() { isAsync_ = false; writeThread_ = nullptr; deque_ = nullptr; - toDay_ = 0; fp_ = nullptr; } @@ -31,7 +30,8 @@ Log::~Log() { } } -int Log::GetLevel() const { +int Log::GetLevel() { + lock_guard locker(mtx_); return level_; } @@ -56,7 +56,7 @@ void Log::init(int level = 1, const char* path, const char* suffix, } else { isAsync_ = false; } - buff_.RetrieveAll(); + lineCount_ = 0; time_t timer = time(nullptr); @@ -68,83 +68,89 @@ void Log::init(int level = 1, const char* path, const char* suffix, snprintf(fileName, LOG_NAME_LEN - 1, "%s/%04d_%02d_%02d%s", path_, t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, suffix_); toDay_ = t.tm_mday; - - if(fp_) { fclose(fp_); } - fp_ = fopen(fileName, "a"); - if(fp_ == nullptr) { - mkdir(path_, 0777); + + { + lock_guard locker(mtx_); + buff_.RetrieveAll(); + if(fp_) { + fflush(fp_); + fclose(fp_); + } + fp_ = fopen(fileName, "a"); - } - assert(fp_ != nullptr); + if(fp_ == nullptr) { + mkdir(path_, 0777); + fp_ = fopen(fileName, "a"); + } + assert(fp_ != nullptr); + } + } void Log::write(int level, const char *format, ...) { if(isAsync_) { deque_->flush(); } - struct timeval now = {0, 0}; gettimeofday(&now, nullptr); time_t tSec = now.tv_sec; struct tm *sysTime = localtime(&tSec); struct tm t = *sysTime; - + va_list vaList; + + /* 日志日期 日志行数 */ + if (toDay_ != t.tm_mday || (lineCount_ && (lineCount_ % MAX_LINES == 0))) { unique_lock locker(mtx_); locker.unlock(); - /* 日志日期 日志行数 */ - if (toDay_ != t.tm_mday || (lineCount_ && (lineCount_ % MAX_LINES == 0))) + char newFile[LOG_NAME_LEN]; + char tail[36] = {0}; + snprintf(tail, 36, "%04d_%02d_%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday); + + if (toDay_ != t.tm_mday) { - char newFile[LOG_NAME_LEN]; - char tail[16] = {0}; - snprintf(tail, 20, "%04d_%02d_%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday); - - if (toDay_ != t.tm_mday) - { - snprintf(newFile, LOG_NAME_LEN - 1, "%s/%s%s", path_, tail, suffix_); - toDay_ = t.tm_mday; - lineCount_ = 0; - } - else { - snprintf(newFile, LOG_NAME_LEN - 1, "%s/%s-%d%s", - path_, tail, (lineCount_ / MAX_LINES), suffix_); - } - - locker.lock(); - fflush(fp_); - fclose(fp_); - fp_ = fopen(newFile, "a"); - assert(fp_ != nullptr); + snprintf(newFile, LOG_NAME_LEN - 72, "%s/%s%s", path_, tail, suffix_); + toDay_ = t.tm_mday; + lineCount_ = 0; } - lineCount_++; + else { + snprintf(newFile, LOG_NAME_LEN - 72, "%s/%s-%d%s", path_, tail, (lineCount_ / MAX_LINES), suffix_); + } + + locker.lock(); + fflush(fp_); + fclose(fp_); + fp_ = fopen(newFile, "a"); + assert(fp_ != nullptr); } - va_list vaList; - va_start(vaList, format); { - lock_guard locker(mtx_); + unique_lock locker(mtx_); + lineCount_++; int n = snprintf(buff_.BeginWrite(), 128, "%d-%02d-%02d %02d:%02d:%02d.%06ld ", - t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, - t.tm_hour, t.tm_min, t.tm_sec, now.tv_usec); + t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, + t.tm_hour, t.tm_min, t.tm_sec, now.tv_usec); + buff_.HasWritten(n); - AppendLogLevel_(); - + AppendLogLevelTitle_(level); + + va_start(vaList, format); int m = vsnprintf(buff_.BeginWrite(), buff_.WritableBytes(), format, vaList); + va_end(vaList); + buff_.HasWritten(m); buff_.Append("\n\0", 2); - } - if(isAsync_ || (deque_ && deque_->full())) { - deque_->push_back(buff_.RetrieveAllToStr()); - } - else { - lock_guard locker(mtx_); - fputs(buff_.Peek(), fp_); + if(isAsync_ && deque_ && !deque_->full()) { + deque_->push_back(buff_.RetrieveAllToStr()); + } else { + fputs(buff_.Peek(), fp_); + } buff_.RetrieveAll(); + } - va_end(vaList); } -void Log::AppendLogLevel_() { - switch(level_) { +void Log::AppendLogLevelTitle_(int level) { + switch(level) { case 0: buff_.Append("[debug]: ", 9); break; diff --git a/code/log/log.h b/code/log/log.h index 3026c14..50ff5d1 100644 --- a/code/log/log.h +++ b/code/log/log.h @@ -22,7 +22,7 @@ class Log public: void init(int level, const char* path = "./log", const char* suffix =".log", - int maxQueueCapacity = 800); + int maxQueueCapacity = 1024); static Log* Instance(); static void FlushLogThread(); @@ -30,18 +30,18 @@ class Log void write(int level, const char *format,...); void flush(); - int GetLevel() const; + int GetLevel(); void SetLevel(int level); bool IsOpen() { return isOpen_; } private: Log(); - void AppendLogLevel_(); + void AppendLogLevelTitle_(int level); virtual ~Log(); void AsyncWrite_(); private: - static const int LOG_PATH_LEN = 128; + static const int LOG_PATH_LEN = 256; static const int LOG_NAME_LEN = 256; static const int MAX_LINES = 50000; From b3b132633affee5f46e81cf289357d65a5861757 Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 29 Jun 2020 12:18:21 +0800 Subject: [PATCH 3/3] :white_check_mark: add threadpool and log test --- test/Makefile | 6 +++--- test/{read.me => readme.md} | 0 test/test.cpp | 29 +++++++++++++++++++++++------ 3 files changed, 26 insertions(+), 9 deletions(-) rename test/{read.me => readme.md} (100%) diff --git a/test/Makefile b/test/Makefile index 5ba1453..1e59761 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,13 +1,13 @@ CXX = g++ CFLAGS = -std=c++14 -O2 -Wall -g -TARGET = server +TARGET = test OBJS = ../code/log/*.cpp ../code/pool/*.cpp ../code/timer/*.cpp \ ../code/http/*.cpp ../code/server/*.cpp \ - ../code/buffer/*.cpp ../code/main.cpp + ../code/buffer/*.cpp ../test/test.cpp all: $(OBJS) - $(CXX) $(CFLAGS) $(OBJS) -o ../bin/$(TARGET) -pthread -lmysqlclient + $(CXX) $(CFLAGS) $(OBJS) -o $(TARGET) -pthread -lmysqlclient clean: rm -rf ../bin/$(OBJS) $(TARGET) diff --git a/test/read.me b/test/readme.md similarity index 100% rename from test/read.me rename to test/readme.md diff --git a/test/test.cpp b/test/test.cpp index 1d940b5..f186bc8 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -4,30 +4,47 @@ * @copyleft GPL 2.0 */ #include "../code/log/log.h" +#include "../code/pool/threadpool.h" void TestLog() { int cnt = 0, level = 0; - Log::Instance()->init(level, "./log//testlog1", ".log", 0); + Log::Instance()->init(level, "./testlog1", ".log", 0); for(level = 3; level >= 0; level--) { Log::Instance()->SetLevel(level); - for(int j = 0; j < 100000; j++ ){ + for(int j = 0; j < 10000; j++ ){ for(int i = 0; i < 4; i++) { - LOG_BASE(i,"%s============%d 2222222222 ", "Test", cnt++); + LOG_BASE(i,"%s 111111111 %d ============= ", "Test", cnt++); } } } cnt = 0; - Log::Instance()->init(level, "./log/testlog2", ".log", 5000); + Log::Instance()->init(level, "./testlog2", ".log", 5000); for(level = 0; level < 4; level++) { Log::Instance()->SetLevel(level); - for(int j = 0; j < 100000; j++ ){ + for(int j = 0; j < 10000; j++ ){ for(int i = 0; i < 4; i++) { - LOG_BASE(i,"%s 111111111 %d ============= ", "Test", cnt++); + LOG_BASE(i,"%s 222222222 %d ============= ", "Test", cnt++); } } } } +void ThreadLogTask(int i, int cnt) { + for(int j = 0; j < 10000; j++ ){ + LOG_BASE(i,"PID:[%04d]======= %05d ========= ", gettid(), cnt++); + } +} + +void TestThreadPool() { + Log::Instance()->init(0, "./testThreadpool", ".log", 5000); + ThreadPool threadpool(6); + for(int i = 0; i < 18; i++) { + threadpool.addTask(std::bind(ThreadLogTask, i % 4, i * 10000)); + } + getchar(); +} + int main() { TestLog(); + TestThreadPool(); } \ No newline at end of file