35 m_transceiver(
std::bind(
38 std::placeholders::_1,
39 std::placeholders::_2)),
46 m_managementRecordCount(0),
47 m_badSocketMessageCount(0),
48 m_badSocketKillCount(0),
50 m_activeThreads(threads),
55 FAIL_LOG(
"You're not allowed to have multiple manager instances")
57 DIAG_LOG(
"Manager_base::Manager_base(): Initialized")
79 DIAG_LOG(
"Starting fastcgi++ manager")
84 if(!thread.joinable())
87 thread.swap(newThread);
102 struct sigaction sigAction;
104 sigemptyset(&sigAction.sa_mask);
105 sigAction.sa_flags=0;
107 sigaction(SIGPIPE, &sigAction, NULL);
108 sigaction(SIGUSR1, &sigAction, NULL);
109 sigaction(SIGTERM, &sigAction, NULL);
120 DIAG_LOG(
"Received SIGUSR1. Stopping fastcgi++ manager.")
124 WARNING_LOG(
"Received SIGUSR1 but fastcgi++ manager isn't "\
132 DIAG_LOG(
"Received SIGTERM. Terminating fastcgi++ manager.")
136 WARNING_LOG(
"Received SIGTERM but fastcgi++ manager isn't "\
149 message = std::move(
m_messages.front().first);
154 if(message.
type == 0)
177 if(std::equal(name, value,
"FCGI_MAX_CONNS"))
180 reinterpret_cast<const char*>(
192 if(std::equal(name, value,
"FCGI_MAX_REQS"))
195 reinterpret_cast<const char*>(
207 if(std::equal(name, value,
"FCGI_MPXS_CONNS"))
210 reinterpret_cast<const char*>(
251 ERROR_LOG(
"Got a non-FastCGI record destined for the manager")
256 std::unique_lock<std::shared_timed_mutex> requestsWriteLock(
260 std::shared_lock<std::shared_timed_mutex> requestsReadLock(
m_requestsMutex);
264 requestsReadLock.unlock();
275 requestsReadLock.lock();
279 std::unique_lock<std::mutex> requestLock(
280 request->second->mutex,
282 requestsReadLock.unlock();
286 auto lock = request->second->handler();
287 if(!lock || !
id.m_socket.valid())
289 #if FASTCGIPP_LOG_LEVEL > 3 290 if(!
id.m_socket.valid())
291 ++m_badSocketKillCount;
295 requestsWriteLock.lock();
296 requestLock.unlock();
298 requestsWriteLock.unlock();
302 requestLock.unlock();
308 requestsReadLock.unlock();
313 requestsReadLock.lock();
316 requestsReadLock.unlock();
317 #if FASTCGIPP_LOG_LEVEL > 3 321 #if FASTCGIPP_LOG_LEVEL > 3 325 m_maxActiveThreads = std::max(m_activeThreads, m_maxActiveThreads);
328 requestsReadLock.lock();
336 #if FASTCGIPP_LOG_LEVEL > 3 337 ++m_managementRecordCount;
340 m_messages.push(std::make_pair(std::move(message),
id.m_socket));
344 #if FASTCGIPP_LOG_LEVEL > 3 345 ++m_badSocketMessageCount;
348 const auto range =
m_requests.equal_range(
id.m_socket);
349 auto request = range.first;
350 while(request != range.second)
352 std::unique_lock<std::mutex> lock(
353 request->second->mutex,
359 #if FASTCGIPP_LOG_LEVEL > 3 360 ++m_badSocketKillCount;
370 #if FASTCGIPP_LOG_LEVEL > 3 377 if(message.type == 0)
389 std::piecewise_construct,
390 std::forward_as_tuple(
id),
391 std::forward_as_tuple()).first;
398 #if FASTCGIPP_LOG_LEVEL > 3 400 m_maxRequests = std::max(m_maxRequests,
m_requests.size());
404 WARNING_LOG(
"Got a non BEGIN_REQUEST record for a request"\
405 " that doesn't exist")
410 request->second->push(std::move(message));
421 DIAG_LOG(
"Manager_base::~Manager_base(): New requests ============== " \
423 DIAG_LOG(
"Manager_base::~Manager_base(): Max concurrent requests === " \
425 DIAG_LOG(
"Manager_base::~Manager_base(): Management records ======== " \
426 << m_managementRecordCount)
427 DIAG_LOG(
"Manager_base::~Manager_base(): Bad socket messages ======= " \
428 << m_badSocketMessageCount)
429 DIAG_LOG(
"Manager_base::~Manager_base(): Bad socket request kills == " \
430 << m_badSocketKillCount)
431 DIAG_LOG(
"Manager_base::~Manager_base(): Request messages received = " \
433 DIAG_LOG(
"Manager_base::~Manager_base(): Maximum active threads ==== " \
434 << m_maxActiveThreads)
435 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining requests ======== " \
437 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining tasks =========== " \
439 DIAG_LOG(
"Manager_base::~Manager_base(): Remaining local messages == " \
std::vector< std::thread > m_threads
Threads our manager is running in.
Topmost namespace for the fastcgi++ library.
void send(const Socket &socket, Block &&data, bool kill)
Queue up a block of data for transmission.
RecordType type
Unknown record type.
const ManagementReply< 13, 2 > maxReqsReply
The maximum allowed requests at a time.
bool m_terminate
True when the manager should be terminating.
Transceiver m_transceiver
Handles low level communication with the other side.
General task and protocol management class base.
bool processParamHeader(const char *data, const char *const dataEnd, const char *&name, const char *&value, const char *&end)
Process the body of a FastCGI record of type RecordType::PARAMS.
static void setupSignals()
Configure the handlers for POSIX signals.
void header(Level level)
Send a log header to logstream.
void join()
Block until a stop() or terminate() is called and completed.
void handler()
General handling function to have it's own thread.
Data structure used to pass messages to requests.
virtual std::unique_ptr< Request_base > makeRequest(const Protocol::RequestId &id, const Protocol::Role &role, bool kill)=0
Make a request object.
const ManagementReply< 15, 1 > mpxsConnsReply
Where or not requests can be multiplexed over a single connections.
BigEndian< Role > role
Role.
void join()
Block until a stop() or terminate() is called and completed.
Declares the Manager class.
#define FASTCGIPP_LOG_LEVEL
const uint16_t badFcgiId
Constant that defines a bad/special FcgiId.
The body for FastCGI records with a RecordType of UNKNOWN_TYPE.
std::queue< std::pair< Message, Socket > > m_messages
Local messages.
bool m_stop
True when the manager should be stopping.
void terminate()
Call from any thread to terminate the handler() thread.
std::mutex m_messagesMutex
Thread safe our local messages.
std::condition_variable m_wake
Condition variable to wake handler() threads up.
void start()
Call from any thread to start the Manager.
static void signalHandler(int signum)
General function to handler POSIX signals.
void start()
Call from any thread to start the handler() thread.
void localHandler()
Handles management messages.
Class for representing an OS level I/O socket.
A unique identifier for each FastCGI request.
void push(Protocol::RequestId id, Message &&message)
Pass a message to a request.
std::mutex m_tasksMutex
Thread safe our tasks.
Block data
The raw data being passed along with the message.
void stop()
Call from any thread to stop the handler() thread.
std::shared_timed_mutex m_requestsMutex
Thread safe our requests.
bool kill() const
Get keep alive value from the record body.
The body for FastCGI records with a RecordType of BEGIN_REQUEST.
void terminate()
Call from any thread to terminate the Manager.
Manager_base(unsigned threads)
Sole constructor.
void stop()
Call from any thread to stop the Manager.
Protocol::Requests< std::unique_ptr< Request_base > > m_requests
An associative container for our requests.
#define FAIL_LOG(data)
Log any "errors" that cannot be recovered from and then exit.
char * end()
Pointer to 1+ the last element.
static Manager_base * instance
Pointer to the Manager object.
#define ERROR_LOG(data)
Log any "errors" that can be recovered from.
Declares the Fastcgipp debugging/logging facilities.
const ManagementReply< 14, 2 > maxConnsReply
The maximum allowed file descriptors open at a time.
const int version
The version of the FastCGI protocol that this adheres to.
std::queue< Protocol::RequestId > m_tasks
Queue for pending tasks.
Data structure to hold a block of raw data.
int type
Type of message. A 0 means FastCGI record. Anything else is open.
#define WARNING_LOG(data)
Log any externally caused "errors".
char * begin()
Pointer to the first element.