1 /**
2 * @file src/megacmdlogger.cpp
3 * @brief MEGAcmd: Controls message logging
4 *
5 * (c) 2013 by Mega Limited, Auckland, New Zealand
6 *
7 * This file is part of the MEGAcmd.
8 *
9 * MEGAcmd is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * @copyright Simplified (2-clause) BSD License.
14 *
15 * You should have received a copy of the license along with this
16 * program.
17 */
18
19 #include "megacmdlogger.h"
20
21 #include <map>
22
23 #include <sys/types.h>
24
25 #ifdef _WIN32
26 #include <fcntl.h>
27 #include <io.h>
28 #include <stdio.h>
29 #ifndef _O_U16TEXT
30 #define _O_U16TEXT 0x00020000
31 #endif
32 #ifndef _O_U8TEXT
33 #define _O_U8TEXT 0x00040000
34 #endif
35 #endif
36
37 using namespace mega;
38
39 namespace megacmd {
40 // different outstreams for every thread. to gather all the output data
41 std::mutex threadLookups;
42 map<uint64_t, LoggedStream *> outstreams;
43 map<uint64_t, int> threadLogLevel;
44 map<uint64_t, int> threadoutCode;
45 map<uint64_t, CmdPetition *> threadpetition;
46 map<uint64_t, bool> threadIsCmdShell;
47
48 LoggedStream LCOUT(&COUT);
49
50
getCurrentOut()51 LoggedStream &getCurrentOut()
52 {
53 std::lock_guard<std::mutex> g(threadLookups);
54 uint64_t currentThread = MegaThread::currentThreadId();
55 if (outstreams.find(currentThread) == outstreams.end())
56 {
57 return LCOUT;
58 }
59 else
60 {
61 return *outstreams[currentThread];
62 }
63 }
64
interactiveThread()65 bool interactiveThread()
66 {
67 if (getCurrentThreadIsCmdShell())
68 {
69 return true;
70 }
71
72 unsigned long long currentThread = MegaThread::currentThreadId();
73
74 std::lock_guard<std::mutex> g(threadLookups);
75 if (outstreams.find(currentThread) == outstreams.end())
76 {
77 return true;
78 }
79 else
80 {
81 return false;
82 }
83 }
84
getCurrentOutCode()85 int getCurrentOutCode()
86 {
87 unsigned long long currentThread = MegaThread::currentThreadId();
88
89 std::lock_guard<std::mutex> g(threadLookups);
90 if (threadoutCode.find(currentThread) == threadoutCode.end())
91 {
92 return 0; //default OK
93 }
94 else
95 {
96 return threadoutCode[currentThread];
97 }
98 }
99
100
getCurrentPetition()101 CmdPetition * getCurrentPetition()
102 {
103 unsigned long long currentThread = MegaThread::currentThreadId();
104
105 std::lock_guard<std::mutex> g(threadLookups);
106 if (threadpetition.find(currentThread) == threadpetition.end())
107 {
108 return NULL;
109 }
110 else
111 {
112 return threadpetition[currentThread];
113 }
114 }
115
getCurrentThreadLogLevel()116 int getCurrentThreadLogLevel()
117 {
118 unsigned long long currentThread = MegaThread::currentThreadId();
119
120 std::lock_guard<std::mutex> g(threadLookups);
121 if (threadLogLevel.find(currentThread) == threadLogLevel.end())
122 {
123 return -1;
124 }
125 else
126 {
127 return threadLogLevel[currentThread];
128 }
129 }
130
getCurrentThreadIsCmdShell()131 bool getCurrentThreadIsCmdShell()
132 {
133 unsigned long long currentThread = MegaThread::currentThreadId();
134
135 std::lock_guard<std::mutex> g(threadLookups);
136 if (threadIsCmdShell.find(currentThread) == threadIsCmdShell.end())
137 {
138 return false; //default not
139 }
140 else
141 {
142 return threadIsCmdShell[currentThread];
143 }
144 }
145
146
setCurrentThreadLogLevel(int level)147 void setCurrentThreadLogLevel(int level)
148 {
149 std::lock_guard<std::mutex> g(threadLookups);
150 threadLogLevel[MegaThread::currentThreadId()] = level;
151 }
152
setCurrentThreadOutStream(LoggedStream * s)153 void setCurrentThreadOutStream(LoggedStream *s)
154 {
155 std::lock_guard<std::mutex> g(threadLookups);
156 outstreams[MegaThread::currentThreadId()] = s;
157 }
158
setCurrentThreadIsCmdShell(bool isit)159 void setCurrentThreadIsCmdShell(bool isit)
160 {
161 std::lock_guard<std::mutex> g(threadLookups);
162 threadIsCmdShell[MegaThread::currentThreadId()] = isit;
163 }
164
setCurrentOutCode(int outCode)165 void setCurrentOutCode(int outCode)
166 {
167 std::lock_guard<std::mutex> g(threadLookups);
168 threadoutCode[MegaThread::currentThreadId()] = outCode;
169 }
170
setCurrentPetition(CmdPetition * petition)171 void setCurrentPetition(CmdPetition *petition)
172 {
173 std::lock_guard<std::mutex> g(threadLookups);
174 threadpetition[MegaThread::currentThreadId()] = petition;
175 }
176
177
MegaCMDLogger()178 MegaCMDLogger::MegaCMDLogger()
179 {
180 this->output = &LCOUT;
181 this->apiLoggerLevel = MegaApi::LOG_LEVEL_ERROR;
182 this->outputmutex = new std::mutex();
183 }
184
~MegaCMDLogger()185 MegaCMDLogger::~MegaCMDLogger()
186 {
187 delete this->outputmutex;
188 }
189
log(const char * time,int loglevel,const char * source,const char * message)190 void MegaCMDLogger::log(const char *time, int loglevel, const char *source, const char *message)
191 {
192 if ( (string(source).find("src/megacmd") != string::npos)
193 || (string(source).find("src\\megacmd") != string::npos)
194 || (string(source).find("listeners.cpp") != string::npos)
195 || (string(source).find("configurationmanager.cpp") != string::npos)
196 || (string(source).find("comunicationsmanager") != string::npos)
197 )
198 {
199 if (loglevel <= cmdLoggerLevel)
200 {
201 #ifdef _WIN32
202 std::lock_guard<std::mutex> g(*outputmutex);
203 int oldmode;
204 oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
205 *output << "[" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
206 _setmode(_fileno(stdout), oldmode);
207 #else
208 *output << "[" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
209 #endif
210
211 }
212
213 int currentThreadLogLevel = getCurrentThreadLogLevel();
214 if (currentThreadLogLevel < 0)
215 {
216 currentThreadLogLevel = cmdLoggerLevel;
217 }
218 if (( loglevel <= currentThreadLogLevel ) && ( &OUTSTREAM != output ))
219 {
220 OUTSTREAM << "[" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
221 }
222 }
223 else
224 {
225 if (loglevel <= apiLoggerLevel)
226 {
227 if (( apiLoggerLevel <= MegaApi::LOG_LEVEL_DEBUG ) && !strcmp(message, "Request (RETRY_PENDING_CONNECTIONS) starting"))
228 {
229 return;
230 }
231 if (( apiLoggerLevel <= MegaApi::LOG_LEVEL_DEBUG ) && !strcmp(message, "Request (RETRY_PENDING_CONNECTIONS) finished"))
232 {
233 return;
234 }
235 #ifdef _WIN32
236 std::lock_guard<std::mutex> g(*outputmutex);
237 int oldmode;
238 oldmode = _setmode(_fileno(stdout), _O_U8TEXT);
239 *output << "[API:" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
240 _setmode(_fileno(stdout), oldmode);
241 #else
242 *output << "[API:" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
243 #endif
244 }
245
246 int currentThreadLogLevel = getCurrentThreadLogLevel();
247
248 if (currentThreadLogLevel < 0)
249 {
250 currentThreadLogLevel = apiLoggerLevel;
251 }
252 if (( loglevel <= currentThreadLogLevel ) && ( &OUTSTREAM != output )) //since it happens in the sdk thread, this shall be false
253 {
254 OUTSTREAM << "[API:" << SimpleLogger::toStr(LogLevel(loglevel)) << ": " << time << "] " << message << endl;
255 }
256 }
257 }
258
getMaxLogLevel()259 int MegaCMDLogger::getMaxLogLevel()
260 {
261 return max(max(getCurrentThreadLogLevel(), cmdLoggerLevel), apiLoggerLevel);
262 }
263
264 }//end namespace
265