Neon C++: cache Session

Starting a neon Session is slow, in particular when libproxy is
involved (seems to search for proxy servers, which involves a DNS
timeout when none are around). Another delay is opening the TCP
connection and determining which kind of autentication is needed.

For a normal program run there's not much that can be done to speed
this up, but in client-test it helps a lot to reuse an existing
Session instance between different tests. This patch enables that
by keeping one Session instance around and returning that if the new
one has the same parameters.

The Settings pointer is a boost::shared_ptr, but this patch avoids
using it unless the Session is in active use, just in case that a user
wants to merge the settings into a class with a different life time.
This commit is contained in:
Patrick Ohly 2010-11-30 17:35:53 +01:00
parent 9b1a91ee23
commit 46e9bf84e1
3 changed files with 44 additions and 5 deletions

View file

@ -192,11 +192,11 @@ Session::Session(const boost::shared_ptr<Settings> &settings) :
}
}
std::string proxyurl = settings->proxy();
if (proxyurl.empty()) {
m_proxyURL = settings->proxy();
if (m_proxyURL.empty()) {
ne_session_system_proxy(m_session, 0);
} else {
URI proxyuri = URI::parse(proxyurl);
URI proxyuri = URI::parse(m_proxyURL);
ne_session_proxy(m_session, proxyuri.m_host.c_str(), proxyuri.m_port);
}
}
@ -209,6 +209,24 @@ Session::~Session()
ne_sock_exit();
}
boost::shared_ptr<Session> Session::m_cachedSession;
boost::shared_ptr<Session> Session::create(const boost::shared_ptr<Settings> &settings)
{
URI uri = URI::parse(settings->getURL());
if (m_cachedSession &&
m_cachedSession->m_uri == uri &&
m_cachedSession->m_proxyURL == settings->proxy()) {
// reuse existing session with new settings pointer
m_cachedSession->m_settings = settings;
return m_cachedSession;
}
// create new session
m_cachedSession.reset(new Session(settings));
return m_cachedSession;
}
int Session::getCredentials(void *userdata, const char *realm, int attempt, char *username, char *password) throw()
{
try {

View file

@ -132,6 +132,16 @@ struct URI {
* doesn't have a trailing slash.
*/
static std::string normalizePath(const std::string &path, bool collection);
bool operator == (const URI &other) {
return m_scheme == other.m_scheme &&
m_host == other.m_host &&
m_userinfo == other.m_userinfo &&
m_port == other.m_port &&
m_path == other.m_path &&
m_query == other.m_query &&
m_fragment == other.m_fragment;
}
};
/** produce debug string for status, which may be NULL */
@ -142,11 +152,21 @@ std::string Status2String(const ne_status *status);
* Throws transport errors for fatal problems.
*/
class Session {
public:
/**
* @param settings must provide information about settings on demand
*/
Session(const boost::shared_ptr<Settings> &settings);
static boost::shared_ptr<Session> m_cachedSession;
public:
/**
* Create or reuse Session instance.
*
* One Session instance is kept alive throughout the life of the process,
* to reuse proxy information (libproxy has a considerably delay during
* initialization) and HTTP connection/authentication.
*/
static boost::shared_ptr<Session> create(const boost::shared_ptr<Settings> &settings);
~Session();
/** ne_options2() */
@ -194,6 +214,7 @@ class Session {
boost::shared_ptr<Settings> m_settings;
ne_session *m_session;
URI m_uri;
std::string m_proxyURL;
time_t m_lastRequestEnd;
/** ne_set_server_auth() callback */

View file

@ -127,7 +127,7 @@ void WebDAVSource::open()
{
SE_LOG_DEBUG(NULL, NULL, "using libneon %s with %s",
ne_version_string(), Neon::features().c_str());
m_session.reset(new Neon::Session(m_settings));
m_session = Neon::Session::create(m_settings);
// Start by checking server capabilities.
// Verifies URL.