Skip to content

Commit e9b7659

Browse files
author
Sebastiano Merlino
committed
Changed cache interface in order to simplify management
1 parent 4ff57b2 commit e9b7659

File tree

4 files changed

+172
-24
lines changed

4 files changed

+172
-24
lines changed

src/http_response.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,15 @@ using namespace std;
2929
namespace httpserver
3030
{
3131

32+
void unlock_on_close::do_action()
33+
{
34+
details::unlock_cache_entry(elem);
35+
}
36+
3237
cache_response::~cache_response()
3338
{
34-
if(locked_element)
35-
ws->unlock_cache_element(content);
39+
if(ce != 0x0 && locked_element)
40+
details::unlock_cache_entry(ce);
3641
}
3742

3843
const std::vector<std::pair<std::string, std::string> > http_response::get_headers()
@@ -134,10 +139,13 @@ void http_file_response::get_raw_response(MHD_Response** response, webserver* ws
134139

135140
void cache_response::get_raw_response(MHD_Response** response, webserver* ws)
136141
{
137-
this->ws = ws;
138142
this->locked_element = true;
139143
bool valid;
140-
http_response* r = ws->get_from_cache(content, &valid, true);
144+
http_response* r;
145+
if(ce == 0x0)
146+
r = ws->get_from_cache(content, &valid, &ce, true, false);
147+
else
148+
r = details::get_response(ce);
141149
r->get_raw_response(response, ws);
142150
r->decorate_response(*response); //It is done here to avoid to search two times for the same element
143151

src/httpserver/http_response.hpp

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ namespace httpserver
3434
{
3535

3636
class webserver;
37+
class http_response;
38+
struct cache_entry;
3739

3840
namespace http
3941
{
@@ -48,6 +50,46 @@ namespace details
4850

4951
using namespace http;
5052

53+
class closure_action
54+
{
55+
public:
56+
closure_action(bool deletable = true):
57+
deletable(deletable)
58+
{
59+
}
60+
closure_action(const closure_action& b):
61+
deletable(b.deletable)
62+
{
63+
}
64+
virtual void do_action() = 0;
65+
bool deletable;
66+
private:
67+
friend class http_response;
68+
};
69+
70+
class empty_closure : public closure_action
71+
{
72+
public:
73+
void do_action()
74+
{
75+
}
76+
};
77+
78+
class unlock_on_close : public closure_action
79+
{
80+
public:
81+
unlock_on_close(cache_entry* elem, bool deletable = true) : closure_action(deletable), elem(elem) { }
82+
unlock_on_close(const unlock_on_close& b) : closure_action(elem), elem(b.elem) { }
83+
unlock_on_close& operator = (const unlock_on_close& b)
84+
{
85+
elem = b.elem;
86+
return *this;
87+
}
88+
virtual void do_action();
89+
private:
90+
cache_entry* elem;
91+
};
92+
5193
/**
5294
* Class representing an abstraction for an Http Response. It is used from classes using these apis to send information through http protocol.
5395
**/
@@ -103,7 +145,8 @@ class http_response
103145
topics(topics),
104146
keepalive_secs(keepalive_secs),
105147
keepalive_msg(keepalive_msg),
106-
send_topic(send_topic)
148+
send_topic(send_topic),
149+
ca(new empty_closure())
107150
{
108151
set_header(http_utils::http_header_content_type, content_type);
109152
}
@@ -128,9 +171,36 @@ class http_response
128171
keepalive_msg(b.keepalive_msg),
129172
send_topic(b.send_topic)
130173
{
174+
if(ca != 0x0 && ca->deletable)
175+
delete ca;
176+
ca = b.ca;
177+
}
178+
http_response& operator=(const http_response& b)
179+
{
180+
response_type = b.response_type;
181+
content = b.content;
182+
response_code = b.response_code;
183+
autodelete = b.autodelete;
184+
realm = b.realm;
185+
opaque = b.opaque;
186+
reload_nonce = b.reload_nonce;
187+
fp = b.fp;
188+
filename = b.filename;
189+
headers = b.headers;
190+
footers = b.footers;
191+
topics = b.topics;
192+
keepalive_secs = b.keepalive_secs;
193+
keepalive_msg = b.keepalive_msg;
194+
send_topic = b.send_topic;
195+
if(ca != 0x0 && ca->deletable)
196+
delete ca;
197+
ca = b.ca;
198+
return *this;
131199
}
132200
virtual ~http_response()
133201
{
202+
if(ca != 0x0 && ca->deletable)
203+
delete ca;
134204
}
135205
/**
136206
* Method used to get the content from the response.
@@ -304,6 +374,10 @@ class http_response
304374
topics.push_back(*it);
305375
return topics.size();
306376
}
377+
void set_closure_action(closure_action* ca)
378+
{
379+
this->ca = ca;
380+
}
307381
protected:
308382
response_type_T response_type;
309383
std::string content;
@@ -321,6 +395,7 @@ class http_response
321395
std::string keepalive_msg;
322396
std::string send_topic;
323397
struct MHD_Connection* underlying_connection;
398+
closure_action* ca;
324399

325400
virtual void get_raw_response(MHD_Response** res, webserver* ws = 0x0);
326401
virtual void decorate_response(MHD_Response* res);
@@ -510,10 +585,20 @@ class cache_response : public http_response
510585
public:
511586
cache_response
512587
(
513-
const std::string& key
588+
const std::string& key,
589+
bool locked_element = false
514590
) : http_response(http_response::CACHED_CONTENT, key),
515-
ws(0x0),
516-
locked_element(false)
591+
ce(0x0),
592+
locked_element(locked_element)
593+
{
594+
}
595+
cache_response
596+
(
597+
cache_entry* ce,
598+
bool locked_element = false
599+
) : http_response(http_response::CACHED_CONTENT, ""),
600+
ce(ce),
601+
locked_element(locked_element)
517602
{
518603
}
519604

@@ -525,7 +610,7 @@ class cache_response : public http_response
525610
virtual void get_raw_response(MHD_Response** res, webserver* ws = 0x0);
526611
virtual void decorate_response(MHD_Response* res);
527612
private:
528-
webserver* ws;
613+
cache_entry* ce;
529614
bool locked_element;
530615
friend class webserver;
531616
};

src/httpserver/webserver.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ class cache_response;
5555
class http_request;
5656
class long_polling_receive_response;
5757
class long_polling_send_response;
58+
struct cache_entry;
5859

5960
namespace details
6061
{
6162
class http_endpoint;
62-
struct cache_entry;
6363
struct modded_request;
6464
struct cache_manager;
65+
void unlock_cache_entry(cache_entry*);
66+
http_response* get_response(cache_entry*);
6567
}
6668

6769
using namespace http;
@@ -263,9 +265,10 @@ class webserver
263265
bool pop_signaled(int consumer);
264266

265267
http_response* get_from_cache(const std::string& key, bool* valid, bool lock = false, bool write = false);
268+
http_response* get_from_cache(const std::string& key, bool* valid, cache_entry** ce, bool lock = false, bool write = false);
266269
void lock_cache_element(const std::string& key, bool write = false);
267270
void unlock_cache_element(const std::string& key);
268-
void put_in_cache(const std::string& key, http_response* value, int validity = -1);
271+
cache_entry* put_in_cache(const std::string& key, http_response* value, bool* new_elem, bool lock = false, bool write = false, int validity = -1);
269272
void remove_from_cache(const std::string& key);
270273
bool is_valid(const std::string& key);
271274
void clean_cache();

src/webserver.cpp

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ namespace details
5858

5959
struct cache_manager
6060
{
61-
std::map<std::string, details::cache_entry> response_cache;
61+
std::map<std::string, cache_entry> response_cache;
6262

6363
cache_manager()
6464
{
@@ -148,11 +148,13 @@ struct modded_request
148148
bool second;
149149
};
150150

151+
}
152+
151153
struct cache_entry
152154
{
153155
long ts;
154156
int validity;
155-
http_response_ptr response;
157+
details::http_response_ptr response;
156158
pthread_rwlock_t elem_guard;
157159

158160
cache_entry():
@@ -184,7 +186,7 @@ struct cache_entry
184186
elem_guard = b.elem_guard;
185187
}
186188

187-
cache_entry(http_response_ptr response, long ts = -1, int validity = -1):
189+
cache_entry(details::http_response_ptr response, long ts = -1, int validity = -1):
188190
ts(ts),
189191
validity(validity),
190192
response(response)
@@ -193,8 +195,21 @@ struct cache_entry
193195
}
194196
};
195197

198+
namespace details
199+
{
200+
201+
void unlock_cache_entry(cache_entry* ce)
202+
{
203+
pthread_rwlock_unlock(&ce->elem_guard);
196204
}
197205

206+
http_response* get_response(cache_entry* ce)
207+
{
208+
return ce->response.ptr();
209+
}
210+
211+
};
212+
198213
using namespace http;
199214

200215
int policy_callback (void *, const struct sockaddr*, socklen_t);
@@ -487,6 +502,8 @@ void webserver::sweet_kill()
487502
void webserver::request_completed (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
488503
{
489504
details::modded_request* mr = (struct details::modded_request*) *con_cls;
505+
if(mr->dhrs->ca != 0x0)
506+
mr->dhrs->ca->do_action();
490507
if (NULL == mr)
491508
{
492509
return;
@@ -1488,10 +1505,16 @@ bool webserver::pop_signaled(int consumer)
14881505
}
14891506

14901507
http_response* webserver::get_from_cache(const std::string& key, bool* valid, bool lock, bool write)
1508+
{
1509+
cache_entry* ce;
1510+
return get_from_cache(key, valid, &ce, lock, write);
1511+
}
1512+
1513+
http_response* webserver::get_from_cache(const std::string& key, bool* valid, cache_entry** ce, bool lock, bool write)
14911514
{
14921515
pthread_rwlock_rdlock(&cache_guard);
14931516
*valid = true;
1494-
map<string, details::cache_entry>::iterator it(cache_m->response_cache.find(key));
1517+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
14951518
if(it != cache_m->response_cache.end())
14961519
{
14971520
if(lock)
@@ -1508,6 +1531,7 @@ http_response* webserver::get_from_cache(const std::string& key, bool* valid, bo
15081531
if( now.tv_sec - (*it).second.ts > (*it).second.validity)
15091532
*valid = false;
15101533
}
1534+
*ce = &((*it).second);
15111535
pthread_rwlock_unlock(&cache_guard);
15121536
return (*it).second.response.ptr();
15131537
}
@@ -1522,7 +1546,7 @@ http_response* webserver::get_from_cache(const std::string& key, bool* valid, bo
15221546
bool webserver::is_valid(const std::string& key)
15231547
{
15241548
pthread_rwlock_rdlock(&cache_guard);
1525-
map<string, details::cache_entry>::iterator it(cache_m->response_cache.find(key));
1549+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15261550
if(it != cache_m->response_cache.end())
15271551
{
15281552
if((*it).second.validity != -1)
@@ -1548,7 +1572,7 @@ bool webserver::is_valid(const std::string& key)
15481572
void webserver::lock_cache_element(const std::string& key, bool write)
15491573
{
15501574
pthread_rwlock_rdlock(&cache_guard);
1551-
map<string, details::cache_entry>::iterator it(cache_m->response_cache.find(key));
1575+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15521576
if(it != cache_m->response_cache.end())
15531577
{
15541578
if(write)
@@ -1562,33 +1586,61 @@ void webserver::lock_cache_element(const std::string& key, bool write)
15621586
void webserver::unlock_cache_element(const std::string& key)
15631587
{
15641588
pthread_rwlock_rdlock(&cache_guard);
1565-
map<string, details::cache_entry>::iterator it(cache_m->response_cache.find(key));
1589+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15661590
if(it != cache_m->response_cache.end())
15671591
pthread_rwlock_unlock(&((*it).second.elem_guard));
15681592
pthread_rwlock_unlock(&cache_guard);
15691593
}
15701594

1571-
void webserver::put_in_cache(const std::string& key, http_response* value, int validity)
1595+
cache_entry* webserver::put_in_cache(const std::string& key, http_response* value, bool* new_elem, bool lock, bool write, int validity)
15721596
{
1597+
pthread_rwlock_wrlock(&cache_guard);
1598+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
1599+
bool unlock = false;
1600+
cache_entry* to_ret;
1601+
if(it != cache_m->response_cache.end())
1602+
{
1603+
pthread_rwlock_wrlock(&((*it).second.elem_guard));
1604+
unlock = true;
1605+
}
15731606
if(validity == -1)
15741607
{
1575-
pthread_rwlock_wrlock(&cache_guard);
1576-
cache_m->response_cache.insert(pair<string, details::cache_entry>(key, details::cache_entry(value)));
1608+
pair<map<string, cache_entry>::iterator, bool> res = cache_m->response_cache.insert(pair<string, cache_entry>(key, cache_entry(value)));
1609+
to_ret = &((*res.first).second);
1610+
if(lock)
1611+
{
1612+
if(write)
1613+
pthread_rwlock_wrlock(&to_ret->elem_guard);
1614+
else
1615+
pthread_rwlock_rdlock(&to_ret->elem_guard);
1616+
}
1617+
*new_elem = res.second;
15771618
}
15781619
else
15791620
{
1580-
pthread_rwlock_wrlock(&cache_guard);
15811621
timeval now;
15821622
gettimeofday(&now, NULL);
1583-
cache_m->response_cache.insert(pair<string, details::cache_entry>(key, details::cache_entry(value, now.tv_sec, validity)));
1623+
pair<map<string, cache_entry>::iterator, bool> res = cache_m->response_cache.insert(pair<string, cache_entry>(key, cache_entry(value, now.tv_sec, validity)));
1624+
to_ret = &((*res.first).second);
1625+
if(lock)
1626+
{
1627+
if(write)
1628+
pthread_rwlock_wrlock(&to_ret->elem_guard);
1629+
else
1630+
pthread_rwlock_rdlock(&to_ret->elem_guard);
1631+
}
1632+
*new_elem = res.second;
15841633
}
1634+
if(unlock)
1635+
pthread_rwlock_unlock(&((*it).second.elem_guard));
15851636
pthread_rwlock_unlock(&cache_guard);
1637+
return to_ret;
15861638
}
15871639

15881640
void webserver::remove_from_cache(const std::string& key)
15891641
{
15901642
pthread_rwlock_wrlock(&cache_guard);
1591-
map<string, details::cache_entry>::iterator it(cache_m->response_cache.find(key));
1643+
map<string, cache_entry>::iterator it(cache_m->response_cache.find(key));
15921644
if(it != cache_m->response_cache.end())
15931645
cache_m->response_cache.erase(it);
15941646
pthread_rwlock_unlock(&cache_guard);

0 commit comments

Comments
 (0)