PageRenderTime 234ms CodeModel.GetById 206ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llmessage/llpumpio.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1225 lines | 979 code | 82 blank | 164 comment | 126 complexity | ebdaf1d2775c78b0b70cfcbf2eecc990 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llpumpio.cpp
  3. * @author Phoenix
  4. * @date 2004-11-21
  5. * @brief Implementation of the i/o pump and related functions.
  6. *
  7. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #include "linden_common.h"
  29. #include "llpumpio.h"
  30. #include <map>
  31. #include <set>
  32. #include "apr_poll.h"
  33. #include "llapr.h"
  34. #include "llmemtype.h"
  35. #include "llstl.h"
  36. #include "llstat.h"
  37. // These should not be enabled in production, but they can be
  38. // intensely useful during development for finding certain kinds of
  39. // bugs.
  40. #if LL_LINUX
  41. //#define LL_DEBUG_PIPE_TYPE_IN_PUMP 1
  42. //#define LL_DEBUG_POLL_FILE_DESCRIPTORS 1
  43. #if LL_DEBUG_POLL_FILE_DESCRIPTORS
  44. #include "apr_portable.h"
  45. #endif
  46. #endif
  47. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  48. #include <typeinfo>
  49. #endif
  50. // constants for poll timeout. if we are threading, we want to have a
  51. // longer poll timeout.
  52. #if LL_THREADS_APR
  53. static const S32 DEFAULT_POLL_TIMEOUT = 1000;
  54. #else
  55. static const S32 DEFAULT_POLL_TIMEOUT = 0;
  56. #endif
  57. // The default (and fallback) expiration time for chains
  58. const F32 DEFAULT_CHAIN_EXPIRY_SECS = 30.0f;
  59. extern const F32 SHORT_CHAIN_EXPIRY_SECS = 1.0f;
  60. extern const F32 NEVER_CHAIN_EXPIRY_SECS = 0.0f;
  61. // sorta spammy debug modes.
  62. //#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR 1
  63. //#define LL_DEBUG_PROCESS_LINK 1
  64. //#define LL_DEBUG_PROCESS_RETURN_VALUE 1
  65. // Super spammy debug mode.
  66. //#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN 1
  67. //#define LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT 1
  68. //
  69. // local functions
  70. //
  71. void ll_debug_poll_fd(const char* msg, const apr_pollfd_t* poll)
  72. {
  73. #if LL_DEBUG_POLL_FILE_DESCRIPTORS
  74. if(!poll)
  75. {
  76. lldebugs << "Poll -- " << (msg?msg:"") << ": no pollfd." << llendl;
  77. return;
  78. }
  79. if(poll->desc.s)
  80. {
  81. apr_os_sock_t os_sock;
  82. if(APR_SUCCESS == apr_os_sock_get(&os_sock, poll->desc.s))
  83. {
  84. lldebugs << "Poll -- " << (msg?msg:"") << " on fd " << os_sock
  85. << " at " << poll->desc.s << llendl;
  86. }
  87. else
  88. {
  89. lldebugs << "Poll -- " << (msg?msg:"") << " no fd "
  90. << " at " << poll->desc.s << llendl;
  91. }
  92. }
  93. else if(poll->desc.f)
  94. {
  95. apr_os_file_t os_file;
  96. if(APR_SUCCESS == apr_os_file_get(&os_file, poll->desc.f))
  97. {
  98. lldebugs << "Poll -- " << (msg?msg:"") << " on fd " << os_file
  99. << " at " << poll->desc.f << llendl;
  100. }
  101. else
  102. {
  103. lldebugs << "Poll -- " << (msg?msg:"") << " no fd "
  104. << " at " << poll->desc.f << llendl;
  105. }
  106. }
  107. else
  108. {
  109. lldebugs << "Poll -- " << (msg?msg:"") << ": no descriptor." << llendl;
  110. }
  111. #endif
  112. }
  113. /**
  114. * @class
  115. */
  116. class LLChainSleeper : public LLRunnable
  117. {
  118. public:
  119. static LLRunner::run_ptr_t build(LLPumpIO* pump, S32 key)
  120. {
  121. return LLRunner::run_ptr_t(new LLChainSleeper(pump, key));
  122. }
  123. virtual void run(LLRunner* runner, S64 handle)
  124. {
  125. mPump->clearLock(mKey);
  126. }
  127. protected:
  128. LLChainSleeper(LLPumpIO* pump, S32 key) : mPump(pump), mKey(key) {}
  129. LLPumpIO* mPump;
  130. S32 mKey;
  131. };
  132. /**
  133. * @struct ll_delete_apr_pollset_fd_client_data
  134. * @brief This is a simple helper class to clean up our client data.
  135. */
  136. struct ll_delete_apr_pollset_fd_client_data
  137. {
  138. typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
  139. void operator()(const pipe_conditional_t& conditional)
  140. {
  141. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  142. S32* client_id = (S32*)conditional.second.client_data;
  143. delete client_id;
  144. }
  145. };
  146. /**
  147. * LLPumpIO
  148. */
  149. LLPumpIO::LLPumpIO(apr_pool_t* pool) :
  150. mState(LLPumpIO::NORMAL),
  151. mRebuildPollset(false),
  152. mPollset(NULL),
  153. mPollsetClientID(0),
  154. mNextLock(0),
  155. mPool(NULL),
  156. mCurrentPool(NULL),
  157. mCurrentPoolReallocCount(0),
  158. mChainsMutex(NULL),
  159. mCallbackMutex(NULL),
  160. mCurrentChain(mRunningChains.end())
  161. {
  162. mCurrentChain = mRunningChains.end();
  163. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  164. initialize(pool);
  165. }
  166. LLPumpIO::~LLPumpIO()
  167. {
  168. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  169. cleanup();
  170. }
  171. bool LLPumpIO::prime(apr_pool_t* pool)
  172. {
  173. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  174. cleanup();
  175. initialize(pool);
  176. return ((pool == NULL) ? false : true);
  177. }
  178. bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)
  179. {
  180. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  181. if(chain.empty()) return false;
  182. #if LL_THREADS_APR
  183. LLScopedLock lock(mChainsMutex);
  184. #endif
  185. LLChainInfo info;
  186. info.mHasCurlRequest = has_curl_request;
  187. info.setTimeoutSeconds(timeout);
  188. info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
  189. info.mData->setThreaded(has_curl_request);
  190. LLLinkInfo link;
  191. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  192. lldebugs << "LLPumpIO::addChain() " << chain[0] << " '"
  193. << typeid(*(chain[0])).name() << "'" << llendl;
  194. #else
  195. lldebugs << "LLPumpIO::addChain() " << chain[0] <<llendl;
  196. #endif
  197. chain_t::const_iterator it = chain.begin();
  198. chain_t::const_iterator end = chain.end();
  199. for(; it != end; ++it)
  200. {
  201. link.mPipe = (*it);
  202. link.mChannels = info.mData->nextChannel();
  203. info.mChainLinks.push_back(link);
  204. }
  205. mPendingChains.push_back(info);
  206. return true;
  207. }
  208. bool LLPumpIO::addChain(
  209. const LLPumpIO::links_t& links,
  210. LLIOPipe::buffer_ptr_t data,
  211. LLSD context,
  212. F32 timeout)
  213. {
  214. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  215. // remember that if the caller is providing a full link
  216. // description, we need to have that description matched to a
  217. // particular buffer.
  218. if(!data) return false;
  219. if(links.empty()) return false;
  220. #if LL_THREADS_APR
  221. LLScopedLock lock(mChainsMutex);
  222. #endif
  223. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  224. lldebugs << "LLPumpIO::addChain() " << links[0].mPipe << " '"
  225. << typeid(*(links[0].mPipe)).name() << "'" << llendl;
  226. #else
  227. lldebugs << "LLPumpIO::addChain() " << links[0].mPipe << llendl;
  228. #endif
  229. LLChainInfo info;
  230. info.setTimeoutSeconds(timeout);
  231. info.mChainLinks = links;
  232. info.mData = data;
  233. info.mContext = context;
  234. mPendingChains.push_back(info);
  235. return true;
  236. }
  237. bool LLPumpIO::setTimeoutSeconds(F32 timeout)
  238. {
  239. // If no chain is running, return failure.
  240. if(mRunningChains.end() == mCurrentChain)
  241. {
  242. return false;
  243. }
  244. (*mCurrentChain).setTimeoutSeconds(timeout);
  245. return true;
  246. }
  247. void LLPumpIO::adjustTimeoutSeconds(F32 delta)
  248. {
  249. // Ensure a chain is running
  250. if(mRunningChains.end() != mCurrentChain)
  251. {
  252. (*mCurrentChain).adjustTimeoutSeconds(delta);
  253. }
  254. }
  255. static std::string events_2_string(apr_int16_t events)
  256. {
  257. std::ostringstream ostr;
  258. if(events & APR_POLLIN)
  259. {
  260. ostr << "read,";
  261. }
  262. if(events & APR_POLLPRI)
  263. {
  264. ostr << "priority,";
  265. }
  266. if(events & APR_POLLOUT)
  267. {
  268. ostr << "write,";
  269. }
  270. if(events & APR_POLLERR)
  271. {
  272. ostr << "error,";
  273. }
  274. if(events & APR_POLLHUP)
  275. {
  276. ostr << "hangup,";
  277. }
  278. if(events & APR_POLLNVAL)
  279. {
  280. ostr << "invalid,";
  281. }
  282. return chop_tail_copy(ostr.str(), 1);
  283. }
  284. bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
  285. {
  286. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  287. if(!pipe) return false;
  288. ll_debug_poll_fd("Set conditional", poll);
  289. lldebugs << "Setting conditionals (" << (poll ? events_2_string(poll->reqevents) :"null")
  290. << ") "
  291. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  292. << "on pipe " << typeid(*pipe).name()
  293. #endif
  294. << " at " << pipe << llendl;
  295. // remove any matching poll file descriptors for this pipe.
  296. LLIOPipe::ptr_t pipe_ptr(pipe);
  297. LLChainInfo::conditionals_t::iterator it;
  298. it = (*mCurrentChain).mDescriptors.begin();
  299. while(it != (*mCurrentChain).mDescriptors.end())
  300. {
  301. LLChainInfo::pipe_conditional_t& value = (*it);
  302. if(pipe_ptr == value.first)
  303. {
  304. ll_delete_apr_pollset_fd_client_data()(value);
  305. it = (*mCurrentChain).mDescriptors.erase(it);
  306. mRebuildPollset = true;
  307. }
  308. else
  309. {
  310. ++it;
  311. }
  312. }
  313. if(!poll)
  314. {
  315. mRebuildPollset = true;
  316. return true;
  317. }
  318. LLChainInfo::pipe_conditional_t value;
  319. value.first = pipe_ptr;
  320. value.second = *poll;
  321. value.second.rtnevents = 0;
  322. if(!poll->p)
  323. {
  324. // each fd needs a pool to work with, so if one was
  325. // not specified, use this pool.
  326. // *FIX: Should it always be this pool?
  327. value.second.p = mPool;
  328. }
  329. value.second.client_data = new S32(++mPollsetClientID);
  330. (*mCurrentChain).mDescriptors.push_back(value);
  331. mRebuildPollset = true;
  332. return true;
  333. }
  334. S32 LLPumpIO::setLock()
  335. {
  336. // *NOTE: I do not think it is necessary to acquire a mutex here
  337. // since this should only be called during the pump(), and should
  338. // only change the running chain. Any other use of this method is
  339. // incorrect usage. If it becomes necessary to acquire a lock
  340. // here, be sure to lock here and call a protected method to get
  341. // the lock, and sleepChain() should probably acquire the same
  342. // lock while and calling the same protected implementation to
  343. // lock the runner at the same time.
  344. // If no chain is running, return failure.
  345. if(mRunningChains.end() == mCurrentChain)
  346. {
  347. return 0;
  348. }
  349. // deal with wrap.
  350. if(++mNextLock <= 0)
  351. {
  352. mNextLock = 1;
  353. }
  354. // set the lock
  355. (*mCurrentChain).mLock = mNextLock;
  356. return mNextLock;
  357. }
  358. void LLPumpIO::clearLock(S32 key)
  359. {
  360. // We need to lock it here since we do not want to be iterating
  361. // over the chains twice. We can safely call process() while this
  362. // is happening since we should not be erasing a locked pipe, and
  363. // therefore won't be treading into deleted memory. I think we can
  364. // also clear the lock on the chain safely since the pump only
  365. // reads that value.
  366. #if LL_THREADS_APR
  367. LLScopedLock lock(mChainsMutex);
  368. #endif
  369. mClearLocks.insert(key);
  370. }
  371. bool LLPumpIO::sleepChain(F64 seconds)
  372. {
  373. // Much like the call to setLock(), this should only be called
  374. // from one chain during processing, so there is no need to
  375. // acquire a mutex.
  376. if(seconds <= 0.0) return false;
  377. S32 key = setLock();
  378. if(!key) return false;
  379. LLRunner::run_handle_t handle = mRunner.addRunnable(
  380. LLChainSleeper::build(this, key),
  381. LLRunner::RUN_IN,
  382. seconds);
  383. if(0 == handle) return false;
  384. return true;
  385. }
  386. bool LLPumpIO::copyCurrentLinkInfo(links_t& links) const
  387. {
  388. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  389. if(mRunningChains.end() == mCurrentChain)
  390. {
  391. return false;
  392. }
  393. std::copy(
  394. (*mCurrentChain).mChainLinks.begin(),
  395. (*mCurrentChain).mChainLinks.end(),
  396. std::back_insert_iterator<links_t>(links));
  397. return true;
  398. }
  399. void LLPumpIO::pump()
  400. {
  401. pump(DEFAULT_POLL_TIMEOUT);
  402. }
  403. static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO");
  404. LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain)
  405. {
  406. std::for_each(
  407. (*run_chain).mDescriptors.begin(),
  408. (*run_chain).mDescriptors.end(),
  409. ll_delete_apr_pollset_fd_client_data());
  410. return mRunningChains.erase(run_chain);
  411. }
  412. //timeout is in microseconds
  413. void LLPumpIO::pump(const S32& poll_timeout)
  414. {
  415. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  416. LLFastTimer t1(FTM_PUMP_IO);
  417. //llinfos << "LLPumpIO::pump()" << llendl;
  418. // Run any pending runners.
  419. mRunner.run();
  420. // We need to move all of the pending heads over to the running
  421. // chains.
  422. PUMP_DEBUG;
  423. if(true)
  424. {
  425. #if LL_THREADS_APR
  426. LLScopedLock lock(mChainsMutex);
  427. #endif
  428. // bail if this pump is paused.
  429. if(PAUSING == mState)
  430. {
  431. mState = PAUSED;
  432. }
  433. if(PAUSED == mState)
  434. {
  435. return;
  436. }
  437. PUMP_DEBUG;
  438. // Move the pending chains over to the running chaings
  439. if(!mPendingChains.empty())
  440. {
  441. PUMP_DEBUG;
  442. //lldebugs << "Pushing " << mPendingChains.size() << "." << llendl;
  443. std::copy(
  444. mPendingChains.begin(),
  445. mPendingChains.end(),
  446. std::back_insert_iterator<running_chains_t>(mRunningChains));
  447. mPendingChains.clear();
  448. PUMP_DEBUG;
  449. }
  450. // Clear any locks. This needs to be done here so that we do
  451. // not clash during a call to clearLock().
  452. if(!mClearLocks.empty())
  453. {
  454. PUMP_DEBUG;
  455. running_chains_t::iterator it = mRunningChains.begin();
  456. running_chains_t::iterator end = mRunningChains.end();
  457. std::set<S32>::iterator not_cleared = mClearLocks.end();
  458. for(; it != end; ++it)
  459. {
  460. if((*it).mLock && mClearLocks.find((*it).mLock) != not_cleared)
  461. {
  462. (*it).mLock = 0;
  463. }
  464. }
  465. PUMP_DEBUG;
  466. mClearLocks.clear();
  467. }
  468. }
  469. PUMP_DEBUG;
  470. // rebuild the pollset if necessary
  471. if(mRebuildPollset)
  472. {
  473. PUMP_DEBUG;
  474. rebuildPollset();
  475. mRebuildPollset = false;
  476. }
  477. // Poll based on the last known pollset
  478. // *TODO: may want to pass in a poll timeout so it works correctly
  479. // in single and multi threaded processes.
  480. PUMP_DEBUG;
  481. typedef std::map<S32, S32> signal_client_t;
  482. signal_client_t signalled_client;
  483. const apr_pollfd_t* poll_fd = NULL;
  484. if(mPollset)
  485. {
  486. PUMP_DEBUG;
  487. //llinfos << "polling" << llendl;
  488. S32 count = 0;
  489. S32 client_id = 0;
  490. {
  491. LLPerfBlock polltime("pump_poll");
  492. apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
  493. }
  494. PUMP_DEBUG;
  495. for(S32 ii = 0; ii < count; ++ii)
  496. {
  497. ll_debug_poll_fd("Signalled pipe", &poll_fd[ii]);
  498. client_id = *((S32*)poll_fd[ii].client_data);
  499. signalled_client[client_id] = ii;
  500. }
  501. PUMP_DEBUG;
  502. }
  503. PUMP_DEBUG;
  504. // set up for a check to see if each one was signalled
  505. signal_client_t::iterator not_signalled = signalled_client.end();
  506. // Process everything as appropriate
  507. //lldebugs << "Running chain count: " << mRunningChains.size() << llendl;
  508. running_chains_t::iterator run_chain = mRunningChains.begin();
  509. bool process_this_chain = false;
  510. while( run_chain != mRunningChains.end() )
  511. {
  512. PUMP_DEBUG;
  513. if((*run_chain).mInit
  514. && (*run_chain).mTimer.getStarted()
  515. && (*run_chain).mTimer.hasExpired())
  516. {
  517. PUMP_DEBUG;
  518. if(handleChainError(*run_chain, LLIOPipe::STATUS_EXPIRED))
  519. {
  520. // the pipe probably handled the error. If the handler
  521. // forgot to reset the expiration then we need to do
  522. // that here.
  523. if((*run_chain).mTimer.getStarted()
  524. && (*run_chain).mTimer.hasExpired())
  525. {
  526. PUMP_DEBUG;
  527. llinfos << "Error handler forgot to reset timeout. "
  528. << "Resetting to " << DEFAULT_CHAIN_EXPIRY_SECS
  529. << " seconds." << llendl;
  530. (*run_chain).setTimeoutSeconds(DEFAULT_CHAIN_EXPIRY_SECS);
  531. }
  532. }
  533. else
  534. {
  535. PUMP_DEBUG;
  536. // it timed out and no one handled it, so we need to
  537. // retire the chain
  538. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  539. lldebugs << "Removing chain "
  540. << (*run_chain).mChainLinks[0].mPipe
  541. << " '"
  542. << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
  543. << "' because it timed out." << llendl;
  544. #else
  545. // lldebugs << "Removing chain "
  546. // << (*run_chain).mChainLinks[0].mPipe
  547. // << " because we reached the end." << llendl;
  548. #endif
  549. run_chain = removeRunningChain(run_chain);
  550. continue;
  551. }
  552. }
  553. else if(isChainExpired(*run_chain))
  554. {
  555. run_chain = removeRunningChain(run_chain);
  556. continue;
  557. }
  558. PUMP_DEBUG;
  559. if((*run_chain).mLock)
  560. {
  561. ++run_chain;
  562. continue;
  563. }
  564. PUMP_DEBUG;
  565. mCurrentChain = run_chain;
  566. if((*run_chain).mDescriptors.empty())
  567. {
  568. // if there are no conditionals, just process this chain.
  569. process_this_chain = true;
  570. //lldebugs << "no conditionals - processing" << llendl;
  571. }
  572. else
  573. {
  574. PUMP_DEBUG;
  575. //lldebugs << "checking conditionals" << llendl;
  576. // Check if this run chain was signalled. If any file
  577. // descriptor is ready for something, then go ahead and
  578. // process this chian.
  579. process_this_chain = false;
  580. if(!signalled_client.empty())
  581. {
  582. PUMP_DEBUG;
  583. LLChainInfo::conditionals_t::iterator it;
  584. it = (*run_chain).mDescriptors.begin();
  585. LLChainInfo::conditionals_t::iterator end;
  586. end = (*run_chain).mDescriptors.end();
  587. S32 client_id = 0;
  588. signal_client_t::iterator signal;
  589. for(; it != end; ++it)
  590. {
  591. PUMP_DEBUG;
  592. client_id = *((S32*)((*it).second.client_data));
  593. signal = signalled_client.find(client_id);
  594. if (signal == not_signalled) continue;
  595. static const apr_int16_t POLL_CHAIN_ERROR =
  596. APR_POLLHUP | APR_POLLNVAL | APR_POLLERR;
  597. const apr_pollfd_t* poll = &(poll_fd[(*signal).second]);
  598. if(poll->rtnevents & POLL_CHAIN_ERROR)
  599. {
  600. // Potential eror condition has been
  601. // returned. If HUP was one of them, we pass
  602. // that as the error even though there may be
  603. // more. If there are in fact more errors,
  604. // we'll just wait for that detection until
  605. // the next pump() cycle to catch it so that
  606. // the logic here gets no more strained than
  607. // it already is.
  608. LLIOPipe::EStatus error_status;
  609. if(poll->rtnevents & APR_POLLHUP)
  610. error_status = LLIOPipe::STATUS_LOST_CONNECTION;
  611. else
  612. error_status = LLIOPipe::STATUS_ERROR;
  613. if(handleChainError(*run_chain, error_status)) break;
  614. ll_debug_poll_fd("Removing pipe", poll);
  615. llwarns << "Removing pipe "
  616. << (*run_chain).mChainLinks[0].mPipe
  617. << " '"
  618. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  619. << typeid(
  620. *((*run_chain).mChainLinks[0].mPipe)).name()
  621. #endif
  622. << "' because: "
  623. << events_2_string(poll->rtnevents)
  624. << llendl;
  625. (*run_chain).mHead = (*run_chain).mChainLinks.end();
  626. break;
  627. }
  628. // at least 1 fd got signalled, and there were no
  629. // errors. That means we process this chain.
  630. process_this_chain = true;
  631. break;
  632. }
  633. }
  634. }
  635. if(process_this_chain)
  636. {
  637. PUMP_DEBUG;
  638. if(!((*run_chain).mInit))
  639. {
  640. (*run_chain).mHead = (*run_chain).mChainLinks.begin();
  641. (*run_chain).mInit = true;
  642. }
  643. PUMP_DEBUG;
  644. processChain(*run_chain);
  645. }
  646. PUMP_DEBUG;
  647. if((*run_chain).mHead == (*run_chain).mChainLinks.end())
  648. {
  649. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  650. lldebugs << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
  651. << " '"
  652. << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
  653. << "' because we reached the end." << llendl;
  654. #else
  655. // lldebugs << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
  656. // << " because we reached the end." << llendl;
  657. #endif
  658. PUMP_DEBUG;
  659. // This chain is done. Clean up any allocated memory and
  660. // erase the chain info.
  661. run_chain = removeRunningChain(run_chain);
  662. // *NOTE: may not always need to rebuild the pollset.
  663. mRebuildPollset = true;
  664. }
  665. else
  666. {
  667. PUMP_DEBUG;
  668. // this chain needs more processing - just go to the next
  669. // chain.
  670. ++run_chain;
  671. }
  672. }
  673. PUMP_DEBUG;
  674. // null out the chain
  675. mCurrentChain = mRunningChains.end();
  676. END_PUMP_DEBUG;
  677. }
  678. //bool LLPumpIO::respond(const chain_t& pipes)
  679. //{
  680. //#if LL_THREADS_APR
  681. // LLScopedLock lock(mCallbackMutex);
  682. //#endif
  683. // LLChainInfo info;
  684. // links_t links;
  685. //
  686. // mPendingCallbacks.push_back(info);
  687. // return true;
  688. //}
  689. bool LLPumpIO::respond(LLIOPipe* pipe)
  690. {
  691. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  692. if(NULL == pipe) return false;
  693. #if LL_THREADS_APR
  694. LLScopedLock lock(mCallbackMutex);
  695. #endif
  696. LLChainInfo info;
  697. LLLinkInfo link;
  698. link.mPipe = pipe;
  699. info.mChainLinks.push_back(link);
  700. mPendingCallbacks.push_back(info);
  701. return true;
  702. }
  703. bool LLPumpIO::respond(
  704. const links_t& links,
  705. LLIOPipe::buffer_ptr_t data,
  706. LLSD context)
  707. {
  708. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  709. // if the caller is providing a full link description, we need to
  710. // have that description matched to a particular buffer.
  711. if(!data) return false;
  712. if(links.empty()) return false;
  713. #if LL_THREADS_APR
  714. LLScopedLock lock(mCallbackMutex);
  715. #endif
  716. // Add the callback response
  717. LLChainInfo info;
  718. info.mChainLinks = links;
  719. info.mData = data;
  720. info.mContext = context;
  721. mPendingCallbacks.push_back(info);
  722. return true;
  723. }
  724. static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain");
  725. void LLPumpIO::callback()
  726. {
  727. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  728. //llinfos << "LLPumpIO::callback()" << llendl;
  729. if(true)
  730. {
  731. #if LL_THREADS_APR
  732. LLScopedLock lock(mCallbackMutex);
  733. #endif
  734. std::copy(
  735. mPendingCallbacks.begin(),
  736. mPendingCallbacks.end(),
  737. std::back_insert_iterator<callbacks_t>(mCallbacks));
  738. mPendingCallbacks.clear();
  739. }
  740. if(!mCallbacks.empty())
  741. {
  742. callbacks_t::iterator it = mCallbacks.begin();
  743. callbacks_t::iterator end = mCallbacks.end();
  744. for(; it != end; ++it)
  745. {
  746. LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN);
  747. // it's always the first and last time for respone chains
  748. (*it).mHead = (*it).mChainLinks.begin();
  749. (*it).mInit = true;
  750. (*it).mEOS = true;
  751. processChain(*it);
  752. }
  753. mCallbacks.clear();
  754. }
  755. }
  756. void LLPumpIO::control(LLPumpIO::EControl op)
  757. {
  758. #if LL_THREADS_APR
  759. LLScopedLock lock(mChainsMutex);
  760. #endif
  761. switch(op)
  762. {
  763. case PAUSE:
  764. mState = PAUSING;
  765. break;
  766. case RESUME:
  767. mState = NORMAL;
  768. break;
  769. default:
  770. // no-op
  771. break;
  772. }
  773. }
  774. void LLPumpIO::initialize(apr_pool_t* pool)
  775. {
  776. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  777. if(!pool) return;
  778. #if LL_THREADS_APR
  779. // SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
  780. apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool);
  781. apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool);
  782. #endif
  783. mPool = pool;
  784. }
  785. void LLPumpIO::cleanup()
  786. {
  787. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  788. #if LL_THREADS_APR
  789. if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
  790. if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
  791. #endif
  792. mChainsMutex = NULL;
  793. mCallbackMutex = NULL;
  794. if(mPollset)
  795. {
  796. // lldebugs << "cleaning up pollset" << llendl;
  797. apr_pollset_destroy(mPollset);
  798. mPollset = NULL;
  799. }
  800. if(mCurrentPool)
  801. {
  802. apr_pool_destroy(mCurrentPool);
  803. mCurrentPool = NULL;
  804. }
  805. mPool = NULL;
  806. }
  807. void LLPumpIO::rebuildPollset()
  808. {
  809. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  810. // lldebugs << "LLPumpIO::rebuildPollset()" << llendl;
  811. if(mPollset)
  812. {
  813. //lldebugs << "destroying pollset" << llendl;
  814. apr_pollset_destroy(mPollset);
  815. mPollset = NULL;
  816. }
  817. U32 size = 0;
  818. running_chains_t::iterator run_it = mRunningChains.begin();
  819. running_chains_t::iterator run_end = mRunningChains.end();
  820. for(; run_it != run_end; ++run_it)
  821. {
  822. size += (*run_it).mDescriptors.size();
  823. }
  824. //lldebugs << "found " << size << " descriptors." << llendl;
  825. if(size)
  826. {
  827. // Recycle the memory pool
  828. const S32 POLLSET_POOL_RECYCLE_COUNT = 100;
  829. if(mCurrentPool
  830. && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
  831. {
  832. apr_pool_destroy(mCurrentPool);
  833. mCurrentPool = NULL;
  834. mCurrentPoolReallocCount = 0;
  835. }
  836. if(!mCurrentPool)
  837. {
  838. apr_status_t status = apr_pool_create(&mCurrentPool, mPool);
  839. (void)ll_apr_warn_status(status);
  840. }
  841. // add all of the file descriptors
  842. run_it = mRunningChains.begin();
  843. LLChainInfo::conditionals_t::iterator fd_it;
  844. LLChainInfo::conditionals_t::iterator fd_end;
  845. apr_pollset_create(&mPollset, size, mCurrentPool, 0);
  846. for(; run_it != run_end; ++run_it)
  847. {
  848. fd_it = (*run_it).mDescriptors.begin();
  849. fd_end = (*run_it).mDescriptors.end();
  850. for(; fd_it != fd_end; ++fd_it)
  851. {
  852. apr_pollset_add(mPollset, &((*fd_it).second));
  853. }
  854. }
  855. }
  856. }
  857. void LLPumpIO::processChain(LLChainInfo& chain)
  858. {
  859. PUMP_DEBUG;
  860. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  861. LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
  862. links_t::iterator it = chain.mHead;
  863. links_t::iterator end = chain.mChainLinks.end();
  864. bool need_process_signaled = false;
  865. bool keep_going = true;
  866. do
  867. {
  868. #if LL_DEBUG_PROCESS_LINK
  869. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  870. llinfos << "Processing " << typeid(*((*it).mPipe)).name() << "."
  871. << llendl;
  872. #else
  873. llinfos << "Processing link " << (*it).mPipe << "." << llendl;
  874. #endif
  875. #endif
  876. #if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN
  877. if(chain.mData)
  878. {
  879. char* buf = NULL;
  880. S32 bytes = chain.mData->countAfter((*it).mChannels.in(), NULL);
  881. if(bytes)
  882. {
  883. buf = new char[bytes + 1];
  884. chain.mData->readAfter(
  885. (*it).mChannels.in(),
  886. NULL,
  887. (U8*)buf,
  888. bytes);
  889. buf[bytes] = '\0';
  890. llinfos << "CHANNEL IN(" << (*it).mChannels.in() << "): "
  891. << buf << llendl;
  892. delete[] buf;
  893. buf = NULL;
  894. }
  895. else
  896. {
  897. llinfos << "CHANNEL IN(" << (*it).mChannels.in()<< "): (null)"
  898. << llendl;
  899. }
  900. }
  901. #endif
  902. PUMP_DEBUG;
  903. status = (*it).mPipe->process(
  904. (*it).mChannels,
  905. chain.mData,
  906. chain.mEOS,
  907. chain.mContext,
  908. this);
  909. #if LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT
  910. if(chain.mData)
  911. {
  912. char* buf = NULL;
  913. S32 bytes = chain.mData->countAfter((*it).mChannels.out(), NULL);
  914. if(bytes)
  915. {
  916. buf = new char[bytes + 1];
  917. chain.mData->readAfter(
  918. (*it).mChannels.out(),
  919. NULL,
  920. (U8*)buf,
  921. bytes);
  922. buf[bytes] = '\0';
  923. llinfos << "CHANNEL OUT(" << (*it).mChannels.out()<< "): "
  924. << buf << llendl;
  925. delete[] buf;
  926. buf = NULL;
  927. }
  928. else
  929. {
  930. llinfos << "CHANNEL OUT(" << (*it).mChannels.out()<< "): (null)"
  931. << llendl;
  932. }
  933. }
  934. #endif
  935. #if LL_DEBUG_PROCESS_RETURN_VALUE
  936. // Only bother with the success codes - error codes are logged
  937. // below.
  938. if(LLIOPipe::isSuccess(status))
  939. {
  940. llinfos << "Pipe returned: '"
  941. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  942. << typeid(*((*it).mPipe)).name() << "':'"
  943. #endif
  944. << LLIOPipe::lookupStatusString(status) << "'" << llendl;
  945. }
  946. #endif
  947. PUMP_DEBUG;
  948. switch(status)
  949. {
  950. case LLIOPipe::STATUS_OK:
  951. // no-op
  952. break;
  953. case LLIOPipe::STATUS_STOP:
  954. PUMP_DEBUG;
  955. status = LLIOPipe::STATUS_OK;
  956. chain.mHead = end;
  957. keep_going = false;
  958. break;
  959. case LLIOPipe::STATUS_DONE:
  960. PUMP_DEBUG;
  961. status = LLIOPipe::STATUS_OK;
  962. chain.mHead = (it + 1);
  963. chain.mEOS = true;
  964. break;
  965. case LLIOPipe::STATUS_BREAK:
  966. PUMP_DEBUG;
  967. status = LLIOPipe::STATUS_OK;
  968. keep_going = false;
  969. break;
  970. case LLIOPipe::STATUS_NEED_PROCESS:
  971. PUMP_DEBUG;
  972. status = LLIOPipe::STATUS_OK;
  973. if(!need_process_signaled)
  974. {
  975. need_process_signaled = true;
  976. chain.mHead = it;
  977. }
  978. break;
  979. default:
  980. PUMP_DEBUG;
  981. if(LLIOPipe::isError(status))
  982. {
  983. llinfos << "Pump generated pipe err: '"
  984. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  985. << typeid(*((*it).mPipe)).name() << "':'"
  986. #endif
  987. << LLIOPipe::lookupStatusString(status)
  988. << "'" << llendl;
  989. #if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR
  990. if(chain.mData)
  991. {
  992. char* buf = NULL;
  993. S32 bytes = chain.mData->countAfter(
  994. (*it).mChannels.in(),
  995. NULL);
  996. if(bytes)
  997. {
  998. buf = new char[bytes + 1];
  999. chain.mData->readAfter(
  1000. (*it).mChannels.in(),
  1001. NULL,
  1002. (U8*)buf,
  1003. bytes);
  1004. buf[bytes] = '\0';
  1005. llinfos << "Input After Error: " << buf << llendl;
  1006. delete[] buf;
  1007. buf = NULL;
  1008. }
  1009. else
  1010. {
  1011. llinfos << "Input After Error: (null)" << llendl;
  1012. }
  1013. }
  1014. else
  1015. {
  1016. llinfos << "Input After Error: (null)" << llendl;
  1017. }
  1018. #endif
  1019. keep_going = false;
  1020. chain.mHead = it;
  1021. if(!handleChainError(chain, status))
  1022. {
  1023. chain.mHead = end;
  1024. }
  1025. }
  1026. else
  1027. {
  1028. llinfos << "Unhandled status code: " << status << ":"
  1029. << LLIOPipe::lookupStatusString(status) << llendl;
  1030. }
  1031. break;
  1032. }
  1033. PUMP_DEBUG;
  1034. } while(keep_going && (++it != end));
  1035. PUMP_DEBUG;
  1036. }
  1037. bool LLPumpIO::isChainExpired(LLChainInfo& chain)
  1038. {
  1039. if(!chain.mHasCurlRequest)
  1040. {
  1041. return false ;
  1042. }
  1043. for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter)
  1044. {
  1045. if(!(*iter).mPipe->isValid())
  1046. {
  1047. return true ;
  1048. }
  1049. }
  1050. return false ;
  1051. }
  1052. bool LLPumpIO::handleChainError(
  1053. LLChainInfo& chain,
  1054. LLIOPipe::EStatus error)
  1055. {
  1056. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  1057. links_t::reverse_iterator rit;
  1058. if(chain.mHead == chain.mChainLinks.end())
  1059. {
  1060. rit = links_t::reverse_iterator(chain.mHead);
  1061. }
  1062. else
  1063. {
  1064. rit = links_t::reverse_iterator(chain.mHead + 1);
  1065. }
  1066. links_t::reverse_iterator rend = chain.mChainLinks.rend();
  1067. bool handled = false;
  1068. bool keep_going = true;
  1069. do
  1070. {
  1071. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  1072. lldebugs << "Passing error to " << typeid(*((*rit).mPipe)).name()
  1073. << "." << llendl;
  1074. #endif
  1075. error = (*rit).mPipe->handleError(error, this);
  1076. switch(error)
  1077. {
  1078. case LLIOPipe::STATUS_OK:
  1079. handled = true;
  1080. chain.mHead = rit.base();
  1081. break;
  1082. case LLIOPipe::STATUS_STOP:
  1083. case LLIOPipe::STATUS_DONE:
  1084. case LLIOPipe::STATUS_BREAK:
  1085. case LLIOPipe::STATUS_NEED_PROCESS:
  1086. #if LL_DEBUG_PIPE_TYPE_IN_PUMP
  1087. lldebugs << "Pipe " << typeid(*((*rit).mPipe)).name()
  1088. << " returned code to stop error handler." << llendl;
  1089. #endif
  1090. keep_going = false;
  1091. break;
  1092. case LLIOPipe::STATUS_EXPIRED:
  1093. keep_going = false;
  1094. break ;
  1095. default:
  1096. if(LLIOPipe::isSuccess(error))
  1097. {
  1098. llinfos << "Unhandled status code: " << error << ":"
  1099. << LLIOPipe::lookupStatusString(error) << llendl;
  1100. error = LLIOPipe::STATUS_ERROR;
  1101. keep_going = false;
  1102. }
  1103. break;
  1104. }
  1105. } while(keep_going && !handled && (++rit != rend));
  1106. return handled;
  1107. }
  1108. /**
  1109. * LLPumpIO::LLChainInfo
  1110. */
  1111. LLPumpIO::LLChainInfo::LLChainInfo() :
  1112. mInit(false),
  1113. mLock(0),
  1114. mEOS(false),
  1115. mHasCurlRequest(false)
  1116. {
  1117. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  1118. mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
  1119. }
  1120. void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout)
  1121. {
  1122. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  1123. if(timeout > 0.0f)
  1124. {
  1125. mTimer.start();
  1126. mTimer.reset();
  1127. mTimer.setTimerExpirySec(timeout);
  1128. }
  1129. else
  1130. {
  1131. mTimer.stop();
  1132. }
  1133. }
  1134. void LLPumpIO::LLChainInfo::adjustTimeoutSeconds(F32 delta)
  1135. {
  1136. LLMemType m1(LLMemType::MTYPE_IO_PUMP);
  1137. if(mTimer.getStarted())
  1138. {
  1139. F64 expiry = mTimer.expiresAt();
  1140. expiry += delta;
  1141. mTimer.setExpiryAt(expiry);
  1142. }
  1143. }