PageRenderTime 40ms CodeModel.GetById 27ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llmessage/lliopipe.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 317 lines | 114 code | 39 blank | 164 comment | 3 complexity | 6334325d40f151079ae1eb65d8ec4bdf MD5 | raw file
  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=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
 29#ifndef LL_LLIOPIPE_H
 30#define LL_LLIOPIPE_H
 31
 32#include <boost/intrusive_ptr.hpp>
 33#include <boost/shared_ptr.hpp>
 34#include "apr_poll.h"
 35
 36#include "llsd.h"
 37
 38class LLIOPipe;
 39class LLPumpIO;
 40class LLBufferArray;
 41class LLChannelDescriptors;
 42
 43// Debugging schmutz for deadlocks
 44//#define LL_DEBUG_PUMPS
 45#ifdef LL_DEBUG_PUMPS
 46void pump_debug(const char *file, S32 line);
 47#define PUMP_DEBUG pump_debug(__FILE__, __LINE__);
 48#define END_PUMP_DEBUG pump_debug("none", 0);
 49#else /* LL_DEBUG_PUMPS */
 50#define PUMP_DEBUG
 51#define END_PUMP_DEBUG
 52#endif
 53
 54
 55/**
 56 * intrusive pointer support
 57 */
 58namespace boost
 59{
 60	void intrusive_ptr_add_ref(LLIOPipe* p);
 61	void intrusive_ptr_release(LLIOPipe* p);
 62};
 63
 64/** 
 65 * @class LLIOPipe
 66 * @brief This class is an abstract base class for data processing units
 67 * @see LLPumpIO
 68 *
 69 * The LLIOPipe is a base class for implementing the basic non-blocking
 70 * processing of data subsystem in our system.
 71 *
 72 * Implementations of this class should behave like a stateful or
 73 * stateless signal processor. Each call to <code>process()</code>
 74 * hands the pipe implementation a buffer and a set of channels in the
 75 * buffer to process, and the pipe returns the status of the
 76 * operation. This is an abstract base class and developer created
 77 * concrete implementations provide block or stream based processing
 78 * of data to implement a particular protocol.
 79 */
 80class LLIOPipe
 81{
 82public:
 83	/** 
 84	 * @brief I have decided that IO objects should have a reference
 85	 * count. In general, you can pass bald LLIOPipe pointers around
 86	 * as you need, but if you need to maintain a reference to one,
 87	 * you need to hold a ptr_t.
 88	 */
 89	typedef boost::intrusive_ptr<LLIOPipe> ptr_t;
 90
 91	/** 
 92	 * @brief Scattered memory container.
 93	 */
 94	typedef boost::shared_ptr<LLBufferArray> buffer_ptr_t;
 95
 96	/** 
 97	 * @brief Enumeration for IO return codes
 98	 *
 99	 * A status code a positive integer value is considered a success,
100	 * but may indicate special handling for future calls, for
101	 * example, issuing a STATUS_STOP to an LLIOSocketReader instance
102	 * will tell the instance to stop reading the socket. A status
103	 * code with a negative value means that a problem has been
104	 * encountered which will require further action on the caller or
105	 * a developer to correct. Some mechanisms, such as the LLPumpIO
106	 * may depend on this definition of success and failure.
107	 */
108	enum EStatus
109	{
110		// Processing occurred normally, future calls will be accepted.
111		STATUS_OK = 0,
112
113		// Processing occured normally, but stop unsolicited calls to
114		// process.
115		STATUS_STOP = 1,
116
117		// This pipe is done with the processing. Future calls to
118		// process will be accepted as long as new data is available.
119		STATUS_DONE = 2,
120
121		// This pipe is requesting that it become the head in a process.
122		STATUS_BREAK = 3,
123
124		// This pipe is requesting that it become the head in a process.
125		STATUS_NEED_PROCESS = 4,
126
127		// Keep track of the highest number of success codes here.
128		STATUS_SUCCESS_COUNT = 5,
129
130		// A generic error code.
131		STATUS_ERROR = -1,
132
133		// This method has not yet been implemented. This usually
134		// indicates the programmer working on the pipe is not yet
135		// done.
136		STATUS_NOT_IMPLEMENTED = -2,
137
138		// This indicates that a pipe precondition was not met. For
139		// example, many pipes require an element to appear after them
140		// in a chain (ie, mNext is not null) and will return this in
141		// response to method calls. To recover from this, it will
142		// require the caller to adjust the pipe state or may require
143		// a dev to adjust the code to satisfy the preconditions.
144		STATUS_PRECONDITION_NOT_MET = -3,
145
146		// This means we could not connect to a remote host.
147		STATUS_NO_CONNECTION = -4,
148
149		// The connection was lost.
150		STATUS_LOST_CONNECTION = -5,
151
152		// The totoal process time has exceeded the timeout.
153		STATUS_EXPIRED = -6,
154
155		// Keep track of the count of codes here.
156		STATUS_ERROR_COUNT = 6,
157	};
158
159	/** 
160	 * @brief Helper function to check status.
161	 *
162	 * When writing code to check status codes, if you do not
163	 * specifically check a particular value, use this method for
164	 * checking an error condition.
165	 * @param status The status to check.
166	 * @return Returns true if the code indicates an error occurred.
167	 */
168	inline static bool isError(EStatus status)
169	{
170		return ((S32)status < 0);
171	}
172
173	/** 
174	 * @brief Helper function to check status.
175	 *
176	 * When writing code to check status codes, if you do not
177	 * specifically check a particular value, use this method for
178	 * checking an error condition.
179	 * @param status The status to check.
180	 * @return Returns true if the code indicates no error was generated.
181	 */
182	inline static bool isSuccess(EStatus status)
183	{
184		return ((S32)status >= 0);
185	}
186
187	/** 
188	 * @brief Helper function to turn status into a string.
189	 *
190	 * @param status The status to check.
191	 * @return Returns the name of the status code or empty string on failure.
192	 */
193	static std::string lookupStatusString(EStatus status);
194
195	/** 
196	 * @brief Process the data in buffer.
197	 *
198	 * @param data The data processed
199	 * @param eos True if this function call is the last because end of stream.
200	 * @param pump The pump which is calling process. May be NULL.
201	 * @param context Shared meta-data for the process.
202	 * @return Returns a status code from the operation.
203	 */
204	EStatus process(
205		const LLChannelDescriptors& channels,
206		buffer_ptr_t& buffer,
207		bool& eos,
208		LLSD& context,
209		LLPumpIO* pump);
210
211	/** 
212	 * @brief Give this pipe a chance to handle a generated error
213	 *
214	 * If this pipe is in a chain being processed by a pump, and one
215	 * of the pipes generates an error, the pump will rewind through
216	 * the chain to see if any of the links can handle the error. For
217	 * example, if a connection is refused in a socket connection, the
218	 * socket client can try to find a new destination host. Return an
219	 * error code if this pipe does not handle the error passed in.
220	 * @param status The status code for the error
221	 * @param pump The pump which was calling process before the error
222	 * was generated.
223	 * @return Returns a status code from the operation. Returns an
224	 * error code if the error passed in was not handled. Returns
225	 * STATUS_OK to indicate the error has been handled.
226	 */
227	virtual EStatus handleError(EStatus status, LLPumpIO* pump);
228
229	/**
230	 * @brief Base Destructor - do not call <code>delete</code> directly.
231	 */
232	virtual ~LLIOPipe();
233
234	virtual bool isValid() ;
235
236protected:
237	/**
238	 * @brief Base Constructor.
239	 */
240	LLIOPipe();
241
242	/** 
243	 * @brief Process the data in buffer
244	 */
245	virtual EStatus process_impl(
246		const LLChannelDescriptors& channels,
247		buffer_ptr_t& buffer,
248		bool& eos,
249		LLSD& context,
250		LLPumpIO* pump) = 0;
251
252private:
253	friend void boost::intrusive_ptr_add_ref(LLIOPipe* p);
254	friend void boost::intrusive_ptr_release(LLIOPipe* p);
255	U32 mReferenceCount;
256};
257
258namespace boost
259{
260	inline void intrusive_ptr_add_ref(LLIOPipe* p)
261	{
262		++p->mReferenceCount;
263	}
264	inline void intrusive_ptr_release(LLIOPipe* p)
265	{
266		if(p && 0 == --p->mReferenceCount)
267		{
268			delete p;
269		}
270	}
271};
272
273
274#if 0
275/** 
276 * @class LLIOBoiler
277 * @brief This class helps construct new LLIOPipe specializations
278 * @see LLIOPipe
279 *
280 * THOROUGH_DESCRIPTION
281 */
282class LLIOBoiler : public LLIOPipe
283{
284public:
285	LLIOBoiler();
286	virtual ~LLIOBoiler();
287
288protected:
289	/* @name LLIOPipe virtual implementations
290	 */
291	//@{
292	/** 
293	 * @brief Process the data in buffer
294	 */
295	virtual EStatus process_impl(
296		const LLChannelDescriptors& channels,
297		buffer_ptr_t& buffer,
298		bool& eos,
299		LLSD& context,
300		LLPumpIO* pump);
301	//@}
302};
303
304// virtual
305LLIOPipe::EStatus process_impl(
306	const LLChannelDescriptors& channels,
307	buffer_ptr_t& buffer,
308	bool& eos,
309	LLSD& context,
310	LLPumpIO* pump)
311{
312	return STATUS_NOT_IMPLEMENTED;
313}
314
315#endif // #if 0 - use this block as a boilerplate
316
317#endif // LL_LLIOPIPE_H