1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3
4#include <base/logger.h>
5#include <base/system.h>
6
7#include <engine/console.h>
8#include <engine/engine.h>
9#include <engine/shared/config.h>
10#include <engine/shared/jobs.h>
11#include <engine/shared/network.h>
12#include <engine/storage.h>
13
14#include <thread>
15
16class CEngine : public IEngine
17{
18 IConsole *m_pConsole;
19 IStorage *m_pStorage;
20
21 bool m_Logging;
22 std::shared_ptr<CFutureLogger> m_pFutureLogger;
23
24 char m_aAppName[256];
25
26 CJobPool m_JobPool;
27
28 static void Con_DbgLognetwork(IConsole::IResult *pResult, void *pUserData)
29 {
30 CEngine *pEngine = static_cast<CEngine *>(pUserData);
31
32 if(pEngine->m_Logging)
33 {
34 CNetBase::CloseLog();
35 pEngine->m_Logging = false;
36 }
37 else
38 {
39 char aBuf[32];
40 str_timestamp(buffer: aBuf, buffer_size: sizeof(aBuf));
41 char aFilenameSent[IO_MAX_PATH_LENGTH], aFilenameRecv[IO_MAX_PATH_LENGTH];
42 str_format(buffer: aFilenameSent, buffer_size: sizeof(aFilenameSent), format: "dumps/network_sent_%s.txt", aBuf);
43 str_format(buffer: aFilenameRecv, buffer_size: sizeof(aFilenameRecv), format: "dumps/network_recv_%s.txt", aBuf);
44 CNetBase::OpenLog(DataLogSent: pEngine->m_pStorage->OpenFile(pFilename: aFilenameSent, Flags: IOFLAG_WRITE, Type: IStorage::TYPE_SAVE),
45 DataLogRecv: pEngine->m_pStorage->OpenFile(pFilename: aFilenameRecv, Flags: IOFLAG_WRITE, Type: IStorage::TYPE_SAVE));
46 pEngine->m_Logging = true;
47 }
48 }
49
50public:
51 CEngine(bool Test, const char *pAppname, std::shared_ptr<CFutureLogger> pFutureLogger) :
52 m_pFutureLogger(std::move(pFutureLogger))
53 {
54 str_copy(dst&: m_aAppName, src: pAppname);
55 if(!Test)
56 {
57 log_info("engine", "running on %s-%s-%s", CONF_FAMILY_STRING, CONF_PLATFORM_STRING, CONF_ARCH_STRING);
58 log_info("engine", "arch is %s", CONF_ARCH_ENDIAN_STRING);
59
60 char aVersionStr[128];
61 if(os_version_str(version: aVersionStr, length: sizeof(aVersionStr)))
62 {
63 log_info("engine", "operating system version: %s", aVersionStr);
64 }
65
66 // init the network
67 net_init();
68 CNetBase::Init();
69 }
70
71#if defined(CONF_PLATFORM_EMSCRIPTEN)
72 // Make sure we don't use more threads than allowed in total (see PTHREAD_POOL_SIZE in Emscripten.toolchain)
73 // otherwise starting more threads may lead to deadlocks as the threads will simply not start.
74 const size_t ThreadCount = 4;
75#else
76 const size_t ThreadCount = std::max(a: 4, b: (int)std::thread::hardware_concurrency()) - 2;
77#endif
78 m_JobPool.Init(NumThreads: ThreadCount);
79
80 m_Logging = false;
81 }
82
83 ~CEngine() override
84 {
85 CNetBase::CloseLog();
86 }
87
88 void Init() override
89 {
90 m_pConsole = Kernel()->RequestInterface<IConsole>();
91 m_pStorage = Kernel()->RequestInterface<IStorage>();
92
93 if(!m_pConsole || !m_pStorage)
94 return;
95
96 m_pConsole->Register(pName: "dbg_lognetwork", pParams: "", Flags: CFGFLAG_SERVER | CFGFLAG_CLIENT, pfnFunc: Con_DbgLognetwork, pUser: this, pHelp: "Log the network");
97 }
98
99 void AddJob(std::shared_ptr<IJob> pJob) override
100 {
101 m_JobPool.Add(pJob: std::move(pJob));
102 }
103
104 void ShutdownJobs() override
105 {
106 m_JobPool.Shutdown();
107 }
108
109 void SetAdditionalLogger(std::shared_ptr<ILogger> &&pLogger) override
110 {
111 m_pFutureLogger->Set(pLogger);
112 }
113};
114
115IEngine *CreateEngine(const char *pAppname, std::shared_ptr<CFutureLogger> pFutureLogger) { return new CEngine(false, pAppname, std::move(pFutureLogger)); }
116IEngine *CreateTestEngine(const char *pAppname) { return new CEngine(true, pAppname, nullptr); }
117