event type
Generally speaking, the purpose of dividing events is to register various events in the script, so as to notify other modules and executable files of various abnormal and non-abnormal occurrence points. For example, a client link is a non-abnormal occurrence point. Timeout offline is an exception point.
The clear division of events in the structure makes it easier to organize the process clearly. Events can be divided into
1 service event
2 session event
3 service status event, such as recording start
switch(_type)
{
// StreamEventType
case EventType::ServerStarted:
case EventType::HostCreated:
case EventType::HostDeleted:
case EventType::AppCreated:
case EventType::AppDeleted:
case EventType::StreamCreated:
case EventType::StreamDeleted:
case EventType::StreamOriginLinkUpdated:
case EventType::StreamOutputsUpdated:
_category = EventCategory::StreamEventType;
break;
// SessionEventType
case EventType::SessionConnected:
case EventType::SessionDisconnected:
_category = EventCategory::SessionEventType;
break;
// ActoinEventType
case EventType::ApiCalled:
case EventType::RecordingStarted:
case EventType::RecordingStopped:
case EventType::PushStarted:
case EventType::PushStopped:
_category = EventCategory::ActoinEventType;
break;
// NotificationEventType
case EventType::Info:
case EventType::Error:
_category = EventCategory::NotificationEventType;
break;
// StatisticsEventType
case EventType::ServerStat:
_category = EventCategory::StatisticsEventType;
break;
}
event translation
Translate events into recognizable strings
String Event::GetTypeString() const
{
switch(_type)
{
// StreamEventType
case EventType::ServerStarted:
return "ServerStarted";
case EventType::HostCreated:
return "HostCreated";
case EventType::HostDeleted:
return "HostDeleted";
case EventType::AppCreated:
return "AppCreated";
case EventType::AppDeleted:
return "AppDeleted";
case EventType::StreamCreated:
return "StreamCreated";
case EventType::StreamDeleted:
return "StreamDeleted";
case EventType::StreamOriginLinkUpdated:
return "StreamOriginLinkUpdated";
case EventType::StreamOutputsUpdated:
return "StreamOutputsUpdated";
// SessionEventType
case EventType::SessionConnected:
return "SessionConnected";
case EventType::SessionDisconnected:
return "SessionDisconnected";
// ActoinEventType
case EventType::ApiCalled:
return "ApiCalled";
case EventType::RecordingStarted:
return "RecordingStarted";
case EventType::RecordingStopped:
return "RecordingStopped";
case EventType::PushStarted:
return "PushStarted";
case EventType::PushStopped:
return "PushStopped";
// NotificationEventType
case EventType::Info:
return "Info";
case EventType::Error:
return "Error";
// StatisticsEventType
case EventType::ServerStat:
return "ServerStat";
}
return "";
}
Events are translated into json
For communication interpretation, events can be translated into json, as shown in the following code
String Event::SerializeToJson() const
{
Json::Value json_root;
// Fill common values
json_root["eventVersion"] = EVENT_VERSION;
json_root["timestampMillis"] = _creation_time_msec;
json_root["userKey"] = _server_metric->GetConfig()->GetAnalytics().GetUserKey().CStr();
json_root["serverID"] = _server_metric->GetConfig()->GetID().CStr();
// Fill root["event"]
Json::Value &json_event = json_root["event"];
json_event["type"] = GetTypeString().CStr();
if(_message.IsEmpty() == false)
{
json_event["message"] = _message.CStr();
}
Json::Value &json_producer = json_event["producer"];
FillProducer(json_producer);
// Fill root["data"]
Json::Value &json_data = json_root["data"];
if(_category == EventCategory::StreamEventType)
{
//TODO(Getroot): Implement this
json_data["dataType"] = "Not Implemented";
Json::Value &json_server_info = json_data["serverInfo"];
FillServerInfo(json_server_info);
}
else if(_category == EventCategory::StatisticsEventType)
{
Json::Value &json_server_stat = json_data["serverStat"];
FillServerStatistics(json_server_stat);
}
Json::StreamWriterBuilder builder;
/*
Default StreamWriterBuilder settings
(*settings)["commentStyle"] = "All";
(*settings)["indentation"] = "\t";
(*settings)["enableYAMLCompatibility"] = false;
(*settings)["dropNullPlaceholders"] = false;
(*settings)["useSpecialFloats"] = false;
(*settings)["emitUTF8"] = false;
(*settings)["precision"] = 17;
(*settings)["precisionType"] = "significant";
*/
logtd("%s", json_root.toStyledString().c_str());
builder["indentation"] = "";
return Json::writeString(builder, json_root).c_str();
}
signal processing
A signal is a software interrupt that provides a processing mechanism for asynchronous events, such as SIGCHLD, which represents a sub-process termination signal. After the sub-process terminates, the signal is captured and the sub-process exception information is processed.
SIGUSR1 SIGUSR2 Both are process-defined signals. These signals are for user-defined purposes. The kernel never sends them. The process can use these two signals for any purpose.
Next is more signal processing, as shown below, there are many signals
bool InitializeSignals()
{
// 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
// 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
// 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
// 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
// 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
// 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
// 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
// 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
// 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
// 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
// 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
// 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
// 63) SIGRTMAX-1 64) SIGRTMAX
return InitializeAbortSignal() &&
InitializeUser1Signal() &&
InitializeReloadSignal() &&
InitializeTerminateSignal();
}
Example of a signal handler
#include <stdio.h>
static void sigint_handle(int signo)
{
printf("............................");
exit(EXIT_SUCCESS);
}
int main(void)
{
if(signal(SIGINT, sigint_handle) == SIG_ERR){
fprintf(stderr,"can not handle\n";
exit(EXIT_FAILURE);
}
for(;;)
{
pause();
}
return 0;
}
Among them, SIGINT is to handle user input interrupt symbol events, such as debugging using ctrl+c, and pause is a system call function, which will suspend the program and know that there is a signal, and the signal is sent to the process by the kernel to wake up the system process. This requires readers to master more principles of the operating system.
Combining events and signals
In addition to writing scripts for processing, such as lua, or javascript, etc., you can also associate events with signals, process system-level calls, such as encountering SIGSEGV memory processing exceptions, SIGXCPU process resource limit and other signals, we receive these signals Then you can restart or close the program.