LogThread.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. // LogThread.cpp: implementation of the CLogThread class.
  15. //
  16. //////////////////////////////////////////////////////////////////////
  17. #include "LogThread.h"
  18. #include "jmisc.hpp"
  19. #include "soapbind.hpp"
  20. #include "esploggingservice_esp.ipp"
  21. #include "espcontext.hpp"
  22. #define MaxLogQueueLength 500000
  23. #define QueueSizeSignal 10000
  24. static int DefaultThreadPoolSize = 50;
  25. static int LogThreadWaitTime = 90;
  26. #ifndef _WIN32
  27. #include <sys/time.h>
  28. #include <sys/resource.h>
  29. #endif
  30. IClientLogThread * createLogClient(IPropertyTree *cfg, const char *process, const char *service,bool bFlatten)
  31. {
  32. return createLogClient2(cfg, process, service, "loggingserver", bFlatten);
  33. }
  34. IClientLogThread * createLogClient3(IPropertyTree *logcfg, const char *service, bool bFlatten)
  35. {
  36. if(!logcfg)
  37. return NULL;
  38. DBGLOG("Creating recovery logging client");
  39. IClientLogThread* pLoggingThread = 0;
  40. pLoggingThread = new CLogThread(logcfg,service, bFlatten, false);
  41. pLoggingThread->start();
  42. return pLoggingThread;
  43. }
  44. IClientLogThread * createLogClient2(IPropertyTree *cfg, const char *process, const char *service, const char* name, bool bFlatten, bool bModelRequest)
  45. {
  46. DBGLOG("Creating recovery logging client %s", name);
  47. IClientLogThread* pLoggingThread = 0;
  48. StringBuffer xpath,loggingServer;
  49. xpath.appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/%s", process, service, name);
  50. IPropertyTree* pServerInfo = cfg->queryPropTree(xpath.str());
  51. if (pServerInfo == 0)
  52. return 0;
  53. pLoggingThread = new CLogThread(pServerInfo,service, bFlatten, bModelRequest);
  54. pLoggingThread->start();
  55. return pLoggingThread;
  56. }
  57. IClientLogThread * createModelLogClient(IPropertyTree *cfg, const char *process, const char *service, bool bFlatten )
  58. {
  59. return createLogClient2( cfg, process, service, "loggingserver", bFlatten, true );
  60. }
  61. //////////////////////////////////////////////////////////////////////
  62. // Construction/Destruction
  63. //////////////////////////////////////////////////////////////////////
  64. CLogThread::CLogThread(IPropertyTree* pServerConfig , const char* Service, bool bFlatten, bool bModelRequest) : m_bRun(true),m_Logcount(0) ,
  65. m_LogTreshhold(0), m_bModelRequest(bModelRequest), m_logResponse(false)
  66. {
  67. if(pServerConfig==NULL)
  68. throw MakeStringException(500,"No Logging Configuration");
  69. if(pServerConfig->hasProp("url")==false)
  70. throw MakeStringException(500,"No Logging Server URL");
  71. m_ServiceURL.appendf("%s",pServerConfig->queryProp("url"));
  72. m_bFailSafeLogging = false;
  73. if(pServerConfig->hasProp("failsafe")==true)
  74. {
  75. const char* failsafe = pServerConfig->queryProp("failsafe");
  76. if(failsafe != 0 && strcmp(failsafe,"true") == 0)
  77. m_bFailSafeLogging = true;
  78. }
  79. StringBuffer poolsizebuf;
  80. if(pServerConfig->hasProp("MaxLoggingThreads"))
  81. pServerConfig->getProp("MaxLoggingThreads", poolsizebuf);
  82. if(poolsizebuf.length() > 0)
  83. {
  84. m_ThreadPoolSize = atoi(poolsizebuf.str());
  85. }
  86. else
  87. {
  88. // If thread pool size not even specified, use default size
  89. m_ThreadPoolSize = DefaultThreadPoolSize;
  90. }
  91. pServerConfig->hasProp("MaxLogQueueLength")==true ? m_MaxLogQueueLength = pServerConfig->getPropInt("MaxLogQueueLength") : m_MaxLogQueueLength = MaxLogQueueLength;
  92. pServerConfig->hasProp("QueueSizeSignal")==true ? m_SignalGrowingQueueAt = pServerConfig->getPropInt("QueueSizeSignal") : m_SignalGrowingQueueAt = QueueSizeSignal;
  93. pServerConfig->hasProp("Throttle")==true ? m_bThrottle = pServerConfig->getPropBool("Throttle") : m_bThrottle = true;
  94. m_logResponse = pServerConfig->getPropBool("LogResponseXml",false);
  95. if(pServerConfig->hasProp("BurstWaitInterval"))
  96. m_BurstWaitInterval = pServerConfig->getPropInt("BurstWaitInterval");
  97. else
  98. m_BurstWaitInterval = 0;
  99. if(pServerConfig->hasProp("LinearWaitInterval"))
  100. m_LinearWaitInterval = pServerConfig->getPropInt("LinearWaitInterval");
  101. else
  102. m_LinearWaitInterval = 0;
  103. if(pServerConfig->hasProp("NiceLevel"))
  104. m_NiceLevel = pServerConfig->getPropInt("NiceLevel");
  105. else
  106. m_NiceLevel = 0;
  107. //by default flatten any trees passes into the service
  108. m_bFlattenTree = bFlatten;
  109. m_LogSendDelta = 0;
  110. m_LogSend = 0;
  111. if(m_ThreadPoolSize > 0)
  112. m_pLoggingService.setown(new CPooledClientWsLogService(m_ThreadPoolSize));
  113. else
  114. m_pLoggingService.setown(createWsLogServiceClient());
  115. m_pLoggingService->addServiceUrl(m_ServiceURL.str());
  116. //temporary fix for authentication on logging service....
  117. const char* loguser = pServerConfig->queryProp("LoggingUser");
  118. const char* logpasswd = pServerConfig->queryProp("LoggingPassword");
  119. m_pLoggingService->setUsernameToken((loguser && *loguser)?loguser:"loggingclient", (logpasswd&&*logpasswd)?logpasswd:"loggingpassword","");
  120. if(m_bFailSafeLogging == true)
  121. {
  122. if(pServerConfig->hasProp("LogsDir"))
  123. m_LogFailSafe.setown(createFailsafelogger(Service, pServerConfig->queryProp("LogsDir")));
  124. else
  125. m_LogFailSafe.setown(createFailsafelogger(Service));
  126. }
  127. bSeedAvailable = false;
  128. bMadeSeedRequest = false;
  129. id_counter=0;
  130. time_t tNow;
  131. time(&tNow);
  132. localtime_r(&tNow, &m_startTime);
  133. }
  134. CLogThread::~CLogThread()
  135. {
  136. DBGLOG("CLogThread::~CLogThread()");
  137. }
  138. bool CLogThread::FetchTransactionSeed(StringBuffer& TransactionSeedID)
  139. {
  140. try{
  141. Owned<IClientTransactionSeedRequest> pSeedReq = m_pLoggingService->createTransactionSeedRequest();
  142. Owned<IClientTransactionSeedResponse> pSeedResp = m_pLoggingService->TransactionSeed(pSeedReq.get());
  143. //if we get to here then we have made the request but no seeds are available
  144. bMadeSeedRequest = true;
  145. if(pSeedResp->getSeedAvailable()==true)
  146. {
  147. TransactionSeedID.appendf("%s",pSeedResp->getSeedId());
  148. return true;
  149. }
  150. else
  151. return false;
  152. }
  153. catch(IException* ex)
  154. {
  155. StringBuffer errorStr;
  156. ex->errorMessage(errorStr);
  157. ERRLOG("Exception caught generating transaction seed (%d) %s",ex->errorCode(),errorStr.str());
  158. ex->Release();
  159. }
  160. catch(...)
  161. {
  162. ERRLOG("Unknown exception caught generating transaction seed");
  163. }
  164. return false;
  165. }
  166. bool CLogThread::GenerateTransactionSeed(StringBuffer& UniqueID, char backendType)
  167. {
  168. CriticalBlock b(seed_gen_crit);
  169. if(bSeedAvailable == false && bMadeSeedRequest==true)
  170. {
  171. //we have checked for a seed but none are available
  172. return false;
  173. }
  174. else if (bSeedAvailable == false)
  175. {
  176. //we have not checked for a seed or we failed when making the request..
  177. bSeedAvailable = FetchTransactionSeed(m_InitialTransactionSeedID);
  178. if(bSeedAvailable==false)
  179. return false;
  180. DBGLOG("Fetched Transaction Seed %s\n", m_InitialTransactionSeedID.str());
  181. }
  182. UniqueID.appendf("%s%c%u",m_InitialTransactionSeedID.str(),backendType,++id_counter);
  183. if(UniqueID.length() > 16)
  184. {
  185. //Sybase limits transaction_id to 16 bytes. If longer, need to get another seed ID and reset id_counter.
  186. m_InitialTransactionSeedID.clear();
  187. bSeedAvailable = FetchTransactionSeed(m_InitialTransactionSeedID);
  188. if(bSeedAvailable==false)
  189. return false;
  190. DBGLOG("TransactionID length exceeded 16 bytes. So re-fetched a Transaction Seed %s.\n", m_InitialTransactionSeedID.str());
  191. id_counter = 0;
  192. UniqueID.clear().appendf("%s-%u",m_InitialTransactionSeedID.str(),++id_counter);
  193. }
  194. return true;
  195. }
  196. IClientLogInfo& CLogThread::addLogInfoElement(IArrayOf<IEspLogInfo>& LogArray)
  197. {
  198. IClientLogInfo* logInfo = new CLogInfo("");
  199. LogArray.append(*(dynamic_cast<IEspLogInfo*>(logInfo)));
  200. return *logInfo;
  201. }
  202. IClientModelLogInformation& CLogThread::getModelLogInformation()
  203. {
  204. return *(new CModelLogInformation(""));
  205. }
  206. IClientModelLogInfo& CLogThread::getModelLogInfo(IClientModelLogInformation* pModelLogInformation)
  207. {
  208. IClientModelLogInfo* pMLogInfo = new CModelLogInfo("");
  209. if(pModelLogInformation!=0)
  210. {
  211. pModelLogInformation->getModels().append(*(dynamic_cast<IEspModelLogInfo*>(pMLogInfo)));
  212. }
  213. return *pMLogInfo;
  214. }
  215. IClientAttributeGroupLogInfo& CLogThread::getAttributeGroupLogInfo(IClientModelLogInformation* pModelLogInformation)
  216. {
  217. IClientAttributeGroupLogInfo* pAttribGrpLogInfo = new CAttributeGroupLogInfo("");
  218. if(pModelLogInformation!=0)
  219. {
  220. pModelLogInformation->getAttributeGroups().append(*(dynamic_cast<IEspAttributeGroupLogInfo*>(pAttribGrpLogInfo)));
  221. }
  222. return *pAttribGrpLogInfo;
  223. }
  224. IClientAttributeLogInfo& CLogThread::getAttributeLogInfo(IClientAttributeGroupLogInfo* pAttributeGroupLogInfo)
  225. {
  226. IClientAttributeLogInfo* pAttribLogInfo = new CAttributeLogInfo("");
  227. if(pAttributeGroupLogInfo!=0)
  228. {
  229. pAttributeGroupLogInfo->getAttributes().append(*(dynamic_cast<IEspAttributeLogInfo*>(pAttribLogInfo)));
  230. }
  231. return *pAttribLogInfo;
  232. }
  233. IClientScoreLogInfo& CLogThread::getScoreLogInfo(IClientModelLogInfo* pModelLogInfo)
  234. {
  235. IClientScoreLogInfo* pScoreLogInfo = new CScoreLogInfo("");
  236. if(pModelLogInfo!=0)
  237. {
  238. pModelLogInfo->getScores().append(*(dynamic_cast<IEspScoreLogInfo*>(pScoreLogInfo)));
  239. }
  240. return *pScoreLogInfo;
  241. }
  242. IClientReasonCodeLogInfo& CLogThread::getReasonCodeLogInfo(IClientScoreLogInfo* pScoreLogInfo)
  243. {
  244. IClientReasonCodeLogInfo* pReasonCodeLogInfo = (IClientReasonCodeLogInfo*) new CReasonCodeLogInfo("");
  245. if(pScoreLogInfo!=0)
  246. {
  247. pScoreLogInfo->getReasonCodes().append(*(dynamic_cast<IEspReasonCodeLogInfo*>(pReasonCodeLogInfo)));
  248. }
  249. return *pReasonCodeLogInfo;
  250. }
  251. bool CLogThread::IsModelLogging()
  252. {
  253. return m_bModelRequest;
  254. }
  255. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, IArrayOf<IEspLogInfo>& LogArray, IInterface& logInfo)
  256. {
  257. StringBuffer dataStr;
  258. serializeRequest(context,logInfo,dataStr);
  259. Owned<IPropertyTree> pLogTreeInfo = createPTreeFromXMLString(dataStr.str(), ipt_none, xr_none);
  260. return queueLog(context,serviceName,RecordsReturned,LogArray, *pLogTreeInfo);
  261. }
  262. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned,bool bBlind,bool bEncrypt, IArrayOf<IEspLogInfo>& LogArray, IInterface& logInfo, IConstModelLogInformation* pModelLogInfo)
  263. {
  264. LOG_INFO _LogStruct(serviceName,RecordsReturned,bBlind);
  265. _LogStruct.Encrypt = bEncrypt;
  266. serializeRequest(context,logInfo,_LogStruct.RequestStr);
  267. Owned<IPropertyTree> pLogTreeInfo = createPTreeFromXMLString(_LogStruct.RequestStr.str(), ipt_none, xr_none);
  268. addLogInfo(LogArray,*pLogTreeInfo.get());
  269. return queueLog(context,_LogStruct, LogArray,pModelLogInfo);
  270. }
  271. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, IInterface& logInfo)
  272. {
  273. StringBuffer dataStr;
  274. serializeRequest(context,logInfo,dataStr);
  275. return queueLog(context,serviceName,RecordsReturned,dataStr);
  276. }
  277. StringBuffer& CLogThread::serializeRequest(IEspContext& context,IInterface& logInfo, StringBuffer& returnStr)
  278. {
  279. IRpcSerializable* rpcreq = dynamic_cast<IRpcSerializable*>(&logInfo);
  280. if(rpcreq==NULL)
  281. throw MakeStringException(500,"Issue serializing log information");
  282. // We want to serialize anything here for logging purpose: e.g., internal user fields: CompanyId
  283. // rpcreq->serialize(&context,returnStr, "LogData");
  284. // rpcreq->serialize(NULL,returnStr, "LogData");
  285. //BUG#26047
  286. //logInfo function parameter is instance of the incoming request object of the service.
  287. //instance objects of context and request are dependent upon the protocol binding.
  288. //Request parameters are relevent for HTTP protocol but are not relevent for protocolX.
  289. //Since request parameters pointer is not initilized in processing protocolX request it remains NULL
  290. //and causing this crash.
  291. IProperties* params = context.queryRequestParameters();
  292. if(params!=NULL)
  293. {
  294. bool notInternal = !params->hasProp("internal");
  295. if (notInternal)
  296. params->setProp("internal","1");
  297. rpcreq->serialize(&context,returnStr, "LogData");
  298. if (notInternal)
  299. params->removeProp("internal");
  300. }else{
  301. rpcreq->serialize(NULL,returnStr, "LogData");
  302. }
  303. return returnStr;
  304. }
  305. bool CLogThread::queueLog(const char *user, const char *realm, const char *peer, const char* serviceName,const char* GUID, int RecordsReturned, IPropertyTree& logInfo)
  306. {
  307. IArrayOf<IEspLogInfo> LogArray;
  308. addLogInfo(LogArray, logInfo);
  309. LOG_INFO _LogInfo(serviceName,GUID, RecordsReturned,false);
  310. return queueLog(user, realm, peer, _LogInfo, LogArray);
  311. }
  312. bool CLogThread::queueLog(const char *user, const char *realm, const char *peer, LOG_INFO& _LogStruct, IArrayOf<IEspLogInfo>& LogArray)
  313. {
  314. if(!m_pLoggingService.get())
  315. return false;
  316. IClientLOGServiceUpdateRequest* tptrRequest;
  317. if( m_bModelRequest )
  318. {
  319. tptrRequest = dynamic_cast<IClientLOGServiceUpdateRequest*>(m_pLoggingService->createUpdateModelLogServiceRequest());
  320. } else {
  321. tptrRequest = m_pLoggingService->createUpdateLogServiceRequest();
  322. }
  323. Owned<IClientLOGServiceUpdateRequest> pRequest( tptrRequest );
  324. if (pRequest == 0)
  325. return false;
  326. pRequest->setUserName(user);
  327. pRequest->setDomainName(realm);
  328. pRequest->setRecordCount(_LogStruct.recordsReturned);
  329. pRequest->setServiceName(_LogStruct.serviceName);
  330. pRequest->setIP(peer);
  331. //This appends the tree structure into the correct format...
  332. pRequest->setLogInformation(LogArray);
  333. return queueLog(pRequest,_LogStruct);
  334. }
  335. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, IPropertyTree& logInfo)
  336. {
  337. LOG_INFO _LogInfo(serviceName,RecordsReturned,false);
  338. IArrayOf<IEspLogInfo> LogArray;
  339. return queueLog(context,_LogInfo, LogArray, logInfo);
  340. }
  341. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,const char* GUID, int RecordsReturned, IPropertyTree& logInfo)
  342. {
  343. LOG_INFO _LogInfo(serviceName,GUID, RecordsReturned,false);
  344. IArrayOf<IEspLogInfo> LogArray;
  345. return queueLog(context,_LogInfo, LogArray, logInfo);
  346. }
  347. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned,IArrayOf<IEspLogInfo>& LogArray, IPropertyTree& logInfo)
  348. {
  349. LOG_INFO _LogStruct(serviceName,RecordsReturned,0);
  350. return queueLog(context,_LogStruct,LogArray, logInfo);
  351. }
  352. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, IArrayOf<IEspLogInfo>& LogArray)
  353. {
  354. LOG_INFO _LogStruct(serviceName,RecordsReturned,false);
  355. return queueLog(context,_LogStruct, LogArray);
  356. }
  357. bool CLogThread::queueLog(IEspContext & context,LOG_INFO& _LogStruct, IArrayOf<IEspLogInfo>& LogArray, IPropertyTree& logInfo)
  358. {
  359. //This appends the tree structure into the correct format...
  360. addLogInfo(LogArray,logInfo);
  361. return queueLog(context,_LogStruct, LogArray); ;
  362. }
  363. bool CLogThread::queueLog(IEspContext & context,LOG_INFO& _LogStruct, IArrayOf<IEspLogInfo>& LogArray, IConstModelLogInformation* pModelLogInfo)
  364. {
  365. if(!m_pLoggingService.get())
  366. return false;
  367. //Owned<IClientLOGServiceUpdateRequest> pRequest = m_pLoggingService->createUpdateLogServiceRequest();
  368. IClientLOGServiceUpdateRequest* tptrRequest;
  369. if( m_bModelRequest )
  370. {
  371. IClientLOGServiceUpdateModelRequest* pUpdateModelRequest = m_pLoggingService->createUpdateModelLogServiceRequest();
  372. if(pModelLogInfo!=0)
  373. {
  374. pUpdateModelRequest->setModelLogInformation(*pModelLogInfo);
  375. }
  376. tptrRequest = dynamic_cast<IClientLOGServiceUpdateRequest*>(pUpdateModelRequest);
  377. } else {
  378. tptrRequest = m_pLoggingService->createUpdateLogServiceRequest();
  379. }
  380. Owned<IClientLOGServiceUpdateRequest> pRequest( tptrRequest );
  381. if (pRequest == 0)
  382. return false;
  383. StringBuffer UserID,realm,peer;
  384. pRequest->setUserName(context.getUserID(UserID).str());
  385. pRequest->setDomainName(context.getRealm(realm).str());
  386. pRequest->setRecordCount(_LogStruct.recordsReturned);
  387. pRequest->setServiceName(_LogStruct.serviceName);
  388. pRequest->setIP(context.getPeer(peer).str());
  389. bool bBlind = _LogStruct.Blind;
  390. bool bEncrypt = _LogStruct.Encrypt;
  391. ISecPropertyList* properties = context.querySecuritySettings();
  392. if( properties !=NULL)
  393. {
  394. if(bBlind==false)
  395. {
  396. if(properties->findProperty("blind")!=NULL)
  397. strncmp(properties->findProperty("blind")->getValue(),"1",1) == 0 ? bBlind=true : bBlind=false;
  398. }
  399. if(bEncrypt==false && properties->findProperty("encryptedlogging")!=NULL)
  400. {
  401. if(strncmp(properties->findProperty("encryptedlogging")->getValue(),"1",1) == 0)
  402. bEncrypt=true;
  403. }
  404. }
  405. if(bEncrypt==true)
  406. {
  407. //need to do encrpyted logging
  408. pRequest->setEncryptedLogging(true);
  409. pRequest->setRawLogInformation(_LogStruct.RequestStr.str());
  410. }
  411. pRequest->setBlindLogging(bBlind);
  412. pRequest->setLogInformation(LogArray);
  413. return queueLog(pRequest,_LogStruct);
  414. }
  415. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, StringBuffer& logInfo)
  416. {
  417. return queueLog(context,serviceName,RecordsReturned,logInfo.str());
  418. }
  419. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned,IArrayOf<IEspLogInfo>& LogArray, StringBuffer& logInfo)
  420. {
  421. Owned<IPropertyTree> pLogTreeInfo = createPTreeFromXMLString(logInfo, ipt_none, xr_none);
  422. return queueLog(context,serviceName,RecordsReturned,LogArray, *pLogTreeInfo.get());
  423. }
  424. bool CLogThread::queueLog(IEspContext & context,const char* serviceName, const char* request, const char* response)
  425. {
  426. IProperties* pProperties = context.queryRequestParameters();
  427. StringBuffer UserID, UserRealm, UserReference, peer;
  428. if(pProperties != NULL && pProperties->hasProp("userid_"))
  429. UserID.appendf("%s",pProperties->queryProp("userid_"));
  430. else
  431. context.getUserID(UserID);
  432. if(pProperties != NULL && pProperties->hasProp("fqdn_"))
  433. UserRealm.appendf("%s",pProperties->queryProp("fqdn_"));
  434. else
  435. context.getRealm(UserRealm);
  436. Owned<IPropertyTree> pLogTreeInfo = createPTreeFromXMLString(request, ipt_none, xr_none);
  437. IArrayOf<IEspLogInfo> LogArray;
  438. addLogInfo(LogArray, *pLogTreeInfo.get());
  439. if(pProperties != NULL && pProperties->hasProp("referencecode_"))
  440. {
  441. //lets manually add the reference number....
  442. IClientLogInfo& LogInfoTransaction = addLogInfoElement(LogArray);
  443. LogInfoTransaction.setName("referencenumber");
  444. LogInfoTransaction.setValue(pProperties->queryProp("referencecode_"));
  445. }
  446. LOG_INFO _LogStruct(serviceName,-1,false);
  447. return queueLog(UserID.str(), UserRealm.str() , context.getPeer(peer).str(),_LogStruct, LogArray );
  448. }
  449. bool CLogThread::queueLog(IEspContext & context,const char* serviceName,int RecordsReturned, const char* logInfo)
  450. {
  451. try {
  452. Owned<IPropertyTree> pLogTreeInfo = createPTreeFromXMLString(logInfo, ipt_none, xr_none);
  453. return queueLog(context,serviceName,RecordsReturned,*pLogTreeInfo);
  454. } catch (IException* e) {
  455. StringBuffer msg;
  456. e->errorMessage(msg);
  457. DBGLOG("Exception caught in CLogThread::queueLog: %s", msg.str());
  458. return false;
  459. } catch (...) {
  460. DBGLOG("Unknown exception caught in CLogThread::queueLog()");
  461. return false;
  462. }
  463. }
  464. bool CLogThread::queueLog(IClientLOGServiceUpdateRequest * pRequest,LOG_INFO& _LogStruct)
  465. {
  466. int QueueSize = m_pServiceLog.ordinality();
  467. //YMA: this is bad. Transaction records will be lost because of this exception. Better to let the queue keep growing so that transactions will be
  468. // written to the tank file. Plus, most deployments configure the MaxLogQueueLength to be 10000, which is way too small.
  469. //if(QueueSize > m_MaxLogQueueLength)
  470. // throw MakeStringException(503,"Service Unavailable (Audit)");
  471. if(QueueSize > m_MaxLogQueueLength)
  472. ERRLOG("SOS!!! Logging queue size %d execeeded MaxLogQueueLength %d, check the logging server at %s!!!",QueueSize, m_MaxLogQueueLength, m_ServiceURL.str());
  473. if(QueueSize!=0 && QueueSize % m_SignalGrowingQueueAt == 0)
  474. ERRLOG("Logging Queue at %d records. Check the logging server at %s.",QueueSize, m_ServiceURL.str());
  475. if(m_bFailSafeLogging == true && m_LogFailSafe.get())
  476. {
  477. //generate a GUID for the query. The cache it within the failsafe object
  478. StringBuffer _GUID;
  479. if(_LogStruct.GUID !=NULL && *_LogStruct.GUID!='\0')
  480. {
  481. _GUID.appendf("%s",_LogStruct.GUID.str());
  482. }
  483. else
  484. {
  485. m_LogFailSafe->GenerateGUID(_GUID,_LogStruct.GUIDSeed);
  486. }
  487. pRequest->setGUID(_GUID.str());
  488. m_LogFailSafe->Add(_GUID,*pRequest);
  489. }
  490. m_pServiceLog.enqueue(LINK(pRequest));
  491. if (++m_Logcount >= m_LogTreshhold && m_LogSendDelta == 0)
  492. {
  493. m_sem.signal();
  494. m_Logcount = 0;
  495. }
  496. return true;
  497. }
  498. void CLogThread::addLogInfo(IArrayOf<IEspLogInfo>& valueArray,IPropertyTree& logInfo)
  499. {
  500. StringBuffer dataStr,nameStr,valueStr;
  501. Owned<IPropertyTreeIterator> itr = logInfo.getElements("*");
  502. itr->first();
  503. while(itr->isValid())
  504. {
  505. IPropertyTree &node = itr->query();
  506. const char* name = node.queryName();
  507. if (getTreeFlattening()==true && node.hasChildren() == true)
  508. {
  509. if(IsArray(node)==true)
  510. {
  511. FlattenArray(valueArray,node,nameStr);
  512. }
  513. else
  514. {
  515. FlattenTree(valueArray,node,nameStr);
  516. }
  517. // logElement.setName(node.queryName());
  518. // dataStr.clear();
  519. /*toXML(&node,dataStr);
  520. //DOM temporary work about for the lack of XML decoding in esp arrays
  521. StringBuffer encodedData;
  522. JBASE64_Encode(dataStr.str(), dataStr.length() , encodedData);
  523. logElement.setData(encodedData.str());
  524. */
  525. }
  526. else if (getTreeFlattening()==false && node.hasChildren() == true)
  527. {
  528. IClientLogInfo& logElement = addLogInfoElement(valueArray);
  529. logElement.setName(node.queryName());
  530. dataStr.clear();
  531. toXML(&node,dataStr);
  532. //DOM temporary work about for the lack of XML decoding in esp arrays
  533. StringBuffer encodedData;
  534. JBASE64_Encode(dataStr.str(), dataStr.length() , encodedData);
  535. logElement.setData(encodedData.str());
  536. }
  537. else if (node.queryProp("") != 0 && ( strcmp(node.queryProp(""),"0") != 0 ))
  538. {
  539. IClientLogInfo& logElement = addLogInfoElement(valueArray);
  540. logElement.setName(node.queryName());
  541. logElement.setValue(node.queryProp(""));
  542. }
  543. itr->next();
  544. }
  545. }
  546. bool CLogThread::IsArray(IPropertyTree& tree)
  547. {
  548. // If the node have more than one children, and all have the same name,
  549. // then it is an array.
  550. StringBuffer name, temp;
  551. Owned<IPropertyTreeIterator> itr = tree.getElements("*");
  552. int count = 0;
  553. for (itr->first(); itr->isValid(); itr->next())
  554. {
  555. if (count==0)
  556. itr->query().getName(name);
  557. else
  558. {
  559. itr->query().getName(temp);
  560. if (stricmp(name,temp)!=0)
  561. return false;
  562. temp.clear();
  563. }
  564. count++;
  565. }
  566. //Loophole in code above if there is only 1 item in the array
  567. if(count==1)
  568. {
  569. if (name!=NULL && stricmp(name,"Item")==0)
  570. return true;
  571. }
  572. return count>1;
  573. }
  574. bool CLogThread::FlattenArray(IArrayOf<IEspLogInfo>& valueArray,IPropertyTree& tree,StringBuffer& RootName)
  575. {
  576. StringBuffer Value,Name;
  577. if (tree.hasChildren() == true)
  578. {
  579. Name.appendf("%s",tree.queryName());
  580. Owned<IPropertyTreeIterator> itrItem = tree.getElements("./*");
  581. itrItem->first();
  582. while(itrItem->isValid()==true)
  583. {
  584. IPropertyTree &node = itrItem->query();
  585. if(Value.length()!=0)
  586. Value.append(",");
  587. Value.appendf("%s",node.queryProp(""));
  588. itrItem->next();
  589. }
  590. IClientLogInfo& logElement = addLogInfoElement(valueArray);
  591. logElement.setName(Name.str());
  592. logElement.setValue(Value.str());
  593. }
  594. return true;
  595. }
  596. bool CLogThread::FlattenTree(IArrayOf<IEspLogInfo>& valueArray,IPropertyTree& tree,StringBuffer& RootName)
  597. {
  598. StringBuffer Value,Name;
  599. if (tree.hasChildren() == true)
  600. {
  601. Owned<IPropertyTreeIterator> itr = tree.getElements("*");
  602. itr->first();
  603. while(itr->isValid())
  604. {
  605. IPropertyTree &node = itr->query();
  606. if(RootName.length() > 0)
  607. Name.appendf("%s_",RootName.str());
  608. Name.appendf("%s",node.queryName());
  609. if (node.hasChildren() == true)
  610. {
  611. if(IsArray(node)==true)
  612. FlattenArray(valueArray,node,Name);
  613. else
  614. FlattenTree(valueArray,node,Name);
  615. }
  616. else
  617. {
  618. const char* _value = tree.queryProp(node.queryName());
  619. if(tree.hasProp(node.queryName())==true && _value!=0 && _value!='\0')
  620. {
  621. Value.appendf("%s",tree.queryProp(node.queryName()));
  622. IClientLogInfo& logElement = addLogInfoElement(valueArray);
  623. logElement.setName(Name.str());
  624. logElement.setValue(Value.str());
  625. //DBGLOG("Add log element: %s, %s", Name.str(), Value.str());
  626. Value.clear();
  627. }
  628. }
  629. Name.clear();
  630. itr->next();
  631. }
  632. }
  633. else
  634. {
  635. return false;
  636. }
  637. return true;
  638. }
  639. void CLogThread::deserializeLogInfo(IArrayOf<IEspLogInfo>& valueArray,IPropertyTree& logInfo)
  640. {
  641. Owned<IPropertyTreeIterator> itr = logInfo.getElements("LogInfo");
  642. itr->first();
  643. while(itr->isValid())
  644. {
  645. IPropertyTree &node = itr->query();
  646. IClientLogInfo& logElement = addLogInfoElement(valueArray);
  647. logElement.setName(node.queryProp("Name"));
  648. logElement.setValue(node.queryProp("Value"));
  649. logElement.setData(node.queryProp("Data"));
  650. itr->next();
  651. }
  652. }
  653. int CLogThread::run()
  654. {
  655. Link();
  656. CheckErrorLogs();
  657. while(m_bRun)
  658. {
  659. m_sem.wait(10000);
  660. SendLog();
  661. checkRollOver();
  662. }
  663. Release();
  664. return 0;
  665. }
  666. void CLogThread::checkRollOver()
  667. {
  668. if(!m_LogFailSafe.get())
  669. return;
  670. try
  671. {
  672. time_t tNow;
  673. time(&tNow);
  674. struct tm ltNow;
  675. localtime_r(&tNow, &ltNow);
  676. if(ltNow.tm_year != m_startTime.tm_year || ltNow.tm_yday != m_startTime.tm_yday)
  677. {
  678. localtime_r(&tNow, &m_startTime); // reset the start time for next rollover check
  679. int numNewArrivals = m_pServiceLog.ordinality();
  680. {
  681. MTimeSection mt(NULL, "Tank file rollover");
  682. m_LogFailSafe->SafeRollover();
  683. }
  684. if(numNewArrivals > 0)
  685. {
  686. DBGLOG("writing %d requests in the queue to the rolled over tank file.", numNewArrivals);
  687. for(int i = 0; i < numNewArrivals; i++)
  688. {
  689. IClientLOGServiceUpdateRequest* pRequest = m_pServiceLog.item(i);
  690. if (pRequest)
  691. {
  692. IEspLOGServiceUpdateRequest* pEspRequest = dynamic_cast<IEspLOGServiceUpdateRequest*>(pRequest);
  693. if(pEspRequest)
  694. {
  695. const char* guid = pEspRequest->getGUID();
  696. if(guid)
  697. m_LogFailSafe->Add(guid,*pRequest);
  698. }
  699. }
  700. }
  701. }
  702. }
  703. }
  704. catch(IException* Ex)
  705. {
  706. StringBuffer str;
  707. Ex->errorMessage(str);
  708. ERRLOG("Exception thrown during tank file rollover: %s",str.str());
  709. Ex->Release();
  710. }
  711. catch(...)
  712. {
  713. ERRLOG("Unknown exception thrown during tank file rollover.");
  714. }
  715. }
  716. void CLogThread::CheckErrorLogs()
  717. {
  718. if(!m_LogFailSafe.get())
  719. return;
  720. try{
  721. bool bRelogError = false;
  722. if(m_LogFailSafe->FindOldLogs() == true)
  723. {
  724. DBGLOG("We have old logs!!!!!!");
  725. DBGLOG("Will now try and recover the lost log messages");
  726. StringArray LostLogMessages;
  727. m_LogFailSafe->LoadOldLogs(LostLogMessages);
  728. ForEachItemIn(aidx, LostLogMessages)
  729. {
  730. LOG_INFO _Info;
  731. Owned<IClientLOGServiceUpdateRequest> pRequest = DeserializeRequest(LostLogMessages.item(aidx),_Info);
  732. if (pRequest==0 || queueLog(pRequest,_Info) == false)
  733. bRelogError=true;
  734. }
  735. }
  736. //if everything went ok then we should be able to rollover the old logs.
  737. if(bRelogError == false)
  738. m_LogFailSafe->RollOldLogs();
  739. }
  740. catch(IException* ex)
  741. {
  742. StringBuffer errorStr;
  743. ex->errorMessage(errorStr);
  744. errorStr.appendf("%s",errorStr.str());
  745. ERRLOG("CheckErrorLogs: %s:" ,errorStr.str());
  746. ex->Release();
  747. }
  748. catch(...)
  749. {
  750. ERRLOG("Unknown exception thrown in CheckErrorLogs");
  751. }
  752. }
  753. IClientLOGServiceUpdateRequest* CLogThread::DeserializeRequest(const char* requestStr,LOG_INFO& _Info)
  754. {
  755. if(!requestStr)
  756. return 0;
  757. //
  758. //
  759. IClientLOGServiceUpdateRequest* pRequest = 0;
  760. if( m_bModelRequest )
  761. {
  762. pRequest = dynamic_cast<IClientLOGServiceUpdateRequest*>(m_pLoggingService->createUpdateModelLogServiceRequest());
  763. } else {
  764. pRequest = m_pLoggingService->createUpdateLogServiceRequest();
  765. }
  766. if (pRequest == 0)
  767. return 0;
  768. StringBuffer xPath,GUID,Cache;
  769. //request should be in the form GUID\tCache
  770. m_LogFailSafe->SplitLogRecord(requestStr,GUID,Cache);
  771. _Info.GUID = GUID.str();
  772. Owned<IPropertyTree> pLogTree = createPTreeFromXMLString(Cache.str(), ipt_none, xr_none);
  773. pRequest->setUserName(pLogTree->queryProp("UserName"));
  774. pRequest->setDomainName(pLogTree->queryProp("DomainName"));
  775. pRequest->setRecordCount(pLogTree->getPropInt("RecordCount"));
  776. pRequest->setServiceName(pLogTree->queryProp("ServiceName"));
  777. pRequest->setIP(pLogTree->queryProp("IP"));
  778. pRequest->setRawLogInformation(pLogTree->queryProp("RawLogInformation"));
  779. if(pLogTree->hasProp("EncryptedLogging")==true)
  780. pRequest->setEncryptedLogging(pLogTree->getPropBool("EncryptedLogging"));
  781. if(pLogTree->hasProp("BlindLogging")==true)
  782. pRequest->setBlindLogging(pLogTree->getPropBool("BlindLogging"));
  783. IArrayOf<IEspLogInfo> logArray;
  784. IPropertyTree* logInfo = pLogTree->queryBranch("LogInformation");
  785. if(logInfo)
  786. deserializeLogInfo(logArray,*logInfo);
  787. pRequest->setLogInformation(logArray);
  788. Owned<IConstModelLogInformation> modelLogInformation;
  789. if(m_bModelRequest)
  790. {
  791. IPropertyTree* pModelLogTree = pLogTree->queryBranch("ModelLogInformation");
  792. if(pModelLogTree!=0)
  793. {
  794. IClientModelLogInformation* pClientModelLogInfo = &getModelLogInformation();
  795. UnserializeModelLogInfo(pModelLogTree,pClientModelLogInfo);
  796. modelLogInformation.setown(dynamic_cast<IConstModelLogInformation*>(pClientModelLogInfo));
  797. IClientLOGServiceUpdateModelRequest* pModelRequest = dynamic_cast<IClientLOGServiceUpdateModelRequest*>(pRequest);
  798. pModelRequest->setModelLogInformation(dynamic_cast<IConstModelLogInformation&>(*pClientModelLogInfo));
  799. }
  800. }
  801. return pRequest;
  802. }
  803. void CLogThread::UnserializeModelLogInfo(IPropertyTree* pModelTreeInfo,IClientModelLogInformation* pModelLogInformation)
  804. {
  805. try
  806. {
  807. Owned<IPropertyTreeIterator> modelItr = pModelTreeInfo->getElements("Models/Model");
  808. if (modelItr->first())
  809. {
  810. while(modelItr->isValid()==true)
  811. {
  812. IPropertyTree& modelSrc = modelItr->query();
  813. IClientModelLogInfo& model = getModelLogInfo(pModelLogInformation);
  814. model.setName(modelSrc.queryProp("Name"));
  815. int scoreSequence = 0;
  816. Owned<IPropertyTreeIterator> ScoreItr = modelSrc.getElements("Scores/Score");
  817. if(ScoreItr->first())
  818. {
  819. while(ScoreItr->isValid()==true)
  820. {
  821. IPropertyTree& ScoreSrc = ScoreItr->query();
  822. IClientScoreLogInfo& Score = getScoreLogInfo(&model);
  823. Score.setName(ScoreSrc.queryProp("Name"));
  824. Score.setLogIdentifier(ScoreSrc.getPropInt("LogIdentifier"));
  825. Score.setValue( ScoreSrc.getPropInt("Value") );
  826. Score.setSequence(ScoreSrc.getPropInt("Sequence"));
  827. int reasonSequence = 0;
  828. Owned<IPropertyTreeIterator> ReasonItr = ScoreSrc.getElements("ReasonCodes/ReasonCode");
  829. if(ReasonItr->first())
  830. {
  831. while(ReasonItr->isValid()==true)
  832. {
  833. IPropertyTree& ReasonSrc = ReasonItr->query();
  834. IClientReasonCodeLogInfo& ReasonCode = getReasonCodeLogInfo(&Score);
  835. ReasonCode.setValue( ReasonSrc.queryProp("Value") );
  836. ReasonCode.setSequence( ReasonSrc.getPropInt("Sequence") );
  837. // leave off the description as it is not logged
  838. //if(ReasonSrc.hasProp("Description")==true)
  839. // ReasonCode.setDescription( ReasonSrc.queryProp("Description") );
  840. ReasonItr->next();
  841. reasonSequence++;
  842. }
  843. }
  844. scoreSequence++;
  845. ScoreItr->next();
  846. } // ScoreIter
  847. } // ScoreIter
  848. modelItr->next();
  849. } // ModelIter
  850. } // if any models
  851. Owned<IPropertyTreeIterator> attribGrpItr = pModelTreeInfo->getElements("AttributeGroups/AttributeGroup");
  852. if (attribGrpItr->first())
  853. {
  854. while(attribGrpItr->isValid()==true)
  855. {
  856. IPropertyTree& attribGrpSrc = attribGrpItr->query();
  857. IClientAttributeGroupLogInfo& attribGroup = getAttributeGroupLogInfo(pModelLogInformation);
  858. attribGroup.setName(attribGrpSrc.queryProp("Name"));
  859. if(attribGrpSrc.hasProp("index")==true)
  860. attribGroup.setLogIdentifier( attribGrpSrc.getPropInt("index") );
  861. Owned<IPropertyTreeIterator> attribItr = attribGrpSrc.getElements("Attributes/Attribute");
  862. if(attribItr->first())
  863. {
  864. while(attribItr->isValid()==true)
  865. {
  866. IPropertyTree& attribSrc = attribItr->query();
  867. IClientAttributeLogInfo& attrib = getAttributeLogInfo(&attribGroup);
  868. attrib.setName(attribSrc.queryProp("Name"));
  869. attrib.setValue(attribSrc.queryProp("Value"));
  870. attribItr->next();
  871. }
  872. }
  873. attribGrpItr->next();
  874. }
  875. }
  876. }
  877. catch (IException* e)
  878. {
  879. StringBuffer msg;
  880. ERRLOG("Fail to parse Model Log information: %s", e->errorMessage(msg).str());
  881. e->Release();
  882. }
  883. catch (...)
  884. {
  885. ERRLOG("Fail to parse Model Log information");
  886. }
  887. }
  888. void CLogThread::SendLog()
  889. {
  890. //TODO: returning here might cause SendDelta to be greater than 0, causing tank files not be able to rollover.
  891. if(m_bRun == false)
  892. return;
  893. int recSend = 0;
  894. IClientLOGServiceUpdateRequest* pRequest = 0;
  895. try{
  896. ForEachQueueItemIn(i,m_pServiceLog)
  897. {
  898. m_LogSend++;
  899. if(m_bThrottle)
  900. {
  901. if(m_BurstWaitInterval > 0 && m_LogSend % 10 == 0 && m_LogSendDelta > 5)
  902. {
  903. m_SenderSem.wait(m_BurstWaitInterval);
  904. }
  905. else if(m_LinearWaitInterval > 0)
  906. {
  907. m_SenderSem.wait(m_LinearWaitInterval);
  908. }
  909. }
  910. pRequest = (IClientLOGServiceUpdateRequest*)m_pServiceLog.dequeue();
  911. if (pRequest != 0)
  912. {
  913. IEspLOGServiceUpdateRequest* pEspRequest = dynamic_cast<IEspLOGServiceUpdateRequest*>(pRequest);
  914. try
  915. {
  916. //need to link once.....
  917. //ESPLOG(LogNormal+1,"Sending ACK %s",pEspRequest->getGUID());
  918. //DBGLOG("Sending log %s",pEspRequest->getGUID()?pEspRequest->getGUID():"");
  919. m_pLoggingService->async_UpdateLogService(pRequest, this, pRequest);
  920. pRequest->Release();
  921. m_LogSendDelta++;
  922. }
  923. catch(IException* Ex)
  924. {
  925. StringBuffer str;
  926. Ex->errorMessage(str);
  927. ERRLOG("Exception %s thrown within logging client",str.str());
  928. m_pServiceLog.enqueue(pRequest);
  929. Ex->Release();
  930. }
  931. catch(...)
  932. {
  933. ERRLOG("Unknown Error thrown within logging client");
  934. m_pServiceLog.enqueue(pRequest);
  935. }
  936. }
  937. }
  938. }
  939. catch(IException* e)
  940. {
  941. StringBuffer errorStr;
  942. e->errorMessage(errorStr);
  943. }
  944. catch(...)
  945. {
  946. int i = 0;
  947. }
  948. return;
  949. }
  950. void CLogThread::HandleLoggingServerResponse(IClientLOGServiceUpdateRequest* Request,IClientLOGServiceUpdateResponse *Response)
  951. {
  952. m_LogSendDelta--;
  953. if(Response==0 || Response->getUpdateLogStatus() == 0 || strlen(Response->getGUID())<10)
  954. {
  955. StringBuffer reasonbuf;
  956. if(Response == 0)
  957. reasonbuf.append("response is NULL");
  958. else if(Response->getUpdateLogStatus() == 0)
  959. reasonbuf.appendf("Log status is 0 for %s", Response->getGUID()?Response->getGUID():"");
  960. else
  961. reasonbuf.appendf("GUID(%s) is not correct", Response->getGUID()?Response->getGUID():"");
  962. DBGLOG("Failed at the server so adding back to the queue. Error: %s", reasonbuf.str());
  963. //means we failed..... so we will have to try again
  964. m_pServiceLog.enqueue(LINK(Request));
  965. return;
  966. }
  967. if(m_bFailSafeLogging == true && m_LogFailSafe.get())
  968. {
  969. //ESPLOG(LogNormal+1,"Adding ACK %s",Response->getGUID());
  970. //DBGLOG("Adding ACK %s",Response->getGUID());
  971. m_LogFailSafe->AddACK(Response->getGUID());
  972. }
  973. // m_SenderSem.signal();
  974. return;
  975. }
  976. int CLogThread::onUpdateLogServiceComplete(IClientLOGServiceUpdateResponse *Response,IInterface* state)
  977. {
  978. m_LogSend--;
  979. if(Response==0 && state==0)
  980. {
  981. DBGLOG("NULL LogRequest passed into onUpdateLogServiceComplete");
  982. return 0;
  983. }
  984. IClientLOGServiceUpdateRequest* Request = dynamic_cast<IClientLOGServiceUpdateRequest*>(state);
  985. if(Request==0)
  986. {
  987. DBGLOG("Could not cast state to IClientLOGServiceUpdateRequest");
  988. }
  989. HandleLoggingServerResponse(Request,Response);
  990. return 0;
  991. }
  992. int CLogThread::onUpdateModelLogServiceComplete(IClientLOGServiceUpdateResponse *Response,IInterface* state)
  993. {
  994. if(Response==0 && state==0)
  995. {
  996. DBGLOG("NULL LogRequest passed into onUpdateModelLogServiceComplete");
  997. return 0;
  998. }
  999. IClientLOGServiceUpdateModelRequest* Request = dynamic_cast<IClientLOGServiceUpdateModelRequest*>(state);
  1000. if(Request==0)
  1001. {
  1002. DBGLOG("Could not cast state to IClientLOGServiceUpdateModelRequest");
  1003. }
  1004. // For a UpdateModelRequest, first cast to it's parent class so
  1005. // we can use the same code in HandleLoggingServerResponse
  1006. IClientLOGServiceUpdateRequest* base_request = dynamic_cast<IClientLOGServiceUpdateRequest*>(state);
  1007. if( base_request == 0 )
  1008. {
  1009. DBGLOG("Could not cast state to IClientLOGServiceUpdateRequest to pass to HandleLoggingServerResponse");
  1010. return 0;
  1011. }
  1012. HandleLoggingServerResponse(base_request,Response);
  1013. return 0;
  1014. }
  1015. int CLogThread::onUpdateLogServiceError(IClientLOGServiceUpdateResponse *Response,IInterface* state)
  1016. {
  1017. DBGLOG("Error Log");
  1018. m_LogSend--;
  1019. IClientLOGServiceUpdateRequest* Request = dynamic_cast<IClientLOGServiceUpdateRequest*>(state);
  1020. if(Request==0)
  1021. {
  1022. DBGLOG("Could not cast state to IClientLOGServiceUpdateRequest");
  1023. }
  1024. HandleLoggingServerResponse(Request,Response);
  1025. return 0;
  1026. }
  1027. int CLogThread::onUpdateModelLogServiceError(IClientLOGServiceUpdateResponse *Response,IInterface* state)
  1028. {
  1029. DBGLOG("Error Log");
  1030. m_LogSend--;
  1031. IClientLOGServiceUpdateModelRequest* Request = dynamic_cast<IClientLOGServiceUpdateModelRequest*>(state);
  1032. if(Request==0)
  1033. {
  1034. DBGLOG("Could not cast state to IClientLOGServiceUpdateModelRequest");
  1035. }
  1036. // For a UpdateModelRequest, first cast to it's parent class so
  1037. // we can use the same code in HandleLoggingServerResponse
  1038. IClientLOGServiceUpdateRequest* base_request = dynamic_cast<IClientLOGServiceUpdateRequest*>(state);
  1039. if( base_request == 0 )
  1040. {
  1041. DBGLOG("Could not cast state to IClientLOGServiceUpdateRequest to pass to HandleLoggingServerResponse");
  1042. return 0;
  1043. }
  1044. HandleLoggingServerResponse(base_request,Response);
  1045. return 0;
  1046. }
  1047. void CLogThread::start()
  1048. {
  1049. if(m_NiceLevel > 0)
  1050. setNice(m_NiceLevel);
  1051. Thread::start();
  1052. }
  1053. void CLogThread::finish()
  1054. {
  1055. try{
  1056. DBGLOG("Log delta of %d",m_LogSendDelta);
  1057. if (m_pServiceLog.ordinality() == 0 && m_LogFailSafe.get() && m_LogSendDelta == 0)
  1058. m_LogFailSafe->RollCurrentLog();
  1059. }
  1060. catch(...){DBGLOG("Exception");}
  1061. m_bRun = false;
  1062. m_sem.signal();
  1063. join();
  1064. }
  1065. void CLogThread::CleanQueue()
  1066. {
  1067. ForEachQueueItemIn(i,m_pServiceLog)
  1068. {
  1069. IClientLOGServiceUpdateRequest* pRequest = (IClientLOGServiceUpdateRequest*)m_pServiceLog.dequeue();
  1070. if (pRequest != 0)
  1071. pRequest->Release();
  1072. }
  1073. }
  1074. void CPooledClientWsLogService::async_UpdateLogService(IClientLOGServiceUpdateRequest *request, IClientWsLogServiceEvents *events,IInterface* state)
  1075. {
  1076. if(m_url.length()==0){ throw MakeStringExceptionDirect(-1, "url not set"); }
  1077. CLOGServiceUpdateModelRequest* espModelRequest = dynamic_cast<CLOGServiceUpdateModelRequest*>(request);
  1078. CLOGServiceUpdateRequest* esprequest = dynamic_cast<CLOGServiceUpdateRequest*>(request);
  1079. if(espModelRequest!=0)
  1080. {
  1081. espModelRequest->setMethod("UpdateModelLogService");
  1082. espModelRequest->setReqId(m_reqId++);
  1083. espModelRequest->setEventSink(events);
  1084. espModelRequest->setState(state);
  1085. espModelRequest->setUserId(m_userid.str());
  1086. espModelRequest->setPassword(m_password.str());
  1087. espModelRequest->setRealm(m_realm.str());
  1088. espModelRequest->Link();
  1089. if(state!=NULL)
  1090. state->Link();
  1091. m_thread_pool->start((void *)(IRpcRequestBinding *)(espModelRequest), "Model Logging Thread", LogThreadWaitTime * 1000);
  1092. }else if(esprequest!=0)
  1093. {
  1094. esprequest->setMethod("UpdateLogService");
  1095. esprequest->setReqId(m_reqId++);
  1096. esprequest->setEventSink(events);
  1097. esprequest->setState(state);
  1098. esprequest->setUserId(m_userid.str());
  1099. esprequest->setPassword(m_password.str());
  1100. esprequest->setRealm(m_realm.str());
  1101. esprequest->Link();
  1102. if(state!=NULL)
  1103. state->Link();
  1104. m_thread_pool->start((void *)(IRpcRequestBinding *)(esprequest), "Logging Thread", LogThreadWaitTime * 1000);
  1105. }else{
  1106. throw MakeStringExceptionDirect(-1, "LogServiceUpdateRequest is null.");
  1107. }
  1108. }