LogThread.cpp 45 KB

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