diff options
author | ipkn <ipknhama@gmail.com> | 2014-05-02 01:17:49 -0400 |
---|---|---|
committer | ipkn <ipknhama@gmail.com> | 2014-05-02 01:17:49 -0400 |
commit | 81bd1e1fb6cb2a74c4e372410fb419cfc94991e0 (patch) | |
tree | fecebb2f7887cf73f6e6aa1d5ce9ee1d7d3cc57c | |
parent | f8893eb138eae88f35ba752221a02b318d275364 (diff) | |
download | crow-81bd1e1fb6cb2a74c4e372410fb419cfc94991e0.tar.gz crow-81bd1e1fb6cb2a74c4e372410fb419cfc94991e0.zip |
caching datetime string for Date header
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | datetime.h | 8 | ||||
-rw-r--r-- | example.cpp | 1 | ||||
-rw-r--r-- | http_connection.h | 68 | ||||
-rw-r--r-- | http_server.h | 21 | ||||
-rw-r--r-- | routing.h | 6 |
6 files changed, 72 insertions, 40 deletions
@@ -1,6 +1,6 @@ all: covtest example -example: example.cpp crow.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h json.h - g++ -Wall -g -O3 -std=c++11 -o example example.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/ +example: example.cpp crow.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h json.h datetime.h + g++ -Wall -g -O3 -std=c++11 -o example example.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -ltcmalloc_minimal -I http-parser/ test: covtest @@ -10,11 +10,11 @@ runtest: example python test.py || exit 0 pkill example -unittest: unittest.cpp routing.h +unittest: unittest.cpp routing.h utility.h crow.h http_server.h http_connection.h parser.h http_response.h common.h json.h datetime.h g++ -Wall -g -std=c++11 -o unittest unittest.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/ ./unittest -covtest: unittest.cpp routing.h utility.h crow.h http_server.h http_connection.h parser.h http_response.h common.h json.h +covtest: unittest.cpp routing.h utility.h crow.h http_server.h http_connection.h parser.h http_response.h common.h json.h datetime.h g++ -Wall -g -std=c++11 -o covtest --coverage unittest.cpp http-parser/http_parser.c -pthread -lboost_system -lboost_thread -I http-parser/ ./covtest gcov -r unittest.cpp @@ -23,12 +23,12 @@ namespace crow // return datetime string std::string str() { + static const std::locale locale_(std::locale::classic(), new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT") ); std::string result; - boost::local_time::local_time_facet* lf(new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT")); try { std::stringstream ss; - ss.imbue(std::locale(ss.getloc(), lf)); + ss.imbue(locale_); ss << m_dt; result = ss.str(); } @@ -59,9 +59,9 @@ namespace crow // parse datetime string void parse(const std::string& dt) { - boost::local_time::local_time_input_facet* lif(new boost::local_time::local_time_input_facet("%a, %d %b %Y %H:%M:%S GMT")); + static const std::locale locale_(std::locale::classic(), new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT") ); std::stringstream ss(dt); - ss.imbue(std::locale(std::locale::classic(), lif)); + ss.imbue(locale_); ss >> m_dt; } diff --git a/example.cpp b/example.cpp index 92bc19c..4af7c75 100644 --- a/example.cpp +++ b/example.cpp @@ -54,5 +54,6 @@ int main() }); app.port(18080) + .multithreaded() .run(); } diff --git a/http_connection.h b/http_connection.h index 4456bb1..99b1fb3 100644 --- a/http_connection.h +++ b/http_connection.h @@ -1,15 +1,16 @@ #pragma once #include <boost/asio.hpp> #include <http_parser.h> -#include <atomic> #include <boost/asio.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/array.hpp> #include <boost/lexical_cast.hpp> +#include <atomic> +#include <chrono> +#include "datetime.h" #include "parser.h" #include "http_response.h" -#include "datetime.h" namespace crow { @@ -19,7 +20,11 @@ namespace crow class Connection { public: - Connection(tcp::socket&& socket, Handler* handler, const std::string& server_name) : socket_(std::move(socket)), handler_(handler), parser_(this), server_name_(server_name) + Connection(tcp::socket&& socket, Handler* handler, const std::string& server_name) + : socket_(std::move(socket)), + handler_(handler), + parser_(this), + server_name_(server_name) { } @@ -71,7 +76,7 @@ namespace crow #ifdef CROW_ENABLE_LOGGING std::cerr << "HTTP/" << parser_.http_major << "." << parser_.http_minor << ' '; std::cerr << method_name(req.method); - std::cerr << " " << res.code << std::endl; + std::cerr << " " << res.code << ' ' <<close_connection_<<std::endl; #endif static std::string seperator = ": "; @@ -116,27 +121,25 @@ namespace crow if (!has_content_length) { - auto ret = res.headers.emplace("Content-Length", boost::lexical_cast<std::string>(res.body.size())); - buffers_.emplace_back(ret.first->first.data(), ret.first->first.size()); - buffers_.emplace_back(seperator.data(), seperator.size()); - buffers_.emplace_back(ret.first->second.data(), ret.first->second.size()); + content_length_ = boost::lexical_cast<std::string>(res.body.size()); + static std::string content_length_tag = "Content-Length: "; + buffers_.emplace_back(content_length_tag.data(), content_length_tag.size()); + buffers_.emplace_back(content_length_.data(), content_length_.size()); buffers_.emplace_back(crlf.data(), crlf.size()); } if (!has_server) { - auto ret = res.headers.emplace("Server", server_name_); - buffers_.emplace_back(ret.first->first.data(), ret.first->first.size()); - buffers_.emplace_back(seperator.data(), seperator.size()); - buffers_.emplace_back(ret.first->second.data(), ret.first->second.size()); + static std::string server_tag = "Server: "; + buffers_.emplace_back(server_tag.data(), server_tag.size()); + buffers_.emplace_back(server_name_.data(), server_name_.size()); buffers_.emplace_back(crlf.data(), crlf.size()); } if (!has_date) { - std::string date_str = DateTime().str(); - auto ret = res.headers.emplace("Date", date_str); - buffers_.emplace_back(ret.first->first.data(), ret.first->first.size()); - buffers_.emplace_back(seperator.data(), seperator.size()); - buffers_.emplace_back(ret.first->second.data(), ret.first->second.size()); + static std::string date_tag = "Date: "; + date_str_ = get_cached_date_str(); + buffers_.emplace_back(date_tag.data(), date_tag.size()); + buffers_.emplace_back(date_str_.data(), date_str_.size()); buffers_.emplace_back(crlf.data(), crlf.size()); } @@ -147,28 +150,38 @@ namespace crow } private: + static std::string get_cached_date_str() + { + using namespace std::chrono; + thread_local auto last = system_clock::now(); + thread_local std::string date_str = DateTime().str(); + + if (system_clock::now() - last >= seconds(1)) + { + last = system_clock::now(); + date_str = DateTime().str(); + } + return date_str; + } + void do_read() { life_++; socket_.async_read_some(boost::asio::buffer(buffer_), [this](boost::system::error_code ec, std::size_t bytes_transferred) { + bool do_complete_task = false; if (!ec) { bool ret = parser_.feed(buffer_.data(), bytes_transferred); if (ret) do_read(); else - { - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both); - socket_.close(); - - life_--; - if ((int)life_ == 0) - delete this; - } + do_complete_task = true; } else + do_complete_task = true; + if (do_complete_task) { parser_.done(); socket_.close(); @@ -217,10 +230,13 @@ namespace crow HTTPParser<Connection> parser_; response res; - std::atomic<int> life_; + int life_; bool close_connection_ = false; const std::string& server_name_; std::vector<boost::asio::const_buffer> buffers_; + + std::string content_length_; + std::string date_str_; }; } diff --git a/http_server.h b/http_server.h index e4893ad..387f2e5 100644 --- a/http_server.h +++ b/http_server.h @@ -2,8 +2,10 @@ #include <boost/asio.hpp> #include <stdint.h> +#include <atomic> #include "http_connection.h" +#include "datetime.h" // TEST #include <iostream> @@ -17,7 +19,11 @@ namespace crow { public: Server(Handler* handler, uint16_t port, uint16_t concurrency = 1) - : acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), socket_(io_service_), handler_(handler), concurrency_(concurrency) + : acceptor_(io_service_, tcp::endpoint(asio::ip::address(), port)), + socket_(io_service_), + signals_(io_service_, SIGINT, SIGTERM), + handler_(handler), + concurrency_(concurrency) { do_accept(); } @@ -29,6 +35,12 @@ namespace crow v.push_back( std::async(std::launch::async, [this]{io_service_.run();}) ); + + signals_.async_wait( + [&](const boost::system::error_code& error, int signal_number){ + io_service_.stop(); + }); + } void stop() @@ -52,8 +64,11 @@ namespace crow asio::io_service io_service_; tcp::acceptor acceptor_; tcp::socket socket_; + boost::asio::signal_set signals_; + Handler* handler_; - uint16_t concurrency_ = 1; - std::string server_name_ = "Flask++/0.1"; + + uint16_t concurrency_ = {1}; + std::string server_name_ = "Crow/0.1"; }; } @@ -27,7 +27,6 @@ namespace crow protected: - friend class Router; }; template <typename ... Args> @@ -219,6 +218,7 @@ namespace crow static const int pos = Pos; }; + friend class Router; }; class Trie @@ -323,7 +323,7 @@ public: if (ret.first && (!found || found > ret.first)) { found = ret.first; - match_params = ret.second; + match_params = std::move(ret.second); } }; @@ -585,7 +585,7 @@ public: if (rule_index >= rules_.size()) throw std::runtime_error("Trie internal structure corrupted!"); #ifdef CROW_ENABLE_LOGGING - std::cerr << req.url << ' ' << rules_[rule_index]->rule_ << std::endl; + std::cerr << req.url << ' ' << ((TaggedRule<>*)rules_[rule_index].get())->rule_ << std::endl; #endif return rules_[rule_index]->handle(req, found.second); } |