#define CPPCMS_SOURCE
#include "tcp_cache_client.h"
#include "atomic_counter.h"
#ifdef CPPCMS_USE_EXTERNAL_BOOST
# include <boost/thread.hpp>
#else // Internal Boost
# include <cppcms_boost/thread.hpp>
namespace boost = cppcms_boost;
#endif
namespace cppcms {
namespace impl {
class cache_over_ip : public base_cache {
public:
cache_over_ip(std::vector<std::string> ips,std::vector<int> ports,intrusive_ptr<base_cache> l1) :
ips_(ips),
ports_(ports),
l1_(l1),
refs_(0)
{
}
bool fetch( std::string const &key,
std::string *a,std::set<std::string> *tags,
time_t *timeout_out,
uint64_t *gen)
{
std::string buffer;
if(!a) a=&buffer;
time_t tmp_timeout;
if(!timeout_out) timeout_out=&tmp_timeout;
uint64_t generation;
if(!gen) gen=&generation;
if(!l1_.get()) {
if(tcp()->fetch(key,*a,tags,*timeout_out,*gen,false)==tcp_cache::found)
return true;
return false;
}
std::set<std::string> tmp_triggers;
if(!tags) tags=&tmp_triggers;
if(l1_->fetch(key,a,tags,timeout_out,gen)) {
int res = tcp()->fetch(key,*a,tags,*timeout_out,*gen,true);
if(res==tcp_cache::up_to_date)
return true;
if(res==tcp_cache::not_found) {
l1_->remove(key);
return false;
}
l1_->store(key,*a,*tags,*timeout_out,gen);
return true;
}
else {
if(tcp()->fetch(key,*a,tags,*timeout_out,*gen,false)==tcp_cache::found) {
l1_->store(key,*a,*tags,*timeout_out,gen);
return true;
}
return false;
}
}
virtual void store(std::string const &key,std::string const &b,std::set<std::string> const &triggers,time_t timeout,uint64_t const *gen)
{
if(l1_.get())
l1_->remove(key);
tcp()->store(key,b,triggers,timeout);
}
virtual void rise(std::string const &trigger)
{
if(l1_.get())
l1_->rise(trigger);
tcp()->rise(trigger);
}
virtual void remove(std::string const &key)
{
// NA
}
virtual void clear()
{
if(l1_.get())
l1_->clear();
tcp()->clear();
}
virtual void stats(unsigned &keys,unsigned &triggers)
{
tcp()->stats(keys,triggers);
}
virtual void add_ref()
{
++refs_;
}
virtual bool del_ref()
{
if(--refs_ == 0)
return true;
return false;
}
virtual ~cache_over_ip()
{
}
private:
tcp_cache *tcp()
{
if(!tcp_.get())
tcp_.reset(new tcp_cache(ips_,ports_));
return tcp_.get();
}
boost::thread_specific_ptr<tcp_cache> tcp_;
std::vector<std::string> ips_;
std::vector<int> ports_;
intrusive_ptr<base_cache> l1_;
atomic_counter refs_;
};
intrusive_ptr<base_cache> CPPCMS_API
tcp_cache_factory( std::vector<std::string> const &ips,
std::vector<int> const &ports,
intrusive_ptr<base_cache> l1)
{
return new cache_over_ip(ips,ports,l1);
}
} // impl
} // cppcms