lliopipe.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /**
  2. * @file lliopipe.h
  3. * @author Phoenix
  4. * @date 2004-11-18
  5. * @brief Declaration of base IO class
  6. *
  7. * $LicenseInfo:firstyear=2004&license=viewergpl$
  8. *
  9. * Copyright (c) 2004-2009, Linden Research, Inc.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #ifndef LL_LLIOPIPE_H
  35. #define LL_LLIOPIPE_H
  36. #include "llwin32headerslean.h"
  37. #include <memory>
  38. #include "boost/intrusive_ptr.hpp"
  39. #include "apr_poll.h"
  40. #include "llpreprocessor.h"
  41. #include "llsd.h"
  42. class LLIOPipe;
  43. class LLPumpIO;
  44. class LLBufferArray;
  45. class LLChannelDescriptors;
  46. // Debugging schmutz for deadlocks
  47. //#define LL_DEBUG_PUMPS
  48. #ifdef LL_DEBUG_PUMPS
  49. void pump_debug(const char *file, S32 line);
  50. #define PUMP_DEBUG pump_debug(__FILE__, __LINE__);
  51. #define END_PUMP_DEBUG pump_debug("none", 0);
  52. #else /* LL_DEBUG_PUMPS */
  53. #define PUMP_DEBUG
  54. #define END_PUMP_DEBUG
  55. #endif
  56. /**
  57. * intrusive pointer support
  58. */
  59. void intrusive_ptr_add_ref(LLIOPipe* p);
  60. void intrusive_ptr_release(LLIOPipe* p);
  61. /**
  62. * @class LLIOPipe
  63. * @brief This class is an abstract base class for data processing units
  64. * @see LLPumpIO
  65. *
  66. * The LLIOPipe is a base class for implementing the basic non-blocking
  67. * processing of data subsystem in our system.
  68. *
  69. * Implementations of this class should behave like a stateful or
  70. * stateless signal processor. Each call to <code>process()</code>
  71. * hands the pipe implementation a buffer and a set of channels in the
  72. * buffer to process, and the pipe returns the status of the
  73. * operation. This is an abstract base class and developer created
  74. * concrete implementations provide block or stream based processing
  75. * of data to implement a particular protocol.
  76. */
  77. class LLIOPipe
  78. {
  79. public:
  80. /**
  81. * @brief I have decided that IO objects should have a reference
  82. * count. In general, you can pass bald LLIOPipe pointers around
  83. * as you need, but if you need to maintain a reference to one,
  84. * you need to hold a ptr_t.
  85. */
  86. typedef boost::intrusive_ptr<LLIOPipe> ptr_t;
  87. /**
  88. * @brief Scattered memory container.
  89. */
  90. typedef std::shared_ptr<LLBufferArray> buffer_ptr_t;
  91. /**
  92. * @brief Enumeration for IO return codes
  93. *
  94. * A status code a positive integer value is considered a success,
  95. * but may indicate special handling for future calls, for
  96. * example, issuing a STATUS_STOP to an LLIOSocketReader instance
  97. * will tell the instance to stop reading the socket. A status
  98. * code with a negative value means that a problem has been
  99. * encountered which will require further action on the caller or
  100. * a developer to correct. Some mechanisms, such as the LLPumpIO
  101. * may depend on this definition of success and failure.
  102. */
  103. enum EStatus
  104. {
  105. // Processing occurred normally, future calls will be accepted.
  106. STATUS_OK = 0,
  107. // Processing occured normally, but stop unsolicited calls to
  108. // process.
  109. STATUS_STOP = 1,
  110. // This pipe is done with the processing. Future calls to
  111. // process will be accepted as long as new data is available.
  112. STATUS_DONE = 2,
  113. // This pipe is requesting that it become the head in a process.
  114. STATUS_BREAK = 3,
  115. // This pipe is requesting that it become the head in a process.
  116. STATUS_NEED_PROCESS = 4,
  117. // Keep track of the highest number of success codes here.
  118. STATUS_SUCCESS_COUNT = 5,
  119. // A generic error code.
  120. STATUS_ERROR = -1,
  121. // This method has not yet been implemented. This usually
  122. // indicates the programmer working on the pipe is not yet
  123. // done.
  124. STATUS_NOT_IMPLEMENTED = -2,
  125. // This indicates that a pipe precondition was not met. For
  126. // example, many pipes require an element to appear after them
  127. // in a chain (ie, mNext is not null) and will return this in
  128. // response to method calls. To recover from this, it will
  129. // require the caller to adjust the pipe state or may require
  130. // a dev to adjust the code to satisfy the preconditions.
  131. STATUS_PRECONDITION_NOT_MET = -3,
  132. // This means we could not connect to a remote host.
  133. STATUS_NO_CONNECTION = -4,
  134. // The connection was lost.
  135. STATUS_LOST_CONNECTION = -5,
  136. // The totoal process time has exceeded the timeout.
  137. STATUS_EXPIRED = -6,
  138. // Keep track of the count of codes here.
  139. STATUS_ERROR_COUNT = 6,
  140. };
  141. /**
  142. * @brief Helper function to check status.
  143. *
  144. * When writing code to check status codes, if you do not
  145. * specifically check a particular value, use this method for
  146. * checking an error condition.
  147. * @param status The status to check.
  148. * @return Returns true if the code indicates an error occurred.
  149. */
  150. LL_INLINE static bool isError(EStatus status)
  151. {
  152. return (S32)status < 0;
  153. }
  154. /**
  155. * @brief Helper function to check status.
  156. *
  157. * When writing code to check status codes, if you do not
  158. * specifically check a particular value, use this method for
  159. * checking an error condition.
  160. * @param status The status to check.
  161. * @return Returns true if the code indicates no error was generated.
  162. */
  163. LL_INLINE static bool isSuccess(EStatus status)
  164. {
  165. return (S32)status >= 0;
  166. }
  167. /**
  168. * @brief Helper function to turn status into a string.
  169. *
  170. * @param status The status to check.
  171. * @return Returns the name of the status code or empty string on failure.
  172. */
  173. static std::string lookupStatusString(EStatus status);
  174. /**
  175. * @brief Process the data in buffer.
  176. *
  177. * @param data The data processed
  178. * @param eos True if this function call is the last because end of stream.
  179. * @param pump The pump which is calling process. May be NULL.
  180. * @param context Shared meta-data for the process.
  181. * @return Returns a status code from the operation.
  182. */
  183. EStatus process(const LLChannelDescriptors& channels,
  184. buffer_ptr_t& buffer, bool& eos,
  185. LLSD& context, LLPumpIO* pump);
  186. /**
  187. * @brief Give this pipe a chance to handle a generated error
  188. *
  189. * If this pipe is in a chain being processed by a pump, and one
  190. * of the pipes generates an error, the pump will rewind through
  191. * the chain to see if any of the links can handle the error. For
  192. * example, if a connection is refused in a socket connection, the
  193. * socket client can try to find a new destination host. Return an
  194. * error code if this pipe does not handle the error passed in.
  195. * @param status The status code for the error
  196. * @param pump The pump which was calling process before the error
  197. * was generated.
  198. * @return Returns a status code from the operation. Returns an
  199. * error code if the error passed in was not handled. Returns
  200. * STATUS_OK to indicate the error has been handled.
  201. */
  202. virtual EStatus handleError(EStatus status, LLPumpIO* pump);
  203. /**
  204. * @brief Base Destructor - do not call <code>delete</code> directly.
  205. */
  206. virtual ~LLIOPipe();
  207. virtual bool isValid();
  208. protected:
  209. /**
  210. * @brief Base Constructor.
  211. */
  212. LLIOPipe();
  213. /**
  214. * @brief Process the data in buffer
  215. */
  216. virtual EStatus process_impl(const LLChannelDescriptors& channels,
  217. buffer_ptr_t& buffer, bool& eos,
  218. LLSD& context, LLPumpIO* pump) = 0;
  219. private:
  220. friend void intrusive_ptr_add_ref(LLIOPipe* p);
  221. friend void intrusive_ptr_release(LLIOPipe* p);
  222. U32 mReferenceCount;
  223. };
  224. LL_INLINE void intrusive_ptr_add_ref(LLIOPipe* p)
  225. {
  226. ++p->mReferenceCount;
  227. }
  228. LL_INLINE void intrusive_ptr_release(LLIOPipe* p)
  229. {
  230. if (p && 0 == --p->mReferenceCount)
  231. {
  232. delete p;
  233. }
  234. }
  235. #if 0
  236. /**
  237. * @class LLIOBoiler
  238. * @brief This class helps construct new LLIOPipe specializations
  239. * @see LLIOPipe
  240. *
  241. * THOROUGH_DESCRIPTION
  242. */
  243. class LLIOBoiler : public LLIOPipe
  244. {
  245. public:
  246. LLIOBoiler();
  247. virtual ~LLIOBoiler();
  248. protected:
  249. /* @name LLIOPipe virtual implementations
  250. */
  251. //@{
  252. /**
  253. * @brief Process the data in buffer
  254. */
  255. virtual EStatus process_impl(const LLChannelDescriptors& channels,
  256. buffer_ptr_t& buffer, bool& eos,
  257. LLSD& context, LLPumpIO* pump);
  258. //@}
  259. };
  260. // virtual
  261. LLIOPipe::EStatus process_impl(const LLChannelDescriptors& channels,
  262. buffer_ptr_t& buffer, bool& eos,
  263. LLSD& context, LLPumpIO* pump)
  264. {
  265. return STATUS_NOT_IMPLEMENTED;
  266. }
  267. #endif // #if 0 - use this block as a boilerplate
  268. #endif // LL_LLIOPIPE_H