winix/winixd/core/loadavg.cpp

407 lines
7.1 KiB
C++
Raw Normal View History

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "loadavg.h"
#include "misc.h"
namespace Winix
{
LoadAvg::LoadAvg()
{
current1.Clear();
current5.Clear();
current15.Clear();
cache_load1 = 0.0;
cache_load5 = 0.0;
cache_load15 = 0.0;
cache_req_per_sec1 = 0.0;
cache_req_per_sec5 = 0.0;
cache_req_per_sec15 = 0.0;
timespec_old_req_stop.tv_sec = 0;
timespec_old_req_stop.tv_nsec = 0;
CreateTable();
}
LoadAvg & LoadAvg::operator=(const LoadAvg & l)
{
current1 = l.current1;
current5 = l.current5;
current15 = l.current15;
cache_load1 = l.cache_load1;
cache_load5 = l.cache_load5;
cache_load15 = l.cache_load15;
cache_req_per_sec1 = l.cache_req_per_sec1;
cache_req_per_sec5 = l.cache_req_per_sec5;
cache_req_per_sec15 = l.cache_req_per_sec15;
timespec_old_req_stop.tv_sec = l.timespec_old_req_stop.tv_sec;
timespec_old_req_stop.tv_nsec = l.timespec_old_req_stop.tv_nsec;
CreateTable();
return *this;
}
LoadAvg::LoadAvg(const LoadAvg & l)
{
operator=(l);
}
LoadAvg::~LoadAvg()
{
delete [] tab1;
delete [] tab5;
delete [] tab15;
}
void LoadAvg::CreateTable(size_t seconds, size_t granularity, Times* & tab, size_t & len)
{
len = (seconds / granularity) + 1; // rounding up (len mininum is 1)
tab = new Times[len];
for(size_t i=0 ; i<len ; ++i)
{
tab[i].Clear();
tab[i].dp = granularity; // at the beginning we assume the pause for all items
}
}
void LoadAvg::CreateTable()
{
CreateTable(60, WINIX_LOADAVG_GRANULARITY1, tab1, len1);
CreateTable(60 * 5, WINIX_LOADAVG_GRANULARITY5, tab5, len5);
CreateTable(60 * 15, WINIX_LOADAVG_GRANULARITY15, tab15, len15);
}
void LoadAvg::MoveTab(Times * tab, size_t len)
{
if( len > 1 )
{
for(size_t i=0 ; i<len-1 ; ++i)
tab[i] = tab[i+1];
}
tab[len-1].Clear();
}
void LoadAvg::UpdateTimer1()
{
MoveTab(tab1, len1);
tab1[len1-1] = current1;
current1.Clear();
cache_load1 = 0.0;
cache_req_per_sec1 = 0.0;
}
void LoadAvg::UpdateTimer5()
{
MoveTab(tab5, len5);
tab5[len5-1] = current5;
current5.Clear();
cache_load5 = 0.0;
cache_req_per_sec5 = 0.0;
}
void LoadAvg::UpdateTimer15()
{
MoveTab(tab15, len15);
tab15[len15-1] = current15;
current15.Clear();
cache_load15 = 0.0;
cache_req_per_sec15 = 0.0;
}
void LoadAvg::CheckTimers()
{
if( current1.dr + current1.dp > (double)WINIX_LOADAVG_GRANULARITY1 )
UpdateTimer1();
if( current5.dr + current5.dp > (double)WINIX_LOADAVG_GRANULARITY5 )
UpdateTimer5();
if( current15.dr + current15.dp > (double)WINIX_LOADAVG_GRANULARITY15 )
UpdateTimer15();
}
void LoadAvg::StartRequest(Request * req)
{
if( timespec_old_req_stop.tv_sec != 0 )
{
// we got at least one request in the past
timespec diff;
calculate_timespec_diff(timespec_old_req_stop, req->timespec_req_start, diff);
double dp = timespec_to_double(diff);
current1.dp += dp;
current5.dp += dp;
current15.dp += dp;
CheckTimers();
}
}
added: possibility to encode the session cookie (added files core/sessionidmanager.h and core/sessionidmanager.cpp) added: config options: // whether or not we should encode the session cookie // (we have a special algorithm) // default: false bool session_cookie_encode; // if session_cookie_encode is true then you should provide // a file where AES keys will be stored std::wstring session_keys_file; // each session has an index -- an unsigned int value // this value is sent in the cookie string (is encoded) // and is incremented when session_index_time_increment time is passed since the last incrementing // if a client sent the cookie back the difference between // current index and the index in the cookie should be less than or equal to session_allow_index_difference // default: 8 size_t session_allow_index_difference; // the time which should pass after the session index is incremented // default: 30 // (session_allow_index_difference + 1) * session_index_time_increment should be less than a time // load of a page and all elements on it such as images (of course it depends on client's download too) time_t session_index_time_increment; // time in seconds after a new AES key pair should be generated // we have 256 pairs of keys so this time multiplied by 256 should not be less than // the max time of a session (session_remember_max_idle), // by default: 256 * 2 days = 512 days = 1.4 year > 3 months (session_remember_max_idle) // default: 172800 = 2 days (max: 2678400 = 1 month, min: 10) size_t session_key_renew_time; changed: when printing the time of a request we print only two non-zero digits git-svn-id: svn://ttmath.org/publicrep/winix/trunk@994 e52654a7-88a9-db11-a3e9-0013d4bc506e
2014-11-22 16:30:56 +01:00
void LoadAvg::StopRequest(Request * req)
{
double dr = timespec_to_double(req->timespec_req_diff);
current1.dr += dr;
current5.dr += dr;
current15.dr += dr;
current1.req += 1;
current5.req += 1;
current15.req += 1;
timespec_old_req_stop = req->timespec_req_stop;
}
void LoadAvg::SumTab(Times * tab, size_t len, double expected, Times & t)
{
size_t i = len;
while( i-- > 0 && t.dr+t.dp < expected )
{
t.dr += tab[i].dr;
t.dp += tab[i].dp;
t.req += tab[i].req;
}
}
void LoadAvg::Calculate1()
{
Times t = current1;
SumTab(tab1, len1, 60.0, t);
if( t.dr+t.dp == 0.0 )
{
cache_load1 = 0.0;
cache_req_per_sec1 = 0.0;
}
else
{
cache_load1 = t.dr / (t.dr+t.dp);
cache_req_per_sec1 = t.req / (t.dr+t.dp);
}
}
void LoadAvg::Calculate5()
{
Times t = current5;
SumTab(tab5, len5, 60.0 * 5, t);
if( t.dr+t.dp == 0.0 )
{
cache_load5 = 0.0;
cache_req_per_sec5 = 0.0;
}
else
{
cache_load5 = t.dr / (t.dr+t.dp);
cache_req_per_sec5 = t.req / (t.dr+t.dp);
}
}
void LoadAvg::Calculate15()
{
Times t = current15;
SumTab(tab15, len15, 60.0 * 15, t);
if( t.dr+t.dp == 0.0 )
{
cache_load15 = 0.0;
cache_req_per_sec15 = 0.0;
}
else
{
cache_load15 = t.dr / (t.dr+t.dp);
cache_req_per_sec15 = t.req / (t.dr+t.dp);
}
}
double LoadAvg::LoadAvgNow()
{
double load = 0.0;
double dr = current1.dr;
double dp = current1.dp;
if( tab1[len1-1].dr + tab1[len1-1].dp < WINIX_LOADAVG_GRANULARITY1 * 2 )
{
dr += tab1[len1-1].dr;
dp += tab1[len1-1].dp;
}
if( dr + dp != 0.0 )
load = dr / (dr + dp);
return load;
}
double LoadAvg::LoadAvg1()
{
if( cache_load1 != 0.0 )
return cache_load1;
Calculate1();
return cache_load1;
}
double LoadAvg::LoadAvg5()
{
if( cache_load5 != 0.0 )
return cache_load5;
Calculate5();
return cache_load5;
}
double LoadAvg::LoadAvg15()
{
if( cache_load15 != 0.0 )
return cache_load15;
Calculate15();
return cache_load15;
}
double LoadAvg::ReqPerSecNow()
{
double req_per_sec = 0.0;
double dr = current1.dr;
double dp = current1.dp;
double req = current1.req;
if( tab1[len1-1].dr + tab1[len1-1].dp < WINIX_LOADAVG_GRANULARITY1 * 2 )
{
dr += tab1[len1-1].dr;
dp += tab1[len1-1].dp;
req += tab1[len1-1].req;
}
if( dr + dp != 0.0 )
req_per_sec = req / (dr + dp);
return req_per_sec;
}
double LoadAvg::ReqPerSec1()
{
if( cache_req_per_sec1 != 0.0 )
return cache_req_per_sec1;
Calculate1();
return cache_req_per_sec1;
}
double LoadAvg::ReqPerSec5()
{
if( cache_req_per_sec5 != 0.0 )
return cache_req_per_sec5;
Calculate5();
return cache_req_per_sec5;
}
double LoadAvg::ReqPerSec15()
{
if( cache_req_per_sec15 != 0.0 )
return cache_req_per_sec15;
Calculate15();
return cache_req_per_sec15;
}
} // namespace Winix