nghttp: Assign different priority according to the resource type

This commit is contained in:
Tatsuhiro Tsujikawa 2013-09-29 18:58:46 +09:00
parent 31ae1fe660
commit 8e9f08f81d
3 changed files with 65 additions and 32 deletions

View File

@ -60,6 +60,20 @@ const char* get_attr(const xmlChar **attrs, const char *name)
}
} // namespace
namespace {
void add_link(ParserData *parser_data, const char *uri, RequestPriority pri)
{
auto u = xmlBuildURI(reinterpret_cast<const xmlChar*>(uri),
reinterpret_cast<const xmlChar*>
(parser_data->base_uri.c_str()));
if(u) {
parser_data->links.push_back(std::make_pair(reinterpret_cast<char*>(u),
pri));
free(u);
}
}
} // namespace
namespace {
void start_element_func
(void* user_data,
@ -70,29 +84,26 @@ void start_element_func
if(util::strieq(reinterpret_cast<const char*>(name), "link")) {
const char *rel_attr = get_attr(attrs, "rel");
const char *href_attr = get_attr(attrs, "href");
if((util::strieq(rel_attr, "shortcut icon") ||
util::strieq(rel_attr, "stylesheet")) &&
href_attr) {
xmlChar *u = xmlBuildURI(reinterpret_cast<const xmlChar*>(href_attr),
reinterpret_cast<const xmlChar*>
(parser_data->base_uri.c_str()));
if(u) {
parser_data->links.push_back(reinterpret_cast<char*>(u));
free(u);
}
if(!href_attr) {
return;
}
} else if(util::strieq(reinterpret_cast<const char*>(name), "img") ||
util::strieq(reinterpret_cast<const char*>(name), "script")) {
if(util::strieq(rel_attr, "shortcut icon")) {
add_link(parser_data, href_attr, REQ_PRI_LOWEST);
} else if(util::strieq(rel_attr, "stylesheet")) {
add_link(parser_data, href_attr, REQ_PRI_MEDIUM);
}
} else if(util::strieq(reinterpret_cast<const char*>(name), "img")) {
const char *src_attr = get_attr(attrs, "src");
if(src_attr) {
xmlChar *u = xmlBuildURI(reinterpret_cast<const xmlChar*>(src_attr),
reinterpret_cast<const xmlChar*>
(parser_data->base_uri.c_str()));
if(u) {
parser_data->links.push_back(reinterpret_cast<char*>(u));
free(u);
}
if(!src_attr) {
return;
}
add_link(parser_data, src_attr, REQ_PRI_LOWEST);
} else if(util::strieq(reinterpret_cast<const char*>(name), "script")) {
const char *src_attr = get_attr(attrs, "src");
if(!src_attr) {
return;
}
add_link(parser_data, src_attr, REQ_PRI_MEDIUM);
}
}
} // namespace
@ -168,7 +179,8 @@ int HtmlParser::parse_chunk_internal(const char *chunk, size_t size,
}
}
const std::vector<std::string>& HtmlParser::get_links() const
const std::vector<std::pair<std::string, RequestPriority>>&
HtmlParser::get_links() const
{
return parser_data_.links;
}

View File

@ -36,9 +36,16 @@
namespace nghttp2 {
enum RequestPriority {
REQ_PRI_HIGH = 0,
REQ_PRI_MEDIUM = 1,
REQ_PRI_LOW = 2,
REQ_PRI_LOWEST = 3
};
struct ParserData {
std::string base_uri;
std::vector<std::string> links;
std::vector<std::pair<std::string, RequestPriority>> links;
ParserData(const std::string& base_uri);
};
@ -47,7 +54,8 @@ public:
HtmlParser(const std::string& base_uri);
~HtmlParser();
int parse_chunk(const char *chunk, size_t size, int fin);
const std::vector<std::string>& get_links() const;
const std::vector<std::pair<std::string, RequestPriority>>&
get_links() const;
void clear_links();
private:
int parse_chunk_internal(const char *chunk, size_t size, int fin);

View File

@ -248,16 +248,17 @@ struct Request {
const nghttp2_data_provider *data_prd;
int64_t data_length;
int64_t data_offset;
int32_t pri;
// Recursion level: 0: first entity, 1: entity linked from first entity
int level;
RequestStat stat;
std::string status;
Request(const std::string& uri, const http_parser_url &u,
const nghttp2_data_provider *data_prd, int64_t data_length,
int level = 0)
int32_t pri, int level = 0)
: uri(uri), u(u),
inflater(nullptr), html_parser(nullptr), data_prd(data_prd),
data_length(data_length), data_offset(0),
data_length(data_length), data_offset(0), pri(pri),
level(level)
{}
@ -794,6 +795,7 @@ struct HttpClient {
bool add_request(const std::string& uri,
const nghttp2_data_provider *data_prd,
int64_t data_length,
int32_t pri,
int level = 0)
{
http_parser_url u;
@ -807,7 +809,7 @@ struct HttpClient {
path_cache.insert(uri);
}
reqvec.push_back(util::make_unique<Request>(uri, u, data_prd,
data_length, level));
data_length, pri, level));
return true;
}
}
@ -930,12 +932,23 @@ void submit_request(HttpClient *client,
}
nv[pos] = nullptr;
int r = nghttp2_submit_request(client->session, config.pri,
int r = nghttp2_submit_request(client->session, req->pri,
nv.get(), req->data_prd, req);
assert(r == 0);
}
} // namespace
namespace {
int32_t adjust_pri(int32_t base_pri, int32_t rel_pri)
{
if((int32_t)NGHTTP2_PRI_LOWEST - rel_pri < base_pri) {
return NGHTTP2_PRI_LOWEST;
} else {
return base_pri + rel_pri;
}
}
} // namespace
namespace {
void update_html_parser(HttpClient *client, Request *req,
const uint8_t *data, size_t len, int fin)
@ -945,16 +958,16 @@ void update_html_parser(HttpClient *client, Request *req,
}
req->update_html_parser(data, len, fin);
for(size_t i = 0; i < req->html_parser->get_links().size(); ++i) {
const auto& raw_uri = req->html_parser->get_links()[i];
auto uri = strip_fragment(raw_uri.c_str());
for(auto& p : req->html_parser->get_links()) {
auto uri = strip_fragment(p.first.c_str());
http_parser_url u;
if(http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_SCHEMA) &&
fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) &&
porteq(uri.c_str(), u, req->uri.c_str(), req->u)) {
int32_t pri = adjust_pri(req->pri, p.second);
// No POST data for assets
if ( client->add_request(uri, nullptr, 0, req->level+1) ) {
if ( client->add_request(uri, nullptr, 0, pri, req->level+1) ) {
submit_request(client, config.headers,
client->reqvec.back().get());
}
@ -1344,7 +1357,7 @@ int communicate(const std::string& scheme, const std::string& host,
for(auto req : requests) {
for(int i = 0; i < config.multiply; ++i) {
client.add_request(std::get<0>(req), std::get<1>(req),
std::get<2>(req));
std::get<2>(req), config.pri);
}
}
client.update_hostport();