aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoripkn <ipknhama@gmail.com>2014-05-02 01:17:49 -0400
committeripkn <ipknhama@gmail.com>2014-05-02 01:17:49 -0400
commit81bd1e1fb6cb2a74c4e372410fb419cfc94991e0 (patch)
treefecebb2f7887cf73f6e6aa1d5ce9ee1d7d3cc57c
parentf8893eb138eae88f35ba752221a02b318d275364 (diff)
downloadcrow-81bd1e1fb6cb2a74c4e372410fb419cfc94991e0.tar.gz
crow-81bd1e1fb6cb2a74c4e372410fb419cfc94991e0.zip
caching datetime string for Date header
-rw-r--r--Makefile8
-rw-r--r--datetime.h8
-rw-r--r--example.cpp1
-rw-r--r--http_connection.h68
-rw-r--r--http_server.h21
-rw-r--r--routing.h6
6 files changed, 72 insertions, 40 deletions
diff --git a/Makefile b/Makefile
index bd50a3a..508316d 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/datetime.h b/datetime.h
index 24fd3c4..0a47379 100644
--- a/datetime.h
+++ b/datetime.h
@@ -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";
};
}
diff --git a/routing.h b/routing.h
index ef7974e..e69a52b 100644
--- a/routing.h
+++ b/routing.h
@@ -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);
}