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:
@@ -40,20 +40,21 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <curl/curl.h>
|
||||
#include "core/app.h"
|
||||
#include "core/version.h"
|
||||
#include "core/lock.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "mainoptions/mainoptionsparser.h"
|
||||
#include "pikotools/version.h"
|
||||
#include "tito.h"
|
||||
#include "runstatus.h"
|
||||
|
||||
|
||||
|
||||
namespace Winix
|
||||
{
|
||||
|
||||
|
||||
|
||||
/*
|
||||
application object
|
||||
*/
|
||||
@@ -104,6 +105,42 @@ void print_syntax()
|
||||
|
||||
|
||||
|
||||
RunStatus ParseParameters(int argc, const char ** argv, pt::Space & options)
|
||||
{
|
||||
pt::Space arguments;
|
||||
pt::MainOptionsParser options_parser;
|
||||
RunStatus run_status;
|
||||
|
||||
arguments.add(L"c", 1);
|
||||
arguments.add(L"config", 1);
|
||||
|
||||
pt::MainOptionsParser::Status status = options_parser.parse(argc, argv, options, arguments);
|
||||
|
||||
if( status != pt::MainOptionsParser::status_ok )
|
||||
{
|
||||
Winix::print_syntax();
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_PARAMETERS_SYNTAX_ERROR;
|
||||
run_status.should_continue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( options.has_key(L"h") || options.has_key(L"help") || options.has_key(L"?") )
|
||||
{
|
||||
Winix::print_syntax();
|
||||
run_status.should_continue = false;
|
||||
}
|
||||
|
||||
if( options.has_key(L"v") || options.has_key(L"version") )
|
||||
{
|
||||
Winix::print_version();
|
||||
run_status.should_continue = false;
|
||||
}
|
||||
}
|
||||
|
||||
return run_status;
|
||||
}
|
||||
|
||||
|
||||
void CreateNewDescriptor(int des_dst, int flags)
|
||||
{
|
||||
int descriptor;
|
||||
@@ -278,50 +315,56 @@ bool ReadConfigs(const pt::Space & options, const char ** env)
|
||||
return status;
|
||||
}
|
||||
|
||||
} // namespace Winix
|
||||
|
||||
|
||||
|
||||
int main(int argc, const char ** argv, const char ** env)
|
||||
bool InitCurlLibrary()
|
||||
{
|
||||
using Winix::app;
|
||||
/*
|
||||
*
|
||||
* from documentation https://curl.se/libcurl/c/curl_global_init.html
|
||||
* This function is thread-safe since libcurl 7.84.0 if curl_version_info has the CURL_VERSION_THREADSAFE
|
||||
* feature bit set (most platforms).
|
||||
*
|
||||
* If this is not thread-safe, you must not call this function when any other thread in the program
|
||||
* (i.e. a thread sharing the same memory) is running. This does not just mean no other thread that
|
||||
* is using libcurl. Because curl_global_init calls functions of other libraries that are similarly
|
||||
* thread unsafe, it could conflict with any other thread that uses these other libraries.
|
||||
*
|
||||
*/
|
||||
CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
|
||||
bool ok = (code == CURLE_OK);
|
||||
|
||||
std::srand(std::time(0));
|
||||
app.system.system_start = time(0);
|
||||
|
||||
pt::Space options;
|
||||
pt::Space arguments;
|
||||
pt::MainOptionsParser options_parser;
|
||||
|
||||
arguments.add(L"c", 1);
|
||||
arguments.add(L"config", 1);
|
||||
|
||||
pt::MainOptionsParser::Status status = options_parser.parse(argc, argv, options, arguments);
|
||||
|
||||
if( status != pt::MainOptionsParser::status_ok )
|
||||
if( !ok )
|
||||
{
|
||||
Winix::print_syntax();
|
||||
return 6;
|
||||
std::cout << "Cannot initialize curl library, exiting" << std::endl;
|
||||
}
|
||||
|
||||
if( options.has_key(L"h") || options.has_key(L"help") || options.has_key(L"?") )
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void CleanupCurlLibrary()
|
||||
{
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
RunStatus InitializeWinix(Log & log, pt::Space & options, const char ** env)
|
||||
{
|
||||
RunStatus run_status;
|
||||
|
||||
if( !InitCurlLibrary() )
|
||||
{
|
||||
Winix::print_syntax();
|
||||
return 0;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_INITIALIZE_CURL;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
if( options.has_key(L"v") || options.has_key(L"version") )
|
||||
if( !ReadConfigs(options, env) )
|
||||
{
|
||||
Winix::print_version();
|
||||
return 0;
|
||||
}
|
||||
pt::WTextStream * log_buffer = log.get_log_buffer();
|
||||
|
||||
Winix::Log & log = app.GetMainLog();
|
||||
pt::WTextStream * log_buffer = log.get_log_buffer();
|
||||
Winix::LogInfo(log, Winix::log3, "UTC booting Winix", true, ""); // date will be printed as UTC because the time zones are not loaded yet
|
||||
|
||||
if( !Winix::ReadConfigs(options, env) )
|
||||
{
|
||||
// we need to print the buffer by hand because the logger
|
||||
// is not fully initialized yet
|
||||
if( log_buffer && !log_buffer->empty() )
|
||||
@@ -329,21 +372,26 @@ using Winix::app;
|
||||
pt::wide_stream_to_utf8(*log_buffer, std::cout);
|
||||
}
|
||||
|
||||
return 2;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_CORRECTLY_READ_CONFIG;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
if( options.has_key(L"dump-config") )
|
||||
{
|
||||
pt::WTextStream * log_buffer = log.get_log_buffer();
|
||||
|
||||
if( log_buffer )
|
||||
{
|
||||
log << "all read config options (some of the values could have been modified by winix"
|
||||
<< " but the modified values are not printed here):" << Winix::logend;
|
||||
<< " but the modified values are not printed here):" << logend;
|
||||
app.config.space.serialize_to_space_stream(*log_buffer, true);
|
||||
log << Winix::logend;
|
||||
log << logend;
|
||||
pt::wide_stream_to_utf8(*log_buffer, std::cout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
app.InitLoggers();
|
||||
@@ -352,55 +400,105 @@ using Winix::app;
|
||||
app.config.log_stdout = false;
|
||||
|
||||
if( !app.config.log_stdout )
|
||||
Winix::CloseDescriptors();
|
||||
CloseDescriptors();
|
||||
|
||||
if( app.config.demonize && !app.Demonize() )
|
||||
{
|
||||
log << Winix::logsave;
|
||||
return 4;
|
||||
log << logsave;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_DEMONIZE;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
if( !app.InitFCGI() )
|
||||
{
|
||||
log << Winix::logsave;
|
||||
return 5;
|
||||
/*
|
||||
* WARNING:
|
||||
* when there is a problem with initializing FastCGI FCGX_OpenSocket() will call exit()
|
||||
* and we never reach here
|
||||
*/
|
||||
log << logsave;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_INITIALIZE_FASTCGI;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
if( !app.DropPrivileges() )
|
||||
{
|
||||
log << Winix::logsave;
|
||||
return 3;
|
||||
log << logsave;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_DROP_PRIVILEGES;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
app.LogUserGroups();
|
||||
Winix::SavePidFile(log);
|
||||
SavePidFile(log);
|
||||
|
||||
// app.Init() starts other threads as well (they will be waiting on the lock)
|
||||
if( !app.Init() )
|
||||
{
|
||||
Winix::RemovePidFile();
|
||||
log << Winix::logsave;
|
||||
return 1;
|
||||
run_status.exit_code = RunStatus::EXIT_CODE_CANNOT_INITIALIZE_APPLICATION;
|
||||
run_status.should_continue = false;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
app.StartThreads();
|
||||
// now we have more threads, we should use Lock() and Unlock()
|
||||
|
||||
// saving all starting logs
|
||||
app.Lock();
|
||||
Winix::LogInfo(log, Winix::log1, "Winix", true, "started");
|
||||
log << Winix::logsave;
|
||||
app.Unlock();
|
||||
|
||||
// main loop
|
||||
app.Start();
|
||||
|
||||
app.Close();
|
||||
|
||||
Winix::LogInfo(log, Winix::log1, "Winix", true, "stopped");
|
||||
Winix::RemovePidFile();
|
||||
log << Winix::logsave;
|
||||
|
||||
return 0;
|
||||
return run_status;
|
||||
}
|
||||
|
||||
|
||||
void UninitializeWinix(Log & log)
|
||||
{
|
||||
Winix::RemovePidFile();
|
||||
log << Winix::logsave;
|
||||
Winix::CleanupCurlLibrary();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Winix
|
||||
|
||||
|
||||
|
||||
int main(int argc, const char ** argv, const char ** env)
|
||||
{
|
||||
using Winix::app;
|
||||
|
||||
Winix::RunStatus run_status;
|
||||
pt::Space options;
|
||||
|
||||
std::srand(std::time(0));
|
||||
app.system.system_start = time(0);
|
||||
|
||||
run_status = Winix::ParseParameters(argc, argv, options);
|
||||
|
||||
if( !run_status.should_continue )
|
||||
return run_status.exit_code;
|
||||
|
||||
Winix::Log & log = app.GetMainLog();
|
||||
Winix::LogInfo(log, Winix::log3, "UTC booting Winix", true, ""); // date will be printed as UTC because the time zones are not loaded yet
|
||||
|
||||
run_status = Winix::InitializeWinix(log, options, env);
|
||||
|
||||
if( run_status.should_continue )
|
||||
{
|
||||
app.StartThreads();
|
||||
// now we are in multi threaded environment, we should use our locking mechanism
|
||||
|
||||
// saving all starting logs (logger can be used without locking)
|
||||
Winix::LogInfo(log, Winix::log1, "Winix", true, "started");
|
||||
log << Winix::logsave;
|
||||
|
||||
// start the main loop
|
||||
app.Start();
|
||||
|
||||
// close winix
|
||||
app.Close();
|
||||
// now all other threads are terminated, we are in single threaded environment again
|
||||
}
|
||||
|
||||
Winix::LogInfo(log, Winix::log1, "Winix", true, "stopped");
|
||||
UninitializeWinix(log);
|
||||
|
||||
return run_status.exit_code;
|
||||
}
|
||||
|
||||
|
69
winixd/main/runstatus.h
Normal file
69
winixd/main/runstatus.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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_main_runstatus
|
||||
#define headerfile_winix_main_runstatus
|
||||
|
||||
|
||||
namespace Winix
|
||||
{
|
||||
|
||||
|
||||
struct RunStatus
|
||||
{
|
||||
const static int EXIT_CODE_OK = 0;
|
||||
const static int EXIT_CODE_CANNOT_INITIALIZE_APPLICATION = 1;
|
||||
const static int EXIT_CODE_CANNOT_CORRECTLY_READ_CONFIG = 2;
|
||||
const static int EXIT_CODE_CANNOT_DROP_PRIVILEGES = 3;
|
||||
const static int EXIT_CODE_CANNOT_DEMONIZE = 4;
|
||||
const static int EXIT_CODE_CANNOT_INITIALIZE_FASTCGI = 5;
|
||||
const static int EXIT_CODE_PARAMETERS_SYNTAX_ERROR = 6;
|
||||
const static int EXIT_CODE_CANNOT_INITIALIZE_CURL = 7;
|
||||
|
||||
int exit_code;
|
||||
bool should_continue;
|
||||
|
||||
RunStatus()
|
||||
{
|
||||
exit_code = EXIT_CODE_OK;
|
||||
should_continue = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user