jmisc.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef __JMISC__
  14. #define __JMISC__
  15. #include "platform.h"
  16. #include <stdio.h>
  17. #include "jiface.hpp"
  18. #include "jcrc.hpp"
  19. #include "jlog.hpp"
  20. #ifdef _WIN32
  21. #include <windows.h>
  22. #endif
  23. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) defines 0x00--0x7F and 0xA0--0xFF
  24. // ISO-8859-1 (aka ISO-Latin-1 and IBM-810) is identical to US-ASCII (aka ANSI_X3.4 and ISO-646) in the range 0x00--0x7F
  25. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) is identical to ISO-8859-15 (aka ISO-Latin-9 and IBM-923) except 0xA4 is Currency rather than Euro
  26. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) is identical to Windows-1252 (aka IBM-5348) and to IBM-1252 except the latter define 0x80--0x9F
  27. #define ASCII_LIKE_CODEPAGE "iso-8859-1"
  28. #define ASCII_LIKE_SUBS_CHAR 0x1a
  29. inline bool isValidAsciiLikeCharacter(unsigned char c) { return ((c < 0x80) || (c >= 0xA0)); }
  30. #define _LOG_TIME MSGFIELD_timeDate
  31. #define _LOG_TID MSGFIELD_thread
  32. #define _LOG_PID MSGFIELD_process //gcc 3.0.4 on Linux defines LOG_PID as 0x1 already in sys/syslog.h
  33. #define _LOG_CLOCK MSGFIELD_milliTime
  34. #define _LOG_HIRESCLOCK MSGFIELD_nanoTime
  35. class StringBuffer;
  36. class ILogIntercept
  37. {
  38. public:
  39. virtual void print(const char *fmt)=0;
  40. virtual void close()=0;
  41. virtual unsigned setLogDetail(unsigned)=0;
  42. };
  43. jlib_decl ILogIntercept* interceptLog(ILogIntercept *intercept); // for custom tracing
  44. //Use openLogFile() to create/append a simple, local component logfile, providing a filename(or filespec).
  45. //Typically used to create a non rolling, local logfile in cwd, using default logfile contents
  46. jlib_decl void openLogFile(StringBuffer & resolvedFS, const char *filename, unsigned detail = 0, bool enterQueueMode = true, bool append = false);
  47. #ifndef DISABLE_PRINTLOG
  48. #define PrintExceptionLog(_e,_txt) EXCLOG(_e, _txt)
  49. #endif
  50. jlib_decl void PrintMemoryStatusLog();
  51. extern jlib_decl StringBuffer & hexdump2string(byte const * in, size32_t inSize, StringBuffer & out);
  52. jlib_decl StringBuffer &addFileTimestamp(StringBuffer &fname, bool daily=false);
  53. jlib_decl FILE *xfopen(const char *path, const char *mode);
  54. jlib_decl const char * queryCcLogName();
  55. jlib_decl StringBuffer& queryCcLogName(const char* wuid, StringBuffer& logname);
  56. jlib_decl char* readarg(char*& curptr);
  57. jlib_decl bool invoke_program(const char *command_line, DWORD &runcode, bool wait=true, const char *outfile=NULL, HANDLE *rethandle=NULL, bool throwException = false, bool newProcessGroup = false);
  58. jlib_decl bool wait_program(HANDLE handle,DWORD &runcode,bool block=true);
  59. jlib_decl bool interrupt_program(HANDLE handle, bool killChildren, int signum=0); // no signum means use default
  60. jlib_decl bool getHomeDir(StringBuffer & homepath);
  61. #ifndef _WIN32
  62. jlib_decl bool CopyFile(const char *file, const char *newfile, bool fail);
  63. #endif
  64. //Endian support
  65. inline void _rev2(char *b) { char t=b[0]; b[0]=b[1]; b[1]=t; }
  66. inline void _rev4(char *b) { char t=b[0]; b[0]=b[3]; b[3]=t; t=b[1]; b[1]=b[2]; b[2]=t; }
  67. inline void _rev8(char *b) { char t=b[0]; b[0]=b[7]; b[7]=t; t=b[1]; b[1]=b[6]; b[6]=t; t=b[2]; b[2]=b[5]; b[5]=t; t=b[3]; b[3]=b[4]; b[4]=t; }
  68. inline void _rev(short &v) { _rev2((char *)&v); }
  69. inline void _rev(unsigned short &v) { _rev2((char *)&v); }
  70. inline void _rev(int &v) { _rev4((char *)&v); }
  71. #if defined (_MSC_VER) && _MSC_VER < 1300
  72. inline void _rev(__int32 &v) { _rev4((char *)&v); }
  73. #endif
  74. inline void _rev(unsigned int &v) { _rev4((char *)&v); }
  75. inline void _rev(long &v) { _rev4((char *)&v); }
  76. inline void _rev(unsigned long &v) { _rev4((char *)&v); }
  77. inline void _rev(__int64 &v) { _rev8((char *)&v); }
  78. inline void _rev(unsigned __int64 &v) { _rev8((char *)&v); }
  79. extern jlib_decl void _rev(size32_t len, void * ptr);
  80. #define _REV2(p) _rev2((char *)&p);
  81. #define _REV4(p) _rev4((char *)&p);
  82. #define _REV8(p) _rev8((char *)&p);
  83. #if __BYTE_ORDER == __LITTLE_ENDIAN
  84. #define _WINREV(x) _rev(x)
  85. #define _WINREV2(p) _REV2(p)
  86. #define _WINREV4(p) _REV4(p)
  87. #define _WINREV8(p) _REV8(p)
  88. #define _WINREVN(l,p) _rev(l, p)
  89. #else
  90. #define _WINREV(x)
  91. #define _WINREV2(p)
  92. #define _WINREV4(p)
  93. #define _WINREV8(p)
  94. #define _WINREVN(l,p)
  95. #endif
  96. inline void _cpyrev2(void * _tgt, const void * _src) {
  97. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  98. tgt[1]=src[0]; tgt[0] = src[1];
  99. }
  100. inline void _cpyrev3(void * _tgt, const void * _src) {
  101. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  102. tgt[2] = src[0]; tgt[1]=src[1]; tgt[0] = src[2];
  103. }
  104. inline void _cpyrev4(void * _tgt, const void * _src) {
  105. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  106. tgt[3]=src[0]; tgt[2] = src[1]; tgt[1]=src[2]; tgt[0] = src[3];
  107. }
  108. inline void _cpyrev5(void * _tgt, const void * _src) {
  109. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  110. tgt[4]=src[0];
  111. tgt[3]=src[1]; tgt[2] = src[2]; tgt[1]=src[3]; tgt[0] = src[4];
  112. }
  113. inline void _cpyrev6(void * _tgt, const void * _src) {
  114. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  115. tgt[5]=src[0]; tgt[4] = src[1];
  116. tgt[3]=src[2]; tgt[2] = src[3]; tgt[1]=src[4]; tgt[0] = src[5];
  117. }
  118. inline void _cpyrev7(void * _tgt, const void * _src) {
  119. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  120. tgt[6] = src[0]; tgt[5]=src[1]; tgt[4]=src[2];
  121. tgt[3] = src[3]; tgt[2]=src[4]; tgt[1]=src[5]; tgt[0]=src[6];
  122. }
  123. inline void _cpyrev8(void * _tgt, const void * _src) {
  124. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  125. tgt[7]=src[0]; tgt[6] = src[1]; tgt[5]=src[2]; tgt[4] = src[3];
  126. tgt[3]=src[4]; tgt[2] = src[5]; tgt[1]=src[6]; tgt[0] = src[7];
  127. }
  128. inline void _cpyrevn(void * _tgt, const void * _src, unsigned len) {
  129. char * tgt = (char *)_tgt; const char * src = (const char *)_src+len;
  130. for (;len;len--) {
  131. *tgt++ = *--src;
  132. }
  133. }
  134. #if __BYTE_ORDER == __LITTLE_ENDIAN
  135. #define _WINCPYREV(x, y, len) _cpyrevn(x, y, len)
  136. #define _WINCPYREV2(x, y) _cpyrev2(x, y)
  137. #define _WINCPYREV4(x, y) _cpyrev4(x, y)
  138. #define _WINCPYREV8(x, y) _cpyrev8(x, y)
  139. #else
  140. #define _WINCPYREV(x, y, len) memcpy(x, y, len)
  141. #define _WINCPYREV2(x, y) memcpy(x, y, 2)
  142. #define _WINCPYREV4(x, y) memcpy(x, y, 4)
  143. #define _WINCPYREV8(x, y) memcpy(x, y, 8)
  144. #endif
  145. #ifdef _WIN32
  146. class jlib_decl C64bitComposite // used to efficiently manage an int64 as two consecutive DWORDS and vice versa
  147. {
  148. private:
  149. LARGE_INTEGER value;
  150. public:
  151. C64bitComposite() {value.QuadPart = 0; }
  152. C64bitComposite(__int64 v) {value.QuadPart = v; }
  153. C64bitComposite(DWORD lo, DWORD hi) {value.LowPart = lo; value.HighPart = hi; }
  154. DWORD getLo() {return value.LowPart; }
  155. LONG getHi() {return value.HighPart; }
  156. __int64 get() {return value.QuadPart; }
  157. void get(DWORD &lo, DWORD &hi) {lo = value.LowPart, hi = value.HighPart; }
  158. C64bitComposite & set(__int64 v) {value.QuadPart = v; return *this; }
  159. C64bitComposite & set(DWORD lo, DWORD hi) {value.LowPart = lo; value.HighPart = hi; return *this; }
  160. C64bitComposite & operator = (__int64 v) {return set(v); }
  161. C64bitComposite & operator += (__int64 v) {value.QuadPart += v; return *this; }
  162. C64bitComposite & operator -= (__int64 v) {value.QuadPart -= v; return *this; }
  163. C64bitComposite & operator ++ () {++value.QuadPart; return * this; }
  164. C64bitComposite & operator -- () {--value.QuadPart; return * this; }
  165. int operator == (const C64bitComposite & s) {return value.QuadPart == s.value.QuadPart; }
  166. int operator != (const C64bitComposite & s) {return value.QuadPart != s.value.QuadPart; }
  167. int operator < (const C64bitComposite & s) {return value.QuadPart < s.value.QuadPart; }
  168. int operator > (const C64bitComposite & s) {return value.QuadPart > s.value.QuadPart; }
  169. int operator <= (const C64bitComposite & s) {return value.QuadPart <= s.value.QuadPart; }
  170. int operator >= (const C64bitComposite & s) {return value.QuadPart >= s.value.QuadPart; }
  171. int operator == (__int64 s) {return value.QuadPart == s; }
  172. int operator != (__int64 s) {return value.QuadPart != s; }
  173. int operator < (__int64 s) {return value.QuadPart < s; }
  174. int operator > (__int64 s) {return value.QuadPart > s; }
  175. int operator <= (__int64 s) {return value.QuadPart <= s; }
  176. int operator >= (__int64 s) {return value.QuadPart >= s; }
  177. };
  178. #endif
  179. // Functions to build and split 64bit integers. Do not depend on the byte order
  180. template<typename T1,typename T2> inline __int64 makeint64(T1 high, T2 low)
  181. {
  182. return (__int64)high<<32 | ((__int64)low & (__int64)0xffffffff);
  183. }
  184. inline __int32 high(__int64 n)
  185. {
  186. return (__int32)(n>>32);
  187. }
  188. inline unsigned __int32 low(__int64 n)
  189. {
  190. return (unsigned __int32)(n & (__int64)0xffffffff);
  191. }
  192. //MORE - We really should restructure this file. Also would this be better with a class interface?
  193. //Handle ^C/break from a console program.
  194. enum ahType { ahTerminate, ahInterrupt};
  195. typedef bool (*AbortHandler)(ahType); // return true to exit program
  196. typedef bool (*SimpleAbortHandler)();
  197. interface IAbortHandler : public IInterface
  198. {
  199. virtual bool onAbort() = 0;
  200. };
  201. #define JLIBERR_UserAbort 0xffffff00
  202. extern jlib_decl void addAbortHandler(AbortHandler handler=NULL); // no parameter means just set the flag for later testing.
  203. extern jlib_decl void addAbortHandler(SimpleAbortHandler handler=NULL);
  204. extern jlib_decl void addAbortHandler(IAbortHandler & handler);
  205. extern jlib_decl void removeAbortHandler(AbortHandler handler);
  206. extern jlib_decl void removeAbortHandler(SimpleAbortHandler handler);
  207. extern jlib_decl void removeAbortHandler(IAbortHandler & handler);
  208. extern jlib_decl bool isAborting();
  209. extern jlib_decl void throwAbortException();
  210. extern jlib_decl void throwExceptionIfAborting();
  211. interface IAbortRequestCallback
  212. {
  213. virtual bool abortRequested() = 0;
  214. };
  215. class LocalAbortHandler
  216. {
  217. public:
  218. LocalAbortHandler(AbortHandler _handler) { handler = _handler; shandler = NULL; addAbortHandler(handler); }
  219. LocalAbortHandler(SimpleAbortHandler _handler) { shandler = _handler; handler = NULL; addAbortHandler(shandler); }
  220. ~LocalAbortHandler() { if (handler) { removeAbortHandler(handler); } else removeAbortHandler(shandler); }
  221. private:
  222. AbortHandler handler;
  223. SimpleAbortHandler shandler;
  224. };
  225. class LocalIAbortHandler
  226. {
  227. public:
  228. LocalIAbortHandler(IAbortHandler & _handler) : handler(_handler) { addAbortHandler(handler); }
  229. ~LocalIAbortHandler() { removeAbortHandler(handler); }
  230. private:
  231. IAbortHandler & handler;
  232. };
  233. // These are undocumented by Microsoft
  234. #define ENABLE_QUICK_EDIT 0x0040
  235. #define ENABLE_INSERT_MODE 0x0020
  236. class NoQuickEditSection
  237. {
  238. #ifdef _WIN32
  239. DWORD savedmode = 0;
  240. bool saved = false;
  241. #endif
  242. public:
  243. NoQuickEditSection()
  244. {
  245. #ifdef _WIN32
  246. saved = false;
  247. HANDLE hStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
  248. if (hStdIn)
  249. {
  250. if (::GetConsoleMode(hStdIn, &savedmode))
  251. saved = true;
  252. // Set new console mode w/ QuickEdit disabled
  253. DWORD mode = savedmode & ~(ENABLE_QUICK_EDIT);
  254. if (!::SetConsoleMode(hStdIn, mode))
  255. DBGLOG("SetConsoleMode failed code %d", GetLastError());
  256. ::CloseHandle(hStdIn);
  257. }
  258. #endif
  259. }
  260. ~NoQuickEditSection()
  261. {
  262. #ifdef _WIN32
  263. if (saved)
  264. {
  265. HANDLE hStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
  266. if (hStdIn)
  267. {
  268. ::SetConsoleMode(hStdIn, savedmode);;
  269. ::CloseHandle(hStdIn);
  270. }
  271. }
  272. #endif
  273. }
  274. };
  275. #ifdef _WIN32
  276. extern jlib_decl char *mkdtemp(char *_template);
  277. #endif
  278. extern jlib_decl char **getSystemEnv();
  279. extern jlib_decl void runKubectlCommand(const char *title, const char *cmd, const char *input, StringBuffer *output);
  280. // return the k8s external host and port for serviceName
  281. extern jlib_decl std::pair<std::string, unsigned> getExternalService(const char *serviceName);
  282. extern jlib_decl std::pair<std::string, unsigned> getDafileServiceFromConfig(const char *application);
  283. #endif