Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use single curl session for Volkszaehler
- Loading branch information
Showing
10 changed files
with
222 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef __CURL_SESSION_PROVIDER_ | ||
#define __CURL_SESSION_PROVIDER_ | ||
|
||
#include <string> | ||
#include <map> | ||
#include <pthread.h> | ||
#include <curl/curl.h> | ||
|
||
class CurlSessionProvider | ||
{ | ||
public: | ||
// non thread safe: | ||
CurlSessionProvider(); | ||
~CurlSessionProvider(); | ||
|
||
// thread-safe functions: | ||
CURL *get_easy_session(std::string key, int timeout=0); // this is intended to block if the handle for the current key is in use and single_session_per_key | ||
void return_session(std::string key, CURL *&); // return a handle. this unblocks another pending request for this key if single_session_per_key | ||
bool inUse(std::string key); // check whether a key is in use (does not guarantee that get... will not block) | ||
|
||
protected: | ||
class CurlUsage | ||
{ | ||
public: | ||
CurlUsage() : eh(0), inUse(false) { mutex = PTHREAD_MUTEX_INITIALIZER; }; | ||
CURL *eh; | ||
bool inUse; | ||
pthread_mutex_t mutex; | ||
}; | ||
|
||
typedef std::map<std::string, CurlUsage>::iterator map_it; | ||
typedef std::map<std::string, CurlUsage>::const_iterator cmap_it; | ||
|
||
std::map<std::string, CurlUsage> _easy_handle_map; | ||
private: | ||
pthread_mutex_t _map_mutex; | ||
}; | ||
|
||
// var to a global/single instance. needs to be initialzed e.g. in main() | ||
extern CurlSessionProvider *curlSessionProvider; | ||
|
||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* CurlSessionProvider - provides one curl session (easy handle) for a key | ||
* | ||
* @author Matthias Behr <mbehr@mcbehr.de> | ||
* @copyright Copyright (c) 2015, The volkszaehler.org project | ||
* @package vzlogger | ||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License | ||
*/ | ||
|
||
#include <assert.h> | ||
#include "CurlSessionProvider.hpp" | ||
|
||
CurlSessionProvider::CurlSessionProvider() | ||
{ | ||
_map_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
curl_global_init(CURL_GLOBAL_ALL); | ||
} | ||
|
||
CurlSessionProvider::~CurlSessionProvider() | ||
{ | ||
// curl_easy_cleanup for each CURL* | ||
pthread_mutex_lock(&_map_mutex); | ||
for (map_it it = _easy_handle_map.begin(); it!=_easy_handle_map.end(); ++it) | ||
{ | ||
CurlUsage cu = (*it).second; | ||
curl_easy_cleanup(cu.eh); | ||
} | ||
curl_global_cleanup(); | ||
|
||
pthread_mutex_unlock(&_map_mutex); | ||
pthread_mutex_destroy(&_map_mutex); | ||
} | ||
|
||
// thread-safe functions: | ||
CURL *CurlSessionProvider::get_easy_session(std::string key, int timeout) // this is intended to block if the handle for the current key is in use and single_session_per_key | ||
{ | ||
CURL *toRet=0; | ||
// thread safe lock here to access the map: | ||
assert( 0 == pthread_mutex_lock(&_map_mutex)); | ||
map_it it = _easy_handle_map.find(key); | ||
if (it!= _easy_handle_map.end()){ | ||
CurlUsage &cur = (*it).second; | ||
pthread_mutex_unlock(&_map_mutex); // we unlock here already but access the current element anyhow assuming an insert doesnt invalidate the reference | ||
assert(0 == pthread_mutex_lock(&cur.mutex)); | ||
assert(!cur.inUse); | ||
cur.inUse = true; | ||
toRet = cur.eh; | ||
} else { | ||
// create new one: | ||
CurlUsage cu; | ||
cu.eh = curl_easy_init(); | ||
cu.inUse=true; | ||
pthread_mutex_lock(&cu.mutex); | ||
_easy_handle_map.insert(std::make_pair(key, cu)); | ||
toRet = cu.eh; | ||
} | ||
pthread_mutex_unlock(&_map_mutex); | ||
|
||
return toRet; | ||
} | ||
|
||
void CurlSessionProvider::return_session(std::string key, CURL *&eh) // return a handle. this unblocks another pending request for this key if single_session_per_key | ||
{ | ||
// thread safe lock here: | ||
assert( 0 == pthread_mutex_lock(&_map_mutex)); | ||
CurlUsage &cu = _easy_handle_map[key]; | ||
assert(eh == cu.eh); | ||
eh=0; | ||
cu.inUse = false; | ||
pthread_mutex_unlock(&cu.mutex); | ||
pthread_mutex_unlock(&_map_mutex); | ||
} | ||
|
||
bool CurlSessionProvider::inUse(std::string key) | ||
{ | ||
pthread_mutex_lock(&_map_mutex); | ||
cmap_it it = _easy_handle_map.find(key); | ||
if (it != _easy_handle_map.end()){ | ||
pthread_mutex_unlock(&_map_mutex); | ||
return (*it).second.inUse; | ||
} | ||
pthread_mutex_unlock(&_map_mutex); | ||
return false; | ||
} | ||
|
||
// global var: | ||
CurlSessionProvider *curlSessionProvider=0; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#include "gtest/gtest.h" | ||
|
||
#include "CurlSessionProvider.hpp" | ||
|
||
TEST(CurlSessionProvider, init) | ||
{ | ||
ASSERT_EQ(0, curlSessionProvider); | ||
curlSessionProvider = new CurlSessionProvider(); | ||
|
||
delete curlSessionProvider; | ||
curlSessionProvider = 0; | ||
|
||
} | ||
|
||
TEST(CurlSessionProvider, single1) | ||
{ | ||
curlSessionProvider = new CurlSessionProvider(); | ||
|
||
ASSERT_FALSE( curlSessionProvider->inUse("1")); | ||
|
||
CURL *eh = curlSessionProvider->get_easy_session("1"); | ||
ASSERT_TRUE(0 != eh); | ||
ASSERT_TRUE( curlSessionProvider->inUse("1")); | ||
curlSessionProvider->return_session("1", eh); | ||
ASSERT_EQ(0, eh); | ||
ASSERT_FALSE( curlSessionProvider->inUse("1")); | ||
|
||
// 2nd try: | ||
eh = curlSessionProvider->get_easy_session("1"); | ||
ASSERT_TRUE(0 != eh); | ||
ASSERT_TRUE( curlSessionProvider->inUse("1")); | ||
curlSessionProvider->return_session("1", eh); | ||
ASSERT_EQ(0, eh); | ||
ASSERT_FALSE( curlSessionProvider->inUse("1")); | ||
|
||
|
||
delete curlSessionProvider; | ||
curlSessionProvider = 0; | ||
|
||
// TODO create that that's spanws a thread and tests blocking on a shared session | ||
} |