Skip to content
Browse files

Add retry support to HttpServerIDMap.

  • Loading branch information...
1 parent de3d512 commit 91edf7bf3a745fd4056406ea2d47ffe0aac95a05 @ewencp ewencp committed Aug 12, 2012
View
95 libcore/plugins/http/HttpServerIDMap.cpp
@@ -14,79 +14,89 @@ using namespace Sirikata::Transfer;
HttpServerIDMap::HttpServerIDMap(
Context* ctx,
const String& internal_host, const String& internal_service, const String& internal_path,
- const String& external_host, const String& external_service, const String& external_path)
+ const String& external_host, const String& external_service, const String& external_path,
+ uint32 retries)
: ServerIDMap(ctx),
mInternalHost(internal_host),
mInternalService(internal_service),
mInternalPath(internal_path),
mExternalHost(external_host),
mExternalService(external_service),
- mExternalPath(external_path)
+ mExternalPath(external_path),
+ mRetries(retries)
{
}
void HttpServerIDMap::lookupInternal(const ServerID& sid, Address4LookupCallback cb) {
startLookup(
- sid, cb,
- mInternalHost, mInternalService, mInternalPath
+ RequestInfo(
+ sid, cb,
+ mInternalHost, mInternalService, mInternalPath
+ ),
+ 0
);
}
void HttpServerIDMap::lookupExternal(const ServerID& sid, Address4LookupCallback cb) {
startLookup(
- sid, cb,
- mExternalHost, mExternalService, mExternalPath
+ RequestInfo(
+ sid, cb,
+ mExternalHost, mExternalService, mExternalPath
+ ),
+ 0
);
}
void HttpServerIDMap::lookupRandomExternal(Address4LookupCallback cb) {
// NullServerID indicates pick randomly
startLookup(
- NullServerID, cb,
- mExternalHost, mExternalService, mExternalPath
+ RequestInfo(
+ NullServerID, cb,
+ mExternalHost, mExternalService, mExternalPath
+ ),
+ 0
);
}
void HttpServerIDMap::startLookup(
- const ServerID& sid, Address4LookupCallback cb,
- const String& host,
- const String& service,
- const String& path
+ const RequestInfo& ri,
+ const uint32 retry
){
- Network::Address addr(host, service);
+ Network::Address addr(ri.host, ri.service);
HttpManager::Headers request_headers;
- request_headers["Host"] = host;
+ request_headers["Host"] = ri.host;
HttpManager::QueryParameters query_params;
// Empty query params if 0, i.e. random, is requested
- if (sid != NullServerID)
- query_params["server"] = boost::lexical_cast<String>(sid);
+ if (ri.sid != NullServerID)
+ query_params["server"] = boost::lexical_cast<String>(ri.sid);
HttpManager::getSingleton().get(
- addr, path,
- std::tr1::bind(&HttpServerIDMap::finishLookup, this, sid, cb, _1, _2, _3),
+ addr, ri.path,
+ std::tr1::bind(&HttpServerIDMap::finishLookup, this, ri, retry, _1, _2, _3),
request_headers, query_params
);
}
void HttpServerIDMap::finishLookup(
- const ServerID& sid, Address4LookupCallback cb,
+ const RequestInfo& ri,
+ const uint32 retry,
HttpManager::HttpResponsePtr response,
HttpManager::ERR_TYPE error,
const boost::system::error_code &boost_error)
{
// Error conditions
if (error != HttpManager::SUCCESS) {
- SILOG(http-serverid-map, error, "Failed to lookup server " << sid);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Failed to lookup server " << ri.sid);
return;
}
String resp = response->getData()->asString();
// Check response code for failure
if (response->getStatusCode() >= 400) {
- SILOG(http-serverid-map, error, "Request to HTTP server failed when looking up server " << sid << ": " << resp);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Request to HTTP server failed when looking up server " << ri.sid << ": " << resp);
return;
}
@@ -101,34 +111,34 @@ void HttpServerIDMap::finishLookup(
String::size_type line_split_pos = resp.find("\n");
String::size_type split_pos = resp.find(":");
if (line_split_pos == String::npos || split_pos == String::npos) {
- SILOG(http-serverid-map, error, "Couldn't parse response for server lookup " << sid << ": " << resp);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Couldn't parse response for server lookup " << ri.sid << ": " << resp);
return;
}
ServerID resolved_sid = boost::lexical_cast<ServerID>( resp.substr(0,line_split_pos) );
- assert(resolved_sid == sid || sid == NullServerID);
+ assert(resolved_sid == ri.sid || ri.sid == NullServerID);
Network::Address retval(
resp.substr(line_split_pos+1,split_pos-line_split_pos-1),
resp.substr(split_pos+1)
);
- mContext->ioService->post(std::tr1::bind(cb, resolved_sid, retval), "HttpServerIDMap::finishLookup");
+ mContext->ioService->post(std::tr1::bind(ri.cb, resolved_sid, retval), "HttpServerIDMap::finishLookup");
}
else if (content_type == "application/json") {
namespace json = json_spirit;
json::Value json_resp;
if (!json::read(resp, json_resp)) {
- SILOG(http-serverid-map, error, "Couldn't parse response for server lookup " << sid << ": " << resp);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Couldn't parse response for server lookup " << ri.sid << ": " << resp);
return;
}
if (!json_resp.contains("server") ||
!json_resp.contains("host") ||
!json_resp.contains("port"))
{
- SILOG(http-serverid-map, error, "Response from server doesn't contain all required fields: " << resp);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Response from server doesn't contain all required fields: " << resp);
return;
}
@@ -138,12 +148,29 @@ void HttpServerIDMap::finishLookup(
ServerID resolved_sid = boost::lexical_cast<ServerID>(server);
Network::Address retval( host, port_str );
- mContext->ioService->post(std::tr1::bind(cb, resolved_sid, retval), "HttpServerIDMap::finishLookup");
+ mContext->ioService->post(std::tr1::bind(ri.cb, resolved_sid, retval), "HttpServerIDMap::finishLookup");
}
else {
- SILOG(http-serverid-map, error, "Unknown content type for HTTP server map response: " << content_type);
- mContext->ioService->post(std::tr1::bind(cb, sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ if (!retryOrFail(ri, retry))
+ SILOG(http-serverid-map, error, "Unknown content type for HTTP server map response: " << content_type);
return;
}
}
+
+bool HttpServerIDMap::retryOrFail(
+ const RequestInfo& ri,
+ const uint32 retry
+) {
+ if (retry < mRetries) {
+ mContext->ioService->post(
+ Duration::seconds(pow(2.0, (float)retry)),
+ std::tr1::bind(&HttpServerIDMap::startLookup, this, ri, retry+1)
+ );
+ return true;
+ }
+
+ mContext->ioService->post(std::tr1::bind(ri.cb, ri.sid, Address4::Null), "HttpServerIDMap::finishLookup");
+ return false;
+}
+
}//end namespace sirikata
View
35 libcore/plugins/http/HttpServerIDMap.hpp
@@ -24,22 +24,45 @@ class HttpServerIDMap : public ServerIDMap {
const String mExternalService;
const String mExternalPath;
+ const uint32 mRetries;
+
+ struct RequestInfo {
+ RequestInfo(
+ const ServerID& _sid, Address4LookupCallback _cb,
+ const String& _host,
+ const String& _service,
+ const String& _path)
+ : sid(_sid), cb(_cb), host(_host), service(_service), path(_path)
+ {}
+
+ const ServerID sid;
+ const Address4LookupCallback cb;
+ const String host;
+ const String service;
+ const String path;
+ };
+
void startLookup(
- const ServerID& sid, Address4LookupCallback cb,
- const String& host,
- const String& service,
- const String& path
+ const RequestInfo& ri,
+ const uint32 retry
);
void finishLookup(
- const ServerID& sid, Address4LookupCallback cb,
+ const RequestInfo& ri,
+ const uint32 retry,
Transfer::HttpManager::HttpResponsePtr response,
Transfer::HttpManager::ERR_TYPE error,
const boost::system::error_code &boost_error);
+ // Returns true if retrying. If returns false, caller should report error.
+ bool retryOrFail(
+ const RequestInfo& ri,
+ const uint32 retry
+ );
public:
HttpServerIDMap(
Context* ctx,
const String& internal_host, const String& internal_service, const String& internal_path,
- const String& external_host, const String& external_service, const String& external_path
+ const String& external_host, const String& external_service, const String& external_path,
+ uint32 retries
);
virtual ~HttpServerIDMap() {}
View
7 libcore/plugins/http/PluginInterface.cpp
@@ -50,6 +50,8 @@ static void InitPluginServermapOptions() {
new Sirikata::OptionValue("internal-path", "/internal", Sirikata::OptionValueType<String>(), "Path to send internal lookup requests to"),
new Sirikata::OptionValue("external-path", "/external", Sirikata::OptionValueType<String>(), "Path to send external lookup requests to"),
+ new Sirikata::OptionValue("retries", "5", Sirikata::OptionValueType<uint32>(), "Number of retries to perform on a lookup before giving up and assuming the request is invalid."),
+
NULL);
}
@@ -70,10 +72,13 @@ static ServerIDMap* createHttpServerIDMap(Context* ctx, const String& args) {
String internal_path = optionsSet->referenceOption("internal-path")->as<String>();
String external_path = optionsSet->referenceOption("external-path")->as<String>();
+ uint32 retries = optionsSet->referenceOption("retries")->as<uint32>();
+
return new HttpServerIDMap(
ctx,
internal_host, internal_service, internal_path,
- external_host, external_service, external_path
+ external_host, external_service, external_path,
+ retries
);
}

0 comments on commit 91edf7b

Please sign in to comment.
Something went wrong with that request. Please try again.