llcorehttpservice.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /**
  2. * @file llcorehttpservice.h
  3. * @brief Declarations for internal class providing HTTP service.
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2012, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef _LLCORE_HTTP_SERVICE_H_
  27. #define _LLCORE_HTTP_SERVICE_H_
  28. #include "llatomic.h"
  29. #include "llcorehttpcommon.h"
  30. #include "llcorehttppolicy.h"
  31. #include "llcorehttppolicyclass.h"
  32. #include "llcorehttppolicyglobal.h"
  33. #include "llcorehttprequest.h"
  34. #include "llerror.h"
  35. namespace LLCore
  36. {
  37. class HttpRequestQueue;
  38. class HttpPolicy;
  39. class HttpLibcurl;
  40. class HttpOpSetGet;
  41. class HttpThread;
  42. // The HttpService class does the work behind the request queue. It oversees
  43. // the HTTP workflow carrying out a number of tasks:
  44. // - Pulling requests from the global request queue
  45. // - Executing 'immediate' requests directly
  46. // - Prioritizing and re-queuing on internal queues the slower requests
  47. // - Providing cpu cycles to the libcurl plumbing
  48. // - Overseeing retry operations
  49. //
  50. // Note that the service object doesn't have a pointer to any reply queue.
  51. // These are kept by HttpRequest and HttpOperation only.
  52. //
  53. // Service, Policy and Transport
  54. //
  55. // HttpService could have been a monolithic class combining a request queue
  56. // servicer, request policy manager and network transport.
  57. // Instead, to prevent monolithic growth and allow for easier replacement, it
  58. // was developed as three separate classes: HttpService, HttpPolicy and
  59. // HttpLibcurl (transport). These always exist in a 1:1:1 relationship with
  60. // HttpService managing instances of the other two. So, these classes do not
  61. // use reference counting to refer to one another, their lifecycles are always
  62. // managed together.
  63. class HttpService
  64. {
  65. friend class HttpOpSetGet;
  66. friend class HttpRequest;
  67. protected:
  68. LOG_CLASS(HttpService);
  69. HttpService();
  70. virtual ~HttpService();
  71. public:
  72. HttpService(const HttpService&) = delete;
  73. void operator=(const HttpService&) = delete;
  74. enum EState
  75. {
  76. NOT_INITIALIZED = -1,
  77. INITIALIZED, // init() has been called
  78. RUNNING, // thread created and running
  79. STOPPED // thread has committed to exiting
  80. };
  81. // Ordered enumeration of idling strategies available to threadRun's loop.
  82. // Ordered so that std::min on values produces the most conservative result
  83. // of multiple requests.
  84. enum ELoopSpeed
  85. {
  86. NORMAL, // continuous polling of request, ready, active queues
  87. REQUEST_SLEEP // can sleep indefinitely waiting for request queue write
  88. };
  89. static void init(HttpRequestQueue*);
  90. static void term();
  91. // Threading: callable by any thread once inited.
  92. LL_INLINE static HttpService* instanceOf() { return sInstance; }
  93. // Return the state of the worker thread. Note that the transition from
  94. // RUNNING to STOPPED is performed by the worker thread itself. This has
  95. // two weaknesses:
  96. // - race where the thread hasn't really stopped but will
  97. // - data ordering between threads where a non-worker thread may see a
  98. // stale RUNNING status.
  99. //
  100. // This transition is generally of interest only to unit tests and these
  101. // weaknesses shouldn't be any real burden.
  102. //
  103. // Threading: callable by any thread with above exceptions.
  104. LL_INLINE static EState getState() { return sState; }
  105. // Threading: callable by any thread but uses @see getState() and
  106. // acquires its weaknesses.
  107. LL_INLINE static bool isStopped()
  108. {
  109. // What is really wanted here is something like:
  110. //
  111. // HttpService* service = instanceOf();
  112. // return STOPPED == sState &&
  113. // (!service || !service->mThread ||
  114. // !service->mThread->joinable());
  115. //
  116. // But boost::thread is not giving me a consistent story on joinability
  117. // of a thread after it returns. Debug and non-debug builds are showing
  118. // different behavior on Linux/Etch so we do a weaker test that may not
  119. // be globally correct (i.e. thread *is* stopping, may not have stopped
  120. // but will very soon):
  121. return sState == STOPPED;
  122. }
  123. // Threading: callable by init thread thread *once*.
  124. void startThread();
  125. // Threading: callable by worker thread.
  126. LL_INLINE void stopRequested() { mExitRequested = 1U; }
  127. // Threading: callable by worker thread.
  128. void shutdown();
  129. // Try to find the given request handle on any of the request
  130. // queues and cancel the operation.
  131. //
  132. // @return True if the request was found and cancelled.
  133. //
  134. // Threading: callable by worker thread.
  135. bool cancel(HttpHandle handle);
  136. // Threading: callable by worker thread.
  137. LL_INLINE HttpPolicy& getPolicy() { return *mPolicy; }
  138. // Threading: callable by worker thread.
  139. LL_INLINE HttpLibcurl& getTransport() { return *mTransport; }
  140. // Threading: callable by worker thread.
  141. LL_INLINE HttpRequestQueue& getRequestQueue() { return *mRequestQueue; }
  142. // Threading: callable by consumer thread.
  143. HttpRequest::policy_t createPolicyClass();
  144. protected:
  145. void threadRun(HttpThread* thread);
  146. int processRequestQueue(ELoopSpeed loop);
  147. // Used internally to describe what operations are allowed on each policy
  148. // option.
  149. struct OptionDescriptor
  150. {
  151. bool mIsLong;
  152. bool mIsDynamic;
  153. bool mIsGlobal;
  154. bool mIsClass;
  155. bool mIsCallback;
  156. };
  157. HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt,
  158. HttpRequest::policy_t,
  159. long* ret_value);
  160. HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt,
  161. HttpRequest::policy_t,
  162. std::string* ret_value);
  163. HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt,
  164. HttpRequest::policy_t,
  165. HttpRequest::policyCallback_t* ret_value);
  166. HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt,
  167. HttpRequest::policy_t,
  168. long value, long* ret_value);
  169. HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt,
  170. HttpRequest::policy_t,
  171. const std::string& value,
  172. std::string* ret_value);
  173. HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt,
  174. HttpRequest::policy_t,
  175. HttpRequest::policyCallback_t value,
  176. HttpRequest::policyCallback_t* ret_value);
  177. protected:
  178. static const OptionDescriptor sOptionDesc[HttpRequest::PO_LAST];
  179. static HttpService* sInstance;
  180. // === shared data ===
  181. static volatile EState sState;
  182. HttpRequestQueue* mRequestQueue; // Refcounted
  183. LLAtomicU32 mExitRequested;
  184. HttpThread* mThread;
  185. // === consumer-thread-only data ===
  186. // === working-thread-only data ===
  187. HttpPolicy* mPolicy; // Simple pointer, has ownership
  188. HttpLibcurl* mTransport; // Simple pointer, has ownership
  189. // === main-thread-only data ===
  190. HttpRequest::policy_t mLastPolicy;
  191. };
  192. } // End namespace LLCore
  193. #endif // _LLCORE_HTTP_SERVICE_H_