///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
///////////////////////////////////////////////////////////////////////////////
#define CPPCMS_SOURCE
#include "session_memory_storage.h"
#include <cppcms/config.h>
#include "hash_map.h"
#include <booster/thread.h>
#include <time.h>
#include <map>
namespace cppcms {
namespace sessions {
class session_memory_storage : public session_storage {
struct _data;
typedef cppcms::impl::hash_map<
std::string,
_data,
cppcms::impl::string_hash
> map_type;
typedef map_type::iterator pointer;
typedef std::multimap<time_t,pointer> timeout_type;
struct _data {
time_t timeout;
std::string info;
timeout_type::iterator timeout_ptr;
};
map_type map_;
timeout_type timeout_;
booster::shared_mutex mutex_;
public:
void save(std::string const &key,time_t to,std::string const &value)
{
booster::unique_lock<booster::shared_mutex> lock(mutex_);
pointer p=map_.find(key);
if(p==map_.end()) {
std::pair<pointer,bool> pr = map_.insert(std::pair<std::string,_data>(key,_data()));
pointer p = pr.first;
p->second.timeout=to;
p->second.info=value;
p->second.timeout_ptr=timeout_.insert(std::pair<time_t,pointer>(to,p));
}
else {
timeout_.erase(p->second.timeout_ptr);
p->second.timeout=to;
p->second.info=value;
p->second.timeout_ptr=timeout_.insert(std::pair<time_t,pointer>(to,p));
}
short_gc();
}
void short_gc()
{
time_t now=::time(0);
timeout_type::iterator p=timeout_.begin(),tmp;
int count = 0;
while(p!=timeout_.end() && p->first < now && count < 5) {
tmp=p;
++p;
map_.erase(tmp->second);
timeout_.erase(tmp);
count++;
}
}
bool load(std::string const &key,time_t &to,std::string &value)
{
booster::shared_lock<booster::shared_mutex> lock(mutex_);
map_type::iterator p=map_.find(key);
if(p==map_.end())
return false;
if(p->second.timeout < ::time(0))
return false;
value=p->second.info;
to=p->second.timeout;
return true;
}
void remove(std::string const &key)
{
booster::unique_lock<booster::shared_mutex> lock(mutex_);
pointer p=map_.find(key);
if(p==map_.end())
return;
timeout_.erase(p->second.timeout_ptr);
map_.erase(p);
short_gc();
}
bool is_blocking()
{
return false;
}
};
session_memory_storage_factory::session_memory_storage_factory() :
storage_(new session_memory_storage())
{
}
session_memory_storage_factory::~session_memory_storage_factory()
{
}
booster::shared_ptr<session_storage> session_memory_storage_factory::get()
{
return storage_;
}
bool session_memory_storage_factory::requires_gc()
{
return false;
}
void session_memory_storage_factory::gc_job()
{
}
} // sessions
} // cppcms