allow a request to be processed in a job

Now we allow a request to be passed into a job queue,
and after the job finishes the request is passed into
a controller again. In order to achieve this we have
a requests queue in System, when we put a request
to the job this Request structure is preserved in the
queue and for a new request a new Request is added to
the queue.

while here:
- remove App::Lock()/Unlock(), use scoped locking
- fix: Plugin now has a Call method which takes ModelConnector
  and a logger (used in multithreaded environment)
- BaseThread has a main_model_connector pointer
  to the main (from the main thread) model connector
- the FastCGI structure fcgi_request moved from App to Request
- some methods for handling requests moved from App to Request
- small refactoring in main.cpp
- add Http class (a http client)
This commit is contained in:
2022-07-25 14:21:21 +02:00
parent b2d92b85a0
commit 979ef907fe
65 changed files with 7018 additions and 4437 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -74,18 +74,20 @@ public:
bool DropPrivileges();
void InitLoggers();
Log & GetMainLog();
void LoadPlugins();
bool InitializePlugins();
bool Init();
bool InitializeRequestForFastCGI();
void SetRequestDependency();
void InitializeNewRequest();
void PrepareRequest();
void PutRequestToJob();
void Start();
void Close();
void LogUserGroups();
void LogRequestTime();
bool Demonize();
void SetStopSignal();
bool WasStopSignal();
bool Lock();
void Unlock();
Synchro * GetSynchro();
void StartThreads();
void WaitForThreads();
@@ -95,10 +97,6 @@ public:
// pointers to the current request and a session
Cur cur;
// temporary one request object
// current request
Request req;
// users sessions
SessionManager session_manager;
@@ -106,7 +104,8 @@ public:
Db db;
DbConn db_conn;
// an unique id for each request
size_t request_id;
// ...
System system;
@@ -136,24 +135,12 @@ private:
AcceptBaseParser accept_base_parser;
AcceptEncodingParser accept_encoding_parser;
Compress compress;
FCGX_Request fcgi_request;
int fcgi_socket;
Synchro synchro;
pthread_t signal_thread;
std::string socket_to_send_on_exit;
std::string send_data_buf;
pt::WTextStream json_out_stream;
std::string aheader_name, aheader_value;
//std::wstring html_filtered;
//std::string output_8bit;
pt::TextStream serialized_model;
pt::WTextStream post_log_tmp_buffer;
pt::WTextStream output_tmp_filtered_stream;
BinaryPage output_8bit;
BinaryPage compressed_output;
std::wstring cookie_id_string;
std::wstring http_header_name;
std::wstring http_header_value;
std::string http_header_8bit;
@@ -199,48 +186,15 @@ private:
void CheckIfNeedSSLredirect();
void SetLocale();
void CheckPostRedirect();
void UseEzcGenerator();
void AddDefaultModels();
void SaveSessionsIfNeeded(); // !! IMPROVE ME wywalic do menagera sesji??
void LogAccess();
void SendData(const BinaryPage & page, FCGX_Stream * out);
void ReadRequest();
void SendAnswer();
void PrepareRawAnswer();
void PrepareJsonAnswer();
void PrepareXmlAnswer();
void PrepareCsvAnswer();
void PrepareContenerizedAnswer();
void PutSeparatorIfNeeded(bool put_separator);
void SerializeFieldJson(const wchar_t * field_name);
void SerializeStream(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamJson(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamXml(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamCsv(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeAllFrames();
void SerializeSpecificFrames();
void SerializeModels();
void Send8bitOutput(BinaryPage & output);
void SerializeModel(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelJson(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelXml(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelCsv(morm::Wrapper & wrapper, const wchar_t * field_name);
void FilterHtmlIfNeeded(const pt::WTextStream & input_stream, BinaryPage & output, bool clear_stream = true);
void LogEnvironmentVariables();
void LogEnvironmentHTTPVariables();
void ParseAcceptHeader(const wchar_t * header_name, const std::wstring & env, std::vector<HeaderValue> & container, size_t max_len);
void ParseAcceptHeader();
void ParseAcceptLanguageHeader();
void SetEnv(const char * name, std::wstring & env);
void ReadEnvVariables();
void ReadEnvHTTPVariables();
@@ -250,37 +204,17 @@ private:
void ParsePostJson();
void ReadPostJson();
void ReadPostVars();
void CheckIE();
void CheckKonqueror();
void CheckRequestMethod();
void CheckSSL();
void CheckHtmx();
void SetSubdomain();
bool IsRequestedFrame();
void ModifyStatusCodeIfNeeded();
void PrepareSessionCookie();
void SendHeaders();
void SendCookies();
bool AddHeader(const wchar_t * name, const wchar_t * value);
bool AddHeader(const std::wstring & name, const std::wstring & value);
bool AddHeader(const wchar_t * name, const pt::WTextStream & value);
bool AddHeader(const std::wstring & name, const pt::WTextStream & value);
bool CreateStaticResourcePath(pt::WTextStream & out_path);
void PrepareSendFileHeaderForStaticMountpoint();
void PrepareHeaderContentType();
void ModifyStatusForRedirect();
void PrepareSendFileHeader();
void PrepareContentEncodingHeader(int compress_encoding);
void PrepareContentLengthHeader(size_t output_size);
void PrepareHeaderStatus(int http_status);
void PrepareHeaders(bool compressing, int compress_encoding, size_t output_size);
int SelectDeflateVersion();
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
bool CanSendContent();
void ClearAfterRequest();
void IncrementRequestId();
void LogUser(const char * msg, uid_t id);
void LogGroup(const char * msg, gid_t id, bool put_logend = true);
@@ -295,6 +229,7 @@ private:
bool DoDatabaseMigration();
bool TryToMakeDatabaseMigration();
void WaitForRequestsToFinish();
// !! IMPROVE ME

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2019, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,10 +42,11 @@ namespace Winix
BaseThread::BaseThread() : thread_signal(PTHREAD_COND_INITIALIZER)
{
synchro = 0;
thread_id = 0;
work_mode = 0;
wake_up_was_called = false;
synchro = nullptr;
thread_id = 0;
work_mode = 0;
wake_up_was_called = false;
main_model_connector = nullptr;
}
@@ -66,6 +67,12 @@ void BaseThread::set_main_file_log(pt::FileLog * file_log)
}
void BaseThread::set_main_model_connector(morm::ModelConnector * main_model_connector)
{
this->main_model_connector = main_model_connector;
}
void BaseThread::Mode(int mode)
{
work_mode = mode;

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2019, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,7 @@ public:
void set_main_log_buffer(pt::WTextStream * log_buffer);
void set_main_file_log(pt::FileLog * file_log);
void set_main_model_connector(morm::ModelConnector * main_model_connector);
// work mode
// we have two modes:
@@ -105,11 +106,13 @@ protected:
// logger for the main thread
Log main_log;
// log from WinixBase is meant to be used by the second thread
// log from WinixBase is meant to be used by the other thread
// model connector for the main thread
// model_connector from the based class WinixModelDeprecated is meant to be used by the second thread
morm::ModelConnector * main_model_connector;
protected:
// signal came (work mode = 0 - default)

View File

@@ -135,7 +135,7 @@ void Config::AssignValues()
fcgi_socket_chmod = Int(L"fcgi_socket_chmod", 0770);
fcgi_socket_user = Text(L"fcgi_socket_user");
fcgi_socket_group = Text(L"fcgi_socket_group");
fcgi_socket_listen = Int(L"fcgi_socket_listen", 100);
fcgi_socket_listen = Int(L"fcgi_socket_listen", 1024);
log_level = Int(L"log_level", 1);
log_request = Int(L"log_request", 1);
log_save_each_line = Bool(L"log_save_each_line", false);
@@ -344,6 +344,8 @@ void Config::AssignValues()
use_antispam_mechanism_for_not_logged_users = Bool(L"use_antispam_mechanism_for_not_logged_users", true);
antispam_list_max_size = Size(L"antispam_list_max_size", 10);
add_header_cache_no_store_in_htmx_request = Bool(L"add_header_cache_no_store_in_htmx_request", true);
request_queue_job_limit = Size(L"request_queue_job_limit", 1024);
}

View File

@@ -94,7 +94,7 @@ public:
bool log_stdout;
// how many requests should be saved in the same time
// if you have a very busy server you can incrase this value
// if you have a very busy server you can increase this value
// default: 1
int log_request;
@@ -934,7 +934,7 @@ public:
// default: X_Real_IP
std::wstring proxy_ip_header;
// use an antismap mechanism for not logged users
// use an antispam mechanism for not logged users
// when they try to add a new item
// default: true
bool use_antispam_mechanism_for_not_logged_users;
@@ -952,6 +952,13 @@ public:
// https://github.com/bigskysoftware/htmx/issues/497
bool add_header_cache_no_store_in_htmx_request;
// a limit for the queue for requests
// when a request is scheduled to a job
// default: 1024
// if the limit is reached then the http status 503 Service Unavailable is returned
size_t request_queue_job_limit;
Config();

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,14 @@ struct Cur
// those pointers are never null, if there is no a session for the user
// the 'session' pointer pointers at a special temporary session
Cur()
{
request = nullptr;
session = nullptr;
mount = nullptr;
}
};

View File

@@ -83,6 +83,11 @@ public:
static constexpr const wchar_t * text_csv_utf8 = L"text/csv; charset=UTF-8";
static constexpr const wchar_t * text_javascript_utf8 = L"text/javascript; charset=UTF-8";
static constexpr const wchar_t * application_x_www_form_urlencoded = L"application/x-www-form-urlencoded";
static constexpr const wchar_t * multipart_form_data = L"multipart/form-data";
static constexpr const wchar_t * bearer = L"Bearer";
static const int status_200_ok = 200;
static const int status_300_multiple_choices = 300;
@@ -95,6 +100,7 @@ public:
static const int status_404_not_found = 404;
static const int status_414_uri_too_long = 414;
static const int status_500_internal_server_error = 500;
static const int status_503_service_unavailale = 503;
static constexpr const wchar_t * str_status_200 = L"OK";
@@ -108,6 +114,7 @@ public:
static constexpr const wchar_t * str_status_404 = L"Not Found";
static constexpr const wchar_t * str_status_414 = L"URI Too Long";
static constexpr const wchar_t * str_status_500 = L"Internal Server Error";
static constexpr const wchar_t * str_status_503 = L"Service Unavailable";
static const wchar_t * find_status_string_value(int http_status);
@@ -135,6 +142,7 @@ protected:
{status_404_not_found, str_status_404},
{status_414_uri_too_long, str_status_414},
{status_500_internal_server_error, str_status_500},
{status_503_service_unavailale, str_status_503},
};
};

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2021, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -496,27 +496,27 @@ void Image::ImageSavedCorrectly()
}
log << log3 << "Image: generated a thumbnail: " << dst_path << logend;
plugin->Call((Session*)0, WINIX_CREATED_THUMB, &file_work);
plugin->Call(model_connector, &log, nullptr, WINIX_CREATED_THUMB, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_RESIZE )
{
log << log3 << "Image: image resized: " << dst_path << logend;
plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CROP )
{
log << log3 << "Image: image cropped: " << dst_path << logend;
// !! IMPROVE ME add a correct message
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
//plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CROP_THUMB )
{
log << log3 << "Image: image thumbnail cropped: " << dst_path << logend;
// !! IMPROVE ME add a correct message
//plugin->Call((Session*)0, WINIX_IMAGE_RESIZED, &file_work);
//plugin->Call(model_connector, &log, nullptr, WINIX_IMAGE_RESIZED, &file_work, nullptr, 0, 0);
}
else
if( item_work.type == WINIX_IMAGE_TYPE_CREATE_CROP_NEW_THUMB )

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2012-2019, Tomasz Sowa
* Copyright (c) 2012-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,9 @@
#include "job.h"
#include "plugin.h"
#include "log.h"
#include "functions/functions.h"
#include "lock.h"
namespace Winix
@@ -45,31 +48,110 @@ namespace Winix
Job::Job()
{
jobs_queue_tab.resize(WINIX_JOBS_HOW_MANY_PRIORITIES);
jobs_queue_tab.resize(PRIORITY_HIGHEST + 1);
cur = nullptr;
functions = nullptr;
mounts = nullptr;
load_avg = nullptr;
req_tab = nullptr;
}
void Job::CheckPriority(int & priority) const
void Job::SetCur(Cur * cur)
{
if( priority < 0 )
priority = 0;
this->cur = cur;
}
if( priority >= WINIX_JOBS_HOW_MANY_PRIORITIES )
priority = WINIX_JOBS_HOW_MANY_PRIORITIES - 1;
void Job::SetFunctions(Functions * functions)
{
this->functions = functions;
}
void Job::SetLoadAvg(LoadAvg * load_avg)
{
this->load_avg = load_avg;
}
void Job::SetMounts(Mounts * mounts)
{
this->mounts = mounts;
}
void Job::SetReqTab(std::list<Request> * req_tab)
{
this->req_tab = req_tab;
}
void Job::CheckPriority(size_t & priority) const
{
if( priority > PRIORITY_HIGHEST )
priority = PRIORITY_HIGHEST;
}
// first thread (objects locked)
void Job::Add(pt::Space & job, int priority)
void Job::Add(pt::Space & job, size_t priority)
{
CheckPriority(priority);
jobs_queue_tab[priority].push(job);
JobTask task;
task.job_type = JobTask::JOB_TYPE_DEFAULT;
task.job_id = JobTask::JOB_ID_DEFAULT;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
// first thread (objects locked)
void Job::Add(Request * request, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_REQUEST_CONTINUATION;
task.job_id = JobTask::JOB_ID_DEFAULT;
task.request = request;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
size_t Job::Size(int priority) const
// first thread (objects locked)
void Job::Add(long job_id, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_DEFAULT;
task.job_id = job_id;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
// first thread (objects locked)
void Job::Add(long job_id, Request * request, pt::Space & job, size_t priority)
{
CheckPriority(priority);
JobTask task;
task.job_type = JobTask::JOB_TYPE_REQUEST_CONTINUATION;
task.job_id = job_id;
task.request = request;
task.job = job;
jobs_queue_tab[priority].push(task);
WakeUpThread();
}
size_t Job::Size(size_t priority) const
{
CheckPriority(priority);
return jobs_queue_tab[priority].size();
@@ -81,14 +163,14 @@ size_t Job::Size() const
{
size_t sum = 0;
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
for(size_t i=0 ; i <= PRIORITY_HIGHEST ; ++i)
sum += Size(i);
return sum;
}
bool Job::Empty(int priority) const
bool Job::Empty(size_t priority) const
{
CheckPriority(priority);
return jobs_queue_tab[priority].empty();
@@ -97,7 +179,7 @@ bool Job::Empty(int priority) const
bool Job::Empty() const
{
for(size_t i=0 ; i<WINIX_JOBS_HOW_MANY_PRIORITIES ; ++i)
for(size_t i=0 ; i <= PRIORITY_HIGHEST ; ++i)
if( !Empty(i) )
return false;
@@ -121,19 +203,20 @@ bool Job::SignalReceived()
// second thread (objects not locked)
void Job::Do()
{
size_t i = WINIX_JOBS_HOW_MANY_PRIORITIES;
size_t i = PRIORITY_HIGHEST + 1;
bool is_empty;
while( i-- > 0 && !IsExitSignal() )
{
do
{
Lock();
is_empty = Empty(i);
Unlock();
{
Winix::Lock lock(synchro);
is_empty = Empty(i);
}
if( !is_empty )
DoQueue(jobs_queue_tab[i]);
DoQueue(jobs_queue_tab[i], i);
}
while( !is_empty && !IsExitSignal() );
}
@@ -141,45 +224,144 @@ bool is_empty;
// second thread (objects not locked, jobs_queue is not empty)
void Job::DoQueue(JobsQueue & jobs_queue)
void Job::DoQueue(JobsQueue & jobs_queue, size_t priority)
{
bool is_empty;
do
{
Lock();
// references will not be invalidated after insertion to jobs_queue
// (jobs_queue is std::queue and it uses std::deque by default)
pt::Space & job = jobs_queue.front();
Unlock();
JobTask * job_task = nullptr;
DoJob(job);
{
Winix::Lock lock(synchro);
Lock();
jobs_queue.pop();
is_empty = jobs_queue.empty();
Unlock();
if( !jobs_queue.empty() )
{
job_task = &jobs_queue.front();
}
}
if( job_task )
{
DoJob(*job_task, priority);
{
Winix::Lock lock(synchro);
jobs_queue.pop();
is_empty = jobs_queue.empty();
}
}
}
while( !is_empty && !IsExitSignal() );
}
// second thread (objects not locked)
void Job::DoJob(pt::Space & job)
void Job::DoJob(JobTask & task, size_t priority)
{
PluginRes res;
try
{
PluginRes res = plugin->Call((Session*)0, WINIX_JOB, &job);
main_log << logsave;
if( task.job_type == JobTask::JOB_TYPE_REQUEST_CONTINUATION )
{
if( task.request )
{
Cur local_cur;
// is this correct? we can read the task.request->session ... from the second thread?
// chyba tak bo ta struktura zostaje na stosie specjalnie dla joba do uzytku
local_cur.request = task.request;
local_cur.session = task.request->session;
local_cur.mount = task.request->mount;
cur->request->run_state = Request::RunState::job_run;
res = plugin->Call(model_connector, &log, &local_cur, WINIX_JOB, &task.job, nullptr, task.job_type, task.job_id);
{
Winix::Lock lock(synchro);
cur->request = local_cur.request;
cur->session = local_cur.session;
cur->mount = local_cur.mount;
// winix templates functions uses its own cur (global pointer in TemplatesFunctions namespace)
// so we have to set it correctly
DoRequestContinuationJob(task, priority);
}
}
else
{
log << log2 << "Job: request continuation task doesn't have a request set, skipping the job and request continuation" << logend;
log << log2 << "Job: this is an internal error, the request if exists in the queue will never be removed" << logend;
}
}
else
{
res = plugin->Call(model_connector, &log, nullptr, WINIX_JOB, &task.job, nullptr, task.job_type, task.job_id);
}
log << logsave;
if( res.res_true == 0 )
DoWinixJob(job);
{
DoWinixJob(task.job); // probably this will be removed
}
}
catch(...)
{
log << log2 << "Job: an exception was catched when doing a job" << logend;
}
}
// second thread (objects locked)
// use main_log (after locking) for the logs to be in the correct order
void Job::DoRequestContinuationJob(JobTask & job_task, size_t priority)
{
if( cur->request->function )
{
main_log << config->log_delimiter << logend;
main_log << log3 << "Job: making a continuation for request " << cur->request << logend;
main_log << log4 << "Job: doing directory analysis again" << logend;
if( functions->ParseOnlyDirs() )
{
cur->mount = mounts->CalcCurMount(cur->request);
cur->request->mount = cur->mount;
cur->request->run_state = Request::RunState::job_continuation_run;
functions->ContinueMakeFunction();
}
}
else
{
main_log << log2 << "Job: request continuation task doesn't have a funtion set, return 500 internal error" << logend;
cur->request->http_status = Header::status_500_internal_server_error;
}
if( cur->request->run_state == Request::RunState::assigned_to_job )
{
log << log3 << "Job: this request (" << cur->request << ") has been moved to the job queue again" << logend;
Add(cur->request->job_id, cur->request, cur->request->job, priority);
}
else
{
cur->request->FinishRequest(); // jak cur->request->function bedzie null to nie zadzialaja funkcje templajtowe
load_avg->StopRequest(cur->request);
cur->request->Clear();
cur->request->run_state = Request::RunState::finished;
RemoveOldRequest(cur->request);
}
main_log << logendrequest;
}
// second thread (objects not locked)
void Job::DoWinixJob(pt::Space & job)
{
@@ -188,6 +370,28 @@ void Job::DoWinixJob(pt::Space & job)
// second thread (objects locked)
// use main_log for the logs to be in the correct order
void Job::RemoveOldRequest(Request * request)
{
std::list<Request>::iterator i = req_tab->begin();
while( i != req_tab->end() )
{
if( &(*i) == request )
{
main_log << log3 << "Job: removing request " << request << logend;
req_tab->erase(i);
break;
}
else
{
++i;
}
}
}
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2012-2014, Tomasz Sowa
* Copyright (c) 2012-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,22 +32,26 @@
*
*/
#ifndef headerfile_winix_core_jobs
#define headerfile_winix_core_jobs
#ifndef headerfile_winix_core_job
#define headerfile_winix_core_job
#include <vector>
#include <queue>
#include "basethread.h"
#include "space/space.h"
#include "jobtask.h"
#include "cur.h"
#include "loadavg.h"
#include "mounts.h"
namespace Winix
{
class Functions;
#define WINIX_JOBS_HOW_MANY_PRIORITIES 32
@@ -55,19 +59,35 @@ class Job : public BaseThread
{
public:
static const size_t PRIORITY_LOWEST = 0;
static const size_t PRIORITY_HIGHEST = 31;
static const size_t PRIORITY_DEFAULT = 16;
static const size_t PRIORITY_REQUEST_CONTINUATION = 17;
Job();
void SetCur(Cur * cur);
void SetFunctions(Functions * functions);
void SetLoadAvg(LoadAvg * load_avg);
void SetMounts(Mounts * mounts);
void SetReqTab(std::list<Request> * req_tab);
/*
add a new job to the queue
priority: 0-31 (0 - the lowest priority, 31 - the highest priority)
*/
void Add(pt::Space & job, int priority = 0);
void Add(pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(Request * request, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(long job_id, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
void Add(long job_id, Request * request, pt::Space & job, size_t priority = PRIORITY_DEFAULT);
/*
queue size, and size of all jobs in any priority
*/
size_t Size(int priority) const;
size_t Size(size_t priority) const;
size_t Size() const;
@@ -75,17 +95,23 @@ public:
true if specified queue is empty
or if all queues are empty
*/
bool Empty(int priority) const;
bool Empty(size_t priority) const;
bool Empty() const;
private:
typedef std::queue<pt::Space> JobsQueue;
Cur * cur;
Functions * functions;
LoadAvg * load_avg;
Mounts * mounts;
std::list<Request> * req_tab;
typedef std::queue<JobTask> JobsQueue;
typedef std::vector<JobsQueue> JobsQueueTab;
JobsQueueTab jobs_queue_tab;
void CheckPriority(int & priority) const;
void CheckPriority(size_t & priority) const;
void SaveToFile();
void ReadFromFile();
@@ -101,9 +127,11 @@ private:
bool SignalReceived();
void Do();
void DoQueue(JobsQueue & jobs_queue);
void DoJob(pt::Space & job);
void DoQueue(JobsQueue & jobs_queue, size_t priority);
void DoJob(JobTask & task, size_t priority);
void DoRequestContinuationJob(JobTask & job_task, size_t priority);
void DoWinixJob(pt::Space & job);
void RemoveOldRequest(Request * request);
};

84
winixd/core/jobtask.h Normal file
View File

@@ -0,0 +1,84 @@
/*
* 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) 2022, 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.
*
*/
#ifndef headerfile_winix_core_jobtask
#define headerfile_winix_core_jobtask
#include "space/space.h"
#include "core/request.h"
namespace Winix
{
class JobTask
{
public:
static const long JOB_TYPE_DEFAULT = 1;
static const long JOB_TYPE_REQUEST_CONTINUATION = 2;
/*
* the value of job_id will be defined by each controller
* so the default value is better to have -1 instead of for example 1
*/
static const long JOB_ID_DEFAULT = -1;
long job_type;
long job_id;
Request * request;
pt::Space job;
JobTask()
{
clear();
}
void clear()
{
job_type = JOB_TYPE_DEFAULT;
job_id = JOB_ID_DEFAULT;
request = nullptr;
job.clear();
}
};
}
#endif

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2014, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,14 +43,38 @@ namespace Winix
Mount::Mount()
{
Clear();
}
Mount::Mount(const Mount & m)
{
operator=(m);
}
Mount & Mount::operator=(const Mount & m)
{
dir_id = m.dir_id;
type = m.type;
fs = m.fs;
param = m.param;
return *this;
}
void Mount::Clear()
{
dir_id = -1;
type = -1;
fs = -1;
ClearParams();
}
void Mount::ClearParams()
{
size_t i;

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2014, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,10 @@ public:
Mount();
Mount(const Mount & m);
Mount & operator=(const Mount & m);
void Clear();
void ClearParams();
bool IsPar(int code);

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2014, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include "mountparser.h"
#include "log.h"
#include "misc.h"
#include "dirs.h"
namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2021, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,6 @@
#include <stdlib.h>
#include <limits.h>
#include "mount.h"
#include "dirs.h"
#include "models/item.h"
#include "winixmodeldeprecated.h"
@@ -49,6 +48,7 @@
namespace Winix
{
class Dirs;

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2021, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
#include "log.h"
#include "db/db.h"
#include "cur.h"
#include "dirs.h"
@@ -49,6 +50,7 @@ Mounts::Mounts()
{
pmount = &empty_mount;
skip_static = false;
dirs = nullptr;
}
@@ -99,7 +101,7 @@ void Mounts::CreateMounts()
CreateMountFs();
CreateMountPar();
plugin->Call((Session*)0, WINIX_ADD_MOUNTS);
plugin->Call(WINIX_ADD_MOUNTS);
empty_mount.param.resize(mount_par_tab.size());
empty_mount.ClearParams();
@@ -118,12 +120,6 @@ void Mounts::SetDb(Db * pdb)
db = pdb;
}
void Mounts::SetCur(Cur * pcur)
{
cur = pcur;
}
int Mounts::AddMountType(const wchar_t * type)
{
@@ -221,13 +217,11 @@ void Mounts::ReadMounts(const std::wstring & mounts)
mount_parser.Parse(mounts, mount_tab);
CalcCurMount();
// IMPROVE ME
// cur->mount is pointing to the empty mount (it is set in functions.cpp in CheckSpecialFile method)
// may would be better to call WINIX_FSTAB_CHANGED after the cur->mount is set?
// some plugins are using 'cur' object
plugin->Call((Session*)0, WINIX_FSTAB_CHANGED);
plugin->Call(WINIX_FSTAB_CHANGED);
}
@@ -292,7 +286,7 @@ void Mounts::MountCmsForRoot()
Mount * Mounts::CalcCurMount()
Mount * Mounts::CalcCurMount(Request * request)
{
std::vector<Item*>::reverse_iterator i;
@@ -300,10 +294,10 @@ std::vector<Item*>::reverse_iterator i;
// when the program starts (when the dir_tab is empty()
// we don't want to call MountCmsForRoot()
if( cur->request->dir_tab.empty() )
if( request->dir_tab.empty() )
return pmount;
for(i = cur->request->dir_tab.rbegin() ; i!=cur->request->dir_tab.rend() ; ++i)
for(i = request->dir_tab.rbegin() ; i!=request->dir_tab.rend() ; ++i)
{
std::map<long, Mount>::iterator m = mount_tab.find( (*i)->id );

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2009-2018, Tomasz Sowa
* Copyright (c) 2009-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,7 +42,6 @@
#include <vector>
#include "mount.h"
#include "error.h"
#include "dirs.h"
#include "db/db.h"
#include "request.h"
#include "mountparser.h"
@@ -51,7 +50,7 @@
namespace Winix
{
class Dirs;
@@ -115,7 +114,6 @@ public:
void SetDirs(Dirs * pdirs);
void SetDb(Db * pdb);
void SetCur(Cur * pcur);
// dir_id, mount_point
typedef std::map<long, Mount> MountTab;
@@ -126,7 +124,7 @@ public:
void ReadMounts(const std::wstring & mounts);
void ReadMounts();
Mount * CalcCurMount();
Mount * CalcCurMount(Request * request);
Mount * CalcMount(long dir_id);
// current mount point
@@ -146,7 +144,6 @@ private:
Db * db;
Dirs * dirs;
Cur * cur;
bool skip_static;

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,47 +48,6 @@ namespace Winix
{
/*
*
* PluginInfo
*
*
*/
void PluginInfo::set_dependency_for(WinixBase * winix_base)
{
plugin->SetDependencyFor(winix_base);
}
void PluginInfo::set_dependency_for(WinixBase & winix_base)
{
set_dependency_for(&winix_base);
}
void PluginInfo::set_dependency_for(WinixModelDeprecated * winix_model)
{
plugin->SetDependencyFor(winix_model);
//model_connector = winix_model->get_model_connector();
// CHECKME what about model_connector here?
}
void PluginInfo::set_dependency_for(WinixModelDeprecated & winix_model)
{
set_dependency_for(&winix_model);
}
/*
*
* Plugin
*
*
*/
void Plugin::UnloadPlugins()
{
size_t i;
@@ -113,6 +72,8 @@ Plugin::Plugin()
templates = nullptr;
session_manager = nullptr;
winix_request = nullptr;
plugin = this;
}
@@ -127,17 +88,6 @@ void Plugin::SetDb(Db * pdb)
db = pdb;
}
//void Plugin::SetConfig(Config * pconfig)
//{
// config = pconfig;
//}
void Plugin::SetCur(Cur * pcur)
{
cur = pcur;
}
void Plugin::SetSystem(System * psystem)
{
@@ -145,6 +95,12 @@ void Plugin::SetSystem(System * psystem)
}
void Plugin::SetCur(Cur * cur)
{
this->cur = cur;
}
void Plugin::SetFunctions(Functions * pfunctions)
{
functions = pfunctions;
@@ -157,12 +113,6 @@ void Plugin::SetTemplates(Templates * ptemplates)
}
//void Plugin::SetSynchro(Synchro * psynchro)
//{
// synchro = psynchro;
//}
void Plugin::SetSessionManager(SessionManager * psession_manager)
{
session_manager = psession_manager;
@@ -192,10 +142,10 @@ void Plugin::Unlock()
bool Plugin::SetDependency(PluginInfo & info)
bool Plugin::SetDependencyForPluginInfo(morm::ModelConnector * pmodel_connector, Log * plog, Cur * pcur, PluginInfo & info)
{
// for safety we call a plugin function only when all our pointers are not null
bool res = (db && config && cur && system && functions && templates && synchro && session_manager && winix_request);
bool res = (pmodel_connector && plog && pcur && db && config && system && functions && templates && synchro && session_manager && winix_request);
if( !res )
{
@@ -204,39 +154,22 @@ bool Plugin::SetDependency(PluginInfo & info)
info.db = db;
info.config = config;
info.cur = cur;
info.cur = pcur;
info.system = system;
info.functions = functions;
info.templates = templates;
info.synchro = synchro;
info.session_manager = session_manager;
info.plugin = this;
info.model_connector = pmodel_connector;;
/*
* FIXME
* if we call a message from a different thread then a different model connector is needed
* (each thread should have its own model connector)
*
*/
info.model_connector = system->get_model_connector();
info.log.set_log_buffer(plog->get_log_buffer());
info.log.set_file_log(plog->get_file_log());
info.log.SetDependency(&log);
return res;
return res;
}
void Plugin::SetDependencyFor(WinixBase * winix_base)
{
winix_base->set_dependency(winix_request);
}
void Plugin::SetDependencyFor(WinixModelDeprecated * winix_model)
{
winix_model->set_dependency(winix_request);
}
void Plugin::LoadPlugins(const std::wstring & plugins_dir, const std::vector<std::wstring> & plugins)
{
@@ -304,7 +237,7 @@ void * plugin_handle;
int old_current_plugin;
PluginInfo info;
if( !SetDependency(info) )
if( !SetDependencyForPluginInfo(model_connector, &log, cur, info) )
return;
if( !(plugin_handle = LoadInitFun(filename, fun_init)) )
@@ -315,6 +248,10 @@ PluginInfo info;
current_plugin = (int)plugins.size();
info.plugin_id = current_plugin;
/*
* WARNING:
* all pointers from Cur are null pointers here
*/
fun_init(info);
PluginsItem item;
@@ -362,19 +299,18 @@ bool Plugin::HasMessage(int message)
}
void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info)
void Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, Slots::iterator & slot, PluginInfo & info)
{
if( !SetDependency(info) )
if( !SetDependencyForPluginInfo(model_connector, plog, cur, info) )
return;
current_plugin = slot->second.index;
info.plugin_id = current_plugin;
info.session = ses;
if( current_plugin != -1 && ses )
info.plugin_data_base = ses->plugin_data.Get(current_plugin);
if( current_plugin != -1 && cur->session && !cur->session->is_temporary_session() )
info.plugin_data_base = cur->session->plugin_data.Get(current_plugin);
else
info.plugin_data_base = 0;
info.plugin_data_base = nullptr;
if( !slot->second.is_running )
{
@@ -411,136 +347,104 @@ void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_)
PluginRes Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, void * p1, void * p2, long l1, long l2)
{
PluginRes res;
int old_current_plugin = current_plugin;
PluginInfo info;
PluginRes res;
int old_current_plugin = current_plugin;
PluginInfo info;
Cur local_cur;
if( !cur )
cur = &local_cur;
Slots::iterator i = slots.lower_bound(message);
for( ; i!=slots.end() && i->first==message ; ++i )
{
info.Clear();
info.p1 = p1_;
info.p2 = p2_;
info.l1 = l1_;
info.l2 = l2_;
info.p1 = p1;
info.p2 = p2;
info.l1 = l1;
info.l2 = l2;
Call(ses, message, i, info);
Call(model_connector, plog, cur, message, i, info);
if( info.res )
++res.res_true;
else
++res.res_false;
}
current_plugin = old_current_plugin;
return res;
return res;
}
PluginRes Plugin::Call(morm::ModelConnector * model_connector, Log * plog, Session * session, Request * request, Mount * mount, int message, void * p1, void * p2, long l1, long l2)
{
Cur local_cur;
local_cur.session = session;
local_cur.request = request;
local_cur.mount = mount;
return Call(model_connector, plog, &local_cur, message, p1, p2, l1, l2);
}
PluginRes Plugin::Call(int message)
{
return Call(cur->session, message, 0, 0, 0, 0);
return Call(model_connector, &log, cur, message, 0, 0, 0, 0);
}
PluginRes Plugin::Call(int message, void * p1_)
{
return Call(cur->session, message, p1_, 0, 0, 0);
return Call(model_connector, &log, cur, message, p1_, 0, 0, 0);
}
PluginRes Plugin::Call(int message, void * p1_, void * p2_)
{
return Call(cur->session, message, p1_, p2_, 0, 0);
return Call(model_connector, &log, cur, message, p1_, p2_, 0, 0);
}
PluginRes Plugin::Call(int message, long l1_)
{
return Call(cur->session, message, 0, 0, l1_, 0);
return Call(model_connector, &log, cur, message, 0, 0, l1_, 0);
}
PluginRes Plugin::Call(int message, long l1_, long l2_)
{
return Call(cur->session, message, 0, 0, l1_, l2_);
return Call(model_connector, &log, cur, message, 0, 0, l1_, l2_);
}
PluginRes Plugin::Call(int message, void * p1_, long l1_)
{
return Call(cur->session, message, p1_, 0, l1_, 0);
return Call(model_connector, &log, cur, message, p1_, 0, l1_, 0);
}
PluginRes Plugin::Call(int message, void * p1_, long l1_, long l2_)
{
return Call(cur->session, message, p1_, 0, l1_, l2_);
return Call(model_connector, &log, cur, message, p1_, 0, l1_, l2_);
}
PluginRes Plugin::Call(int message, void * p1_, void * p2_, long l1_)
{
return Call(cur->session, message, p1_, p2_, l1_, 0);
return Call(model_connector, &log, cur, message, p1_, p2_, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message)
{
return Call(ses, message, 0, 0, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_)
{
return Call(ses, message, p1_, 0, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_)
{
return Call(ses, message, p1_, p2_, 0, 0);
}
PluginRes Plugin::Call(Session * ses, int message, long l1_)
{
return Call(ses, message, 0, 0, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message, long l1_, long l2_)
{
return Call(ses, message, 0, 0, l1_, l2_);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_)
{
return Call(ses, message, p1_, 0, l1_, 0);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, long l1_, long l2_)
{
return Call(ses, message, p1_, 0, l1_, l2_);
}
PluginRes Plugin::Call(Session * ses, int message, void * p1_, void * p2_, long l1_)
{
return Call(ses, message, p1_, p2_, l1_, 0);
}
size_t Plugin::Size()
{
return plugins.size();

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,8 +40,10 @@
#include <map>
#include "pluginmsg.h"
#include "plugindata.h"
#include "winixbase.h"
#include "winixmodeldeprecated.h"
#include "modelconnector.h"
#include "mount.h"
@@ -78,6 +80,7 @@ class WinixRequest;
class Plugin;
class Session;
class Request;
// move me to a different file
@@ -111,14 +114,6 @@ struct PluginInfo
morm::ModelConnector * model_connector;
// a session
// some messages are sent in a session's context e.g. logging a user
// this pointer in not always the same as cur->session, it is preferred
// to use this pointer instead of cur->session
// (cur->session can point at a temporary object)
// this pointer can be null
Session * session;
// pointer to the plugin session (can be null if not set by the plugin or if session is null)
// this is taken from session->plugin_data.Get()
// you should use WINIX_SESSION_CREATED and WINIX_PLUGIN_SESSION_DATA_REMOVE
@@ -130,13 +125,6 @@ struct PluginInfo
bool res;
void set_dependency_for(WinixBase * winix_base);
void set_dependency_for(WinixBase & winix_base);
void set_dependency_for(WinixModelDeprecated * winix_model);
void set_dependency_for(WinixModelDeprecated & winix_model);
void Clear()
{
// pointers to winix objects are not cleared here
@@ -147,7 +135,6 @@ struct PluginInfo
l2 = 0;
plugin_id = -1;
session = 0;
plugin_data_base = 0;
res = false;
@@ -173,11 +160,11 @@ struct PluginRes
class Plugin : public WinixBase
class Plugin : public WinixModelDeprecated
{
public:
// index of a plugin which is called by Call() method
// index of a plugin which is called by CallAllRegisteredMessages() method
// normally: -1
int current_plugin;
@@ -215,12 +202,10 @@ public:
~Plugin();
void SetDb(Db * pdb);
//void SetConfig(Config * pconfig);
void SetCur(Cur * pcur);
void SetSystem(System * psystem);
void SetCur(Cur * cur);
void SetFunctions(Functions * pfunctions);
void SetTemplates(Templates * ptemplates);
//void SetSynchro(Synchro * psynchro);
void SetSessionManager(SessionManager * psession_manager);
void SetWinixRequest(WinixRequest * winix_request);
@@ -244,16 +229,9 @@ public:
PluginRes Call(int message, void * p1_, long l1_);
PluginRes Call(int message, void * p1_, long l1_, long l2_);
PluginRes Call(int message, void * p1_, void * p2_, long l1_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_, long l2_);
PluginRes Call(Session * ses, int message);
PluginRes Call(Session * ses, int message, void * p1_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_);
PluginRes Call(Session * ses, int message, long l1_);
PluginRes Call(Session * ses, int message, long l1_, long l2_);
PluginRes Call(Session * ses, int message, void * p1_, long l1_);
PluginRes Call(Session * ses, int message, void * p1_, long l1_, long l2_);
PluginRes Call(Session * ses, int message, void * p1_, void * p2_, long l1_);
PluginRes Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, void * p1 = nullptr, void * p2 = nullptr, long l1 = 0, long l2 = 0);
PluginRes Call(morm::ModelConnector * model_connector, Log * plog, Session * session, Request * request, Mount * mount, int message, void * p1 = nullptr, void * p2 = nullptr, long l1 = 0, long l2 = 0);
// how many plugins there are
size_t Size();
@@ -269,15 +247,13 @@ public:
private:
Db * db;
//Config * config;
Cur * cur;
System * system;
Functions * functions;
Templates * templates;
//Synchro * synchro;
SessionManager * session_manager;
WinixRequest * winix_request;
WinixRequest * winix_request; // is it needed anymore? !!!!!!!!!!!!!!!!
std::wstring temp_path; // used when loading plugins
@@ -287,11 +263,10 @@ private:
Slots slots;
void * LoadInitFun(const wchar_t * filename, Fun1 & fun_init);
void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info);
void Call(morm::ModelConnector * model_connector, Log * plog, Cur * cur, int message, Slots::iterator & slot, PluginInfo & info);
bool SetDependency(PluginInfo & info);
void SetDependencyFor(WinixBase * winix_base);
void SetDependencyFor(WinixModelDeprecated * winix_model);
bool SetDependencyForPluginInfo(morm::ModelConnector * pmodel_connector, Log * plog, Cur * pcur, PluginInfo & info);
void Lock();
void Unlock();

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,6 +180,7 @@ namespace Winix
// the request is being ended
// you can clear some of your objects here
// in p1 you have a pointer to the Request object
#define WINIX_END_REQUEST 30140
// a new file (page) has been added
@@ -323,6 +324,13 @@ namespace Winix
// session is null
// if you process the job then return 'true' from the processing method (from plugin call)
// so this prevent to make a standard (system) job
// in l1 there is a job type (from JobTask structure), e.g. if you want to know whether
// the job is a request continuation you should compare l1 == JobTask::JOB_TYPE_REQUEST_CONTINUATION
// in l2 there is a job_id - the values passed to the Job::Add(long job_id, ...) method
// if you have called Add(...) without long job_id parameter then the default value JobTask::JOB_ID_DEFAULT is used
// if the job type is JobTask::JOB_TYPE_REQUEST_CONTINUATION then a pointer to Session can be set,
// such a Session has allow_to_delete flag set to false but of course you have to Lock/Unlock when
// you are using this structure
#define WINIX_JOB 31200

View File

@@ -70,7 +70,7 @@ void PostParser::Parse(FCGX_Stream * in, Request & request)
HttpSimpleParser::Parse();
if( has_winix_raw_post_msg )
plugin->Call(0, WINIX_RAW_POST_STRING, &raw_post);
plugin->Call(WINIX_RAW_POST_STRING, &raw_post);
raw_post.clear();
}
@@ -114,7 +114,7 @@ void PostParser::CreateLog(bool param_added, const std::wstring & name, const st
void PostParser::Parameter(std::wstring & name, std::wstring & value)
{
if( has_winix_post_params_msg )
plugin->Call(0, WINIX_POST_PARAMS, &name, &value);
plugin->Call(WINIX_POST_PARAMS, &name, &value);
bool added = request->AddPostVar(name, value);
CreateLog(added, name, value);

File diff suppressed because it is too large Load Diff

View File

@@ -51,6 +51,11 @@
#include "models.h"
#include "models/winixmodel.h"
#include "header.h"
#include "compress.h"
#include "plugin.h"
#include "mount.h"
#include "mounts.h"
namespace Winix
@@ -60,7 +65,7 @@ namespace Winix
class FunctionBase;
class Templates;
@@ -87,6 +92,15 @@ public:
*/
size_t id;
// the state of the request
// not_assigned - the object is not being used
// normal_run - run in the main thread, this state is set after a new request is made
// assigned_to_job - the request is preserved and a new job will be called
// job_run - run in the job thread (objects are locked)
// finished - the request is finished and the object can be removed
enum RunState { not_assigned = 0, normal_run, assigned_to_job, job_run, job_continuation_run, finished};
RunState run_state;
/*
* request start time
@@ -230,13 +244,23 @@ public:
// null if there is no a function
FunctionBase * function;
// current session (if exists, can be null)
Session * session;
// current mount point (can be null, it is treated as cms filesystem then)
Mount * mount;
// parameters (name:value)
ParamTab param_tab;
// this is a pointer either to the item (if exists) or to the last directory
Item * last_item;
// can we use gzip compression algorithm when sending content to the client
bool accept_gzip;
// can we use deflate compression algorithm when sending content to the client
bool accept_deflate;
/*
@@ -412,16 +436,24 @@ public:
std::vector<Item> item_tab;
/*
* FastCGI request structure with pointers to input/output streams
*/
FCGX_Request fcgi_request;
long job_id;
pt::Space job;
Request();
void SetConfig(Config * pconfig);
void SetConfig(Config * config);
void SetTemplates(Templates * templates);
void SetCompress(Compress * compress);
void SetPlugin(Plugin * plugin);
void SetMounts(Mounts * mounts);
void fields();
@@ -473,10 +505,34 @@ public:
bool has_frame(const wchar_t * frame);
bool has_frame(const std::wstring & frame);
void create_job(long job_id);
void modify_status_code_if_needed();
// RENAMEME to add_header_if_not_exists
bool AddHeader(const wchar_t * name, const wchar_t * value);
bool AddHeader(const std::wstring & name, const std::wstring & value);
bool AddHeader(const wchar_t * name, const pt::WTextStream & value);
bool AddHeader(const std::wstring & name, const pt::WTextStream & value);
void FinishRequest();
private:
Config * config;
Templates * templates;
Compress * compress;
Plugin * plugin;
Mounts * mounts;
BinaryPage output_8bit;
BinaryPage compressed_output;
pt::WTextStream output_tmp_filtered_stream;
pt::TextStream serialized_model;
std::string aheader_name, aheader_value;
std::wstring cookie_id_string;
std::string send_data_buf;
// used in ParamValue() and PostVar() when there is no such a param
const std::wstring str_empty;
@@ -493,6 +549,45 @@ private:
void http_status_error_title(EzcEnv & env);
void http_status_error_description(EzcEnv & env);
void SendAnswer();
void PrepareRawAnswer();
void PrepareJsonAnswer();
void PrepareXmlAnswer();
void PrepareCsvAnswer();
void PrepareContenerizedAnswer();
void PutSeparatorIfNeeded(bool put_separator);
void SerializeFieldJson(const wchar_t * field_name);
void SerializeStream(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamJson(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamXml(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeStreamCsv(const pt::WTextStream & input_stream, const wchar_t * field_name);
void SerializeAllFrames();
void SerializeSpecificFrames();
void SerializeModels();
void SerializeModel(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelJson(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelXml(morm::Wrapper & wrapper, const wchar_t * field_name);
void SerializeModelCsv(morm::Wrapper & wrapper, const wchar_t * field_name);
void FilterHtmlIfNeeded(const pt::WTextStream & input_stream, BinaryPage & output, bool clear_stream = true);
void Send8bitOutput(BinaryPage & output);
void SendData(const BinaryPage & page, FCGX_Stream * out);
void UseEzcGenerator();
int SelectDeflateVersion();
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
void PrepareSessionCookie();
void PrepareHeaders(bool compressing, int compress_encoding, size_t output_size);
void ModifyStatusForRedirect();
void PrepareSendFileHeaderForStaticMountpoint();
void PrepareSendFileHeader();
void PrepareContentEncodingHeader(int compress_encoding);
void PrepareContentLengthHeader(size_t output_size);
void PrepareHeaderContentType();
void PrepareHeaderStatus(int http_status);
void SendHeaders();
void SendCookies();
bool CreateStaticResourcePath(pt::WTextStream & out_path);
bool CanSendContent();
void LogRequestTime();
MORM_MEMBER_FIELD(Request)

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -97,6 +97,7 @@ void Session::Clear(bool clear_plugin_data)
new_session = true;
spam_score = 0;
remove_me = false;
allow_to_delete = true;
start_time = 0;
last_time = 0;
@@ -121,6 +122,11 @@ void Session::ClearAfterRequest()
}
bool Session::is_temporary_session() const
{
return id == 0;
}
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,7 +66,7 @@ public:
void ClearAfterRequest();
// 0 - means that there is a temporary session
// 0 - means that this is a temporary session
long id;
// a session index
@@ -101,10 +101,17 @@ public:
bool remember_me;
// if true then this session will be removed by SessionManager
// without checking the time expiration
// if remove_me is true and if allow_to_delete is true then this session will be
// removed by SessionManager without checking the time expiration
bool remove_me;
// if the session can be removed then this value is true (default)
// if we continue a request from a controller to a job
// then we set this value to false in order for the SessionManager
// to not delete this
bool allow_to_delete;
PluginData plugin_data;
@@ -133,6 +140,8 @@ public:
bool is_temporary_session() const;
};

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2018, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -82,7 +82,7 @@ Table::iterator i = table.begin();
{
if( i->plugin_data.HasAllocatedData() )
{
plugin->Call(&*i, WINIX_PLUGIN_SESSION_DATA_REMOVE); // the session passed here is ok?
plugin->Call(model_connector, &log, &*i, nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE, nullptr, nullptr, 0, 0); // the session passed here is ok?
}
//i->plugin_data.DeleteAll(); // it's better to call it here instead in the destructor
@@ -116,7 +116,7 @@ IndexId::iterator i = index_id.find(id);
if( i->second->plugin_data.HasAllocatedData() )
{
plugin->Call(&*(i->second), WINIX_PLUGIN_SESSION_DATA_REMOVE); // the session passed here is ok?
plugin->Call(model_connector, &log, &*(i->second), nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE, nullptr, nullptr, 0, 0); // the session passed here is ok?
}
//i->second->plugin_data.DeleteAll();

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
#include "session.h"
#include "sessionparser.h"
#include "functions/functionbase.h"
#include "system.h"
@@ -558,7 +559,7 @@ SessionContainer::Iterator SessionManager::SessionEnd()
// called from the main thread (from App::Close)
void SessionManager::DeleteSessions()
{
SessionContainer::Iterator i;
@@ -567,7 +568,7 @@ void SessionManager::DeleteSessions()
{
if( i->puser && !i->remember_me )
{
plugin->Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, i->puser, nullptr, 0, 0);
last_container->UserLogout(i->puser->id, i->id);
}
}
@@ -599,7 +600,7 @@ SessionContainer::Iterator i = session_tab.FindById(old_id);
}
if( changed )
plugin->Call(&(*i), WINIX_SESSION_CHANGED_ID, old_id, new_id);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_SESSION_CHANGED_ID, nullptr, nullptr, old_id, new_id);
else
main_log << log1 << "SM: I cannot create a new session id (still uses old one)" << logend;
}
@@ -612,19 +613,20 @@ return changed;
}
// called from the main thread (from App::Init)
void SessionManager::InitTmpSession()
{
Session * old_session = cur->session;
main_log << log4 << "SM: initializing temporary session" << logend;
cur->session = &temporary_session;
plugin->Call(WINIX_SESSION_CREATED);
plugin->Call(main_model_connector, &main_log, nullptr, WINIX_SESSION_CREATED);
cur->session = old_session;
}
// called from the main thread at the and (from App::Close)
void SessionManager::UninitTmpSession()
{
Session * old_session = cur->session;
@@ -635,18 +637,16 @@ void SessionManager::UninitTmpSession()
if( cur->session->plugin_data.HasAllocatedData() )
{
plugin->Call(cur->session, WINIX_PLUGIN_SESSION_DATA_REMOVE);
plugin->Call(main_model_connector, &main_log, cur->session, nullptr, nullptr, WINIX_PLUGIN_SESSION_DATA_REMOVE);
}
//cur->session->plugin_data.DeleteAll(); // this will call plugin.Call(WINIX_PLUGIN_SESSION_DATA_REMOVE);
cur->session->plugin_data.Resize(0);
cur->session = old_session;
}
// called from the main thread (from App::Init)
void SessionManager::LoadSessions()
{
SessionParser sp;
@@ -665,7 +665,7 @@ SessionContainer::Iterator i;
for(i=session_tab.Begin() ; i != session_tab.End() ; ++i)
{
i->plugin_data.Resize(plugin->Size());
plugin->Call(&(*i), WINIX_SESSION_CREATED);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_SESSION_CREATED);
/*
!! IMPROVE ME
@@ -673,7 +673,7 @@ SessionContainer::Iterator i;
*/
if( i->puser )
plugin->Call(&(*i), WINIX_USER_LOGGED);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_USER_LOGGED);
}
}
else
@@ -758,7 +758,7 @@ size_t SessionManager::MarkAllSessionsToRemove(long user_id)
{
if( i->puser && i->puser->id == user_id )
{
plugin->Call(&(*i), WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
plugin->Call(main_model_connector, &main_log, &(*i), nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, i->puser);
last_container->UserLogout(i->puser->id, i->id);
i->remove_me = true;
i->puser = 0;
@@ -871,7 +871,7 @@ const int deleted_max_at_once = 10;
}
else
{
if( i->remove_me || IsSessionOutdated(*i) )
if( i->allow_to_delete && (i->remove_me || IsSessionOutdated(*i)) )
{
Session * ses = &(*i);
++i;
@@ -917,16 +917,16 @@ void SessionManager::DeleteSession(Session * del_session)
{
if( del_session->puser )
{
plugin->Call(del_session, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser);
plugin->Call(model_connector, &log, del_session, nullptr, nullptr, WINIX_PREPARE_USER_TO_LOGOUT, del_session->puser, nullptr, 0, 0);
last_container->UserLogout(del_session->puser->id, del_session->id);
del_session->puser = 0;
}
long id = del_session->id;
plugin->Call(del_session, WINIX_PREPARE_SESSION_TO_REMOVE);
plugin->Call(model_connector, &log, del_session, nullptr, nullptr, WINIX_PREPARE_SESSION_TO_REMOVE, del_session->puser, nullptr, 0, 0);
session_tab.EraseById(del_session->id);
plugin->Call((Session*)0, WINIX_SESSION_REMOVED, id);
plugin->Call(model_connector, &log, nullptr, WINIX_SESSION_REMOVED, nullptr, nullptr, id, 0);
}

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2019, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,6 @@
#include "config.h"
#include "request.h"
#include "lastcontainer.h"
#include "system.h"
#include "synchro.h"
#include "basethread.h"
#include "sessionidmanager.h"

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2021, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -137,7 +137,6 @@ bool System::Init()
mounts.SkipStaticDirs(config->dont_use_static_dirs);
mounts.SetDirs(&dirs);
mounts.SetDb(db);
mounts.SetCur(cur); // only one method is using cur, can be passed as a parameter to the method
mounts.CreateMounts();
mounts.ReadMounts();
@@ -168,6 +167,12 @@ bool System::Init()
if( !thread_manager.Add(&image, L"image") )
return false;
job.SetCur(cur);
job.SetFunctions(functions);
job.SetLoadAvg(&load_avg);
job.SetMounts(&mounts);
job.SetReqTab(&req_tab);
// SetSynchro will be called by ThreadManager itself
// job.ReadFromFile();
if( !thread_manager.Add(&job, L"job") )
@@ -1440,7 +1445,7 @@ bool System::FollowAllLinks(const std::wstring & link_to,
log << log3 << "System: current directory changed and the new file loaded" << logend;
}
mounts.CalcCurMount();
mounts.CalcCurMount(cur->request);
}
else
{
@@ -1522,5 +1527,28 @@ bool System::AddCommonFileToVar(const wchar_t * file_path, const wchar_t * url,
void System::DeleteOldRequests(bool leave_one_object)
{
std::list<Request>::iterator i = req_tab.begin();
while( i != req_tab.end() )
{
// leave at least one object (even if it is finished)
if( i->run_state == Request::RunState::finished && (!leave_one_object || req_tab.size() > 1) )
{
log << log3 << "System: removing finished request " << cur->request << logend;
std::list<Request>::iterator old_i = i;
++i;
req_tab.erase(old_i);
}
else
{
++i;
}
}
}
} // namespace Winix

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2018, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -108,6 +108,9 @@ public:
// when winix starts
TimeZones time_zones;
// list of requests, if a request is to be continued in a job then it is preserved in the req_tab
// and a new Request is inserted for the next incoming request
std::list<Request> req_tab;
using WinixModelDeprecated::get_model_connector;
@@ -221,6 +224,7 @@ public:
void CreateItemLink(const Item & item, std::wstring & link, bool clear_str = true);
void DeleteOldRequests(bool leave_one_object = false);
private:

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2011-2021, Tomasz Sowa
* Copyright (c) 2011-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -121,6 +121,7 @@ bool ThreadManager::Add(BaseThread * pbase, const wchar_t * thread_name)
data.model_connector.set_winix_time_zones(nullptr); // null for a moment, may will be changed
data.model_connector.set_winix_pattern_cacher(nullptr); // null for a moment, may will be changed
item.object->set_main_model_connector(get_model_connector());
item.object->set_model_connector(&data.model_connector);
if( were_started )

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2018-2021, Tomasz Sowa
* Copyright (c) 2018-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,7 +69,7 @@ void WinixBase::set_log_buffer(pt::WTextStream * log_buffer)
}
void WinixBase::set_file_log(FileLog * file_log)
void WinixBase::set_file_log(pt::FileLog * file_log)
{
log.set_file_log(file_log);
}

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2018-2021, Tomasz Sowa
* Copyright (c) 2018-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,7 @@ public:
void set_config(Config * config);
void set_synchro(Synchro * synchro);
void set_log_buffer(pt::WTextStream * log_buffer);
void set_file_log(FileLog * file_log);
void set_file_log(pt::FileLog * file_log);
Log * get_logger();

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2018-2021, Tomasz Sowa
* Copyright (c) 2018-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,12 +36,16 @@
#define headerfile_winix_core_winixmodel
#include "core/winixbase.h"
#include "plugin.h"
#include "morm.h"
namespace Winix
{
/*
* Plugin class is based on WinixModelDeprecated so we cannot include plugin.h here
*/
class Plugin;
// may rename it to WinixConnector or WinixStorage?
class WinixModelDeprecated : public WinixBase