winix/core/sessioncontainer.cpp

221 lines
3.3 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* All rights reserved.
*
*/
#include "sessioncontainer.h"
#include "log.h"
#include "misc.h"
SessionContainer::SessionContainer()
{
request = 0;
table_size = 0;
work_mode = 1; // threading work mode
}
void SessionContainer::SetRequest(Request * prequest)
{
request = prequest;
}
void SessionContainer::SetConfig(Config * pconfig)
{
config = pconfig;
}
void SessionContainer::Clear()
{
Table::iterator i = table.begin();
// don't use table.clear();
// because plugins session data would not be erased
while( i != table.end() )
{
request->session = &(*i);
table.erase(i++);
}
// erasing indexes
index_id.clear();
table_size = 0;
request->session = 0;
}
void SessionContainer::SetLastContainer(LastContainer * plast_container)
{
last_container = plast_container;
}
size_t SessionContainer::Size()
{
// don't use table.size() as it has O(n) complexity on FreeBSD
return table_size;
}
SessionContainer::Iterator SessionContainer::Begin()
{
return table.begin();
}
SessionContainer::Iterator SessionContainer::End()
{
return table.end();
}
Session & SessionContainer::Back()
{
return table.back();
}
bool SessionContainer::PushBack(const Session & session)
{
std::pair<IndexId::iterator, bool> index_id_res = index_id.insert( std::make_pair(session.id, table.end()) );
if( !index_id_res.second )
{
// that element already exists (was not inserted now)
return false;
}
Iterator last = table.insert(table.end(), session);
index_id_res.first->second = last;
table_size += 1;
log << log3 << "SC: added session, id: " << session.id << logend;
return true;
}
SessionContainer::Iterator SessionContainer::FindById(long id)
{
IndexId::iterator i;
i = index_id.find(id);
if( i == index_id.end() )
return table.end();
return i->second;
}
/*
*
*
* sessions gc (another thread)
*
*
*/
void SessionContainer::Work()
{
bool exit = false;
IndexId::iterator i;
Lock();
i = index_id.begin();
Unlock();
while( !exit )
{
Lock();
if( i == index_id.end() )
{
i = index_id.begin();
WaitForSignalSleep(10);
//WaitForSignalSleep(1);
}
else
{
if( IsSessionOutdated(*i->second) )
DeleteSession(i++);
else
++i;
}
exit = synchro->was_stop_signal;
Unlock();
}
}
// it's called from the other thread (with Lock and Unlock)
bool SessionContainer::IsSessionOutdated(const Session & s) const
{
bool outdated;
if( s.remember_me )
outdated = s.last_time < std::time(0) - config->session_remember_max_idle;
else
outdated = s.last_time < std::time(0) - config->session_max_idle;
return outdated;
}
// it's called from the other thread (with Lock and Unlock)
void SessionContainer::DeleteSession(SessionContainer::IndexId::iterator i)
{
Session * old_session = 0;
Session * del_session = &(*i->second);
if( del_session != request->session )
old_session = request->session;
request->session = del_session;
log << log4 << "SessionContainer: deleting outdated session, id: " << del_session->id << logend;
if( del_session->puser )
last_container->UserLogout(del_session->puser->id, del_session->id);
table.erase(i->second);
index_id.erase(i);
table_size -= 1;
// !! tu moze byc zero
request->session = old_session;
}
/*
*
*
* end of sessions gc
*
*
*/