#ifndef __OUC_ERRINFO_H__
#define __OUC_ERRINFO_H__
/******************************************************************************/
/* */
/* X r d O u c E r r I n f o . h h */
/* */
/* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/* */
/******************************************************************************/
#include // For strlcpy()
#include
#include "XrdOuc/XrdOucBuffer.hh"
#include "XrdSys/XrdSysPlatform.hh"
/******************************************************************************/
/* X r d O u c E I */
/******************************************************************************/
//-----------------------------------------------------------------------------
//! The XrdOucEI struct encapsulates error information. It uses a fixed buffer
//! for message text and tracing information. It also allows extended
//! information to be recorded in an appendage. It cannot be directly used.
//-----------------------------------------------------------------------------
struct XrdOucEI // Err information structure
{
static const size_t Max_Error_Len = 2048;
static const int Path_Offset = 1024;
const char *user;
int ucap;
int code;
char message[Max_Error_Len];
static const int uVMask = 0x0000ffff; //! ucap: Extract protocol version
static const int uAsync = 0x80000000; //! ucap: Supports async responses
static const int uUrlOK = 0x40000000; //! ucap: Supports url redirects
static const int uMProt = 0x20000000; //! ucap: Supports multiple protocols
static const int uReadR = 0x10000000; //! ucap: Supports read redirects
static const int uIPv4 = 0x08000000; //! ucap: Supports only IPv4 info
static const int uIPv64 = 0x04000000; //! ucap: Supports IPv6|IPv4 info and
//! uIPv4 says IPv4 is prefered
static const int uPrip = 0x02000000; //! ucap: Client is on a private net
static const int uLclF = 0x01000000; //! ucap: Client supports "file://"
static const int uRedirFlgs = 0x00800000; //! ucap: Client supports redirect flags
static const int uEcRedir = 0x00400000; //! ucap: Client support EC redirects
inline void clear(const char *usr=0, int uc=0)
{code=0; ucap = uc; message[0]='\0';
user = (usr ? usr : "?");
}
XrdOucEI &operator =(const XrdOucEI &rhs)
{code = rhs.code;
user = rhs.user;
ucap = rhs.ucap;
strcpy(message, rhs.message);
return *this;
}
XrdOucEI(const char *usr, int uc=0) {clear(usr, uc);}
};
/******************************************************************************/
/* X r d O u c E r r I n f o */
/******************************************************************************/
class XrdOucEICB;
class XrdOucEnv;
class XrdSysSemaphore;
//-----------------------------------------------------------------------------
//! The XrdOucErrInfo class is used to communicate data, error, and callback
//! information between plug-ins.
//-----------------------------------------------------------------------------
class XrdOucErrInfo
{
public:
//-----------------------------------------------------------------------------
//! Reset data and error information to null. Any appenadges are released.
//-----------------------------------------------------------------------------
void clear() {Reset(); ErrInfo.clear();}
//-----------------------------------------------------------------------------
//! Set callback argument.
//!
//! @param cbarg - An opaque 8-byte call-back argument.
//-----------------------------------------------------------------------------
inline void setErrArg(unsigned long long cbarg=0) {ErrCBarg = cbarg;}
//-----------------------------------------------------------------------------
//! Set callback information.
//!
//! @param cb - Pointer to the object describing the callback.
//! @param cbarg - An opaque 8-byte call-back argument.
//-----------------------------------------------------------------------------
inline void setErrCB(XrdOucEICB *cb, unsigned long long cbarg=0)
{ErrCB = cb; ErrCBarg = cbarg;}
//-----------------------------------------------------------------------------
//! Set error code. Any existing error text remains intact.
//!
//! @param code - The error number describing the error.
//!
//! @return code - The error number.
//-----------------------------------------------------------------------------
inline int setErrCode(int code) {return ErrInfo.code = code;}
//-----------------------------------------------------------------------------
//! Set error code and error text.
//!
//! @param code - The error number describing the error.
//! @param emsg - The error message text.
//!
//! @return code - The error number.
//-----------------------------------------------------------------------------
inline int setErrInfo(int code, const char *emsg)
{strlcpy(ErrInfo.message, emsg, sizeof(ErrInfo.message));
if (dataBuff) {dataBuff->Recycle(); dataBuff = 0;}
return ErrInfo.code = code;
}
//-----------------------------------------------------------------------------
//! Set error code and error text.
//!
//! @param code - The error number describing the error.
//! @param txtlist - A vector of error message text segments.
//! @param n - The number of valid elements in txtlist.
//!
//! @return code - The error number.
//-----------------------------------------------------------------------------
inline int setErrInfo(int code, const char *txtlist[], int n)
{int i, j = 0, k = sizeof(ErrInfo.message), l;
for (i = 0; i < n && k > 1; i++)
{l = strlcpy(&ErrInfo.message[j], txtlist[i], k);
j += l; k -= l;
}
if (dataBuff) {dataBuff->Recycle(); dataBuff = 0;}
return ErrInfo.code = code;
}
//-----------------------------------------------------------------------------
//! Set error code and error text.
//!
//! @param code - The error number describing the error.
//! @param buffP - Pointer to the data buffer holding the error text, This
//! object takes ownership of the buffer and recycles it.
//!
//! @return code - The error number.
//-----------------------------------------------------------------------------
inline int setErrInfo(int code, XrdOucBuffer *buffP)
{if (dataBuff) dataBuff->Recycle();
dataBuff = buffP;
return ErrInfo.code = code;
}
//-----------------------------------------------------------------------------
//! Set user pointer.
//!
//! @param user - Pointer to a stable storage area containing the username.
//-----------------------------------------------------------------------------
inline void setErrUser(const char *user) {ErrInfo.user = (user ? user : "?");}
//-----------------------------------------------------------------------------
//! Obtain the callback argument.
//!
//! @return The argument value currently in effect.
//-----------------------------------------------------------------------------
inline unsigned long long getErrArg() {return ErrCBarg;}
//-----------------------------------------------------------------------------
//! Get the pointer to the internal message buffer along with its size.
//!
//! @param mblen - Reference to where the size it to be returned.
//!
//! @return Pointer to the internal message buffer.
//-----------------------------------------------------------------------------
inline char *getMsgBuff(int &mblen)
{mblen = sizeof(ErrInfo.message);
return ErrInfo.message;
}
//-----------------------------------------------------------------------------
//! Get the callback object.
//!
//! @return Pointer to the callback object.
//-----------------------------------------------------------------------------
inline XrdOucEICB *getErrCB() {return ErrCB;}
//-----------------------------------------------------------------------------
//! Get the callback object and its argument.
//!
//! @param ap - Reference to where the callback argument is returned.
//!
//! @return Pointer to the callback object, ap holds the argument.
//-----------------------------------------------------------------------------
inline XrdOucEICB *getErrCB(unsigned long long &ap)
{ap = ErrCBarg; return ErrCB;}
//-----------------------------------------------------------------------------
//! Get the error code.
//!
//! @return The error code that was previously set.
//-----------------------------------------------------------------------------
inline int getErrInfo() {return ErrInfo.code;}
/*
//-----------------------------------------------------------------------------
//! Get a copy of the error information.
//!
//! @param errParm - Reference to where error information is to be copied.
//!
//! @return The error code that was previously set.
//-----------------------------------------------------------------------------
inline int getErrInfo(XrdOucEI &errParm)
{errParm = ErrInfo; return ErrInfo.code;}
*/
//-----------------------------------------------------------------------------
//! Get a pointer to the error text.
//!
//! @return The pointer to the internal error text.
//-----------------------------------------------------------------------------
inline const char *getErrText()
{if (dataBuff) return dataBuff->Data();
return (const char *)ErrInfo.message;
}
//-----------------------------------------------------------------------------
//! Get a pointer to the error text and the error code.
//!
//! @param ecode - Reference to where the error code is to be returned.
//! @return The pointer to the internal error text.
//-----------------------------------------------------------------------------
inline const char *getErrText(int &ecode)
{ecode = ErrInfo.code;
if (dataBuff) return dataBuff->Data();
return (const char *)ErrInfo.message;
}
//-----------------------------------------------------------------------------
//! Get the error text length (optimized for external buffers).
//!
//! @return The mesage length.
//-----------------------------------------------------------------------------
inline int getErrTextLen()
{if (dataBuff) return dataBuff->DataLen();
return strlen(ErrInfo.message);
}
//-----------------------------------------------------------------------------
//! Get a pointer to user information.
//!
//! @return The pointer to the user string.
//-----------------------------------------------------------------------------
inline const char *getErrUser() {return ErrInfo.user;}
//-----------------------------------------------------------------------------
//! Get a pointer to the error environment that was previously set.
//!
//! @return =0 - A callback is in effect which is mutually exclusive of
//! conaining an error environment (i.e. no environment).
//! @return !0 - Pointer to the error environment.
//-----------------------------------------------------------------------------
inline XrdOucEnv *getEnv() {return (ErrCB ? 0 : ErrEnv);}
//-----------------------------------------------------------------------------
//! Set the error environment and return the previous environment. This call
//! destroys any callback information that may have existed.
//!
//! @param newEnv - Pointer to the new error environment.
//!
//! @return =0 - No previous envuironment existed.
//! @return !0 - Pointer to the previous error environment.
//-----------------------------------------------------------------------------
inline XrdOucEnv *setEnv(XrdOucEnv *newEnv)
{XrdOucEnv *oldEnv = (ErrCB ? 0 : ErrEnv);
ErrEnv = newEnv;
ErrCB = 0;
return oldEnv;
}
//-----------------------------------------------------------------------------
//! Get the error tracing data.
//!
//! @return =0 - No tracing data has been set.
//! @return !0 - Pointer to error tracing data.
//-----------------------------------------------------------------------------
inline const char *getErrData() {return (dOff < 0 ? 0 : ErrInfo.message+dOff);}
//-----------------------------------------------------------------------------
//! Set the error tracing data (this is always placed in the internal buffer)
//!
//! @param Data - Pointer to the error tracing data.
//! @param Offs - Ofset into the message buffer where the data is to be set.
//-----------------------------------------------------------------------------
inline void setErrData(const char *Data, int Offs=0)
{if (!Data) dOff = -1;
else {strlcpy(ErrInfo.message+Offs, Data,
sizeof(ErrInfo.message)-Offs);
dOff = Offs;
}
}
//-----------------------------------------------------------------------------
//! Get the monitoring identifier.
//!
//! @return The monitoring identifier.
//-----------------------------------------------------------------------------
inline int getErrMid() {return mID;}
//-----------------------------------------------------------------------------
//! Set the monitoring identifier.
//-----------------------------------------------------------------------------
inline void setErrMid(int mid) {mID = mid;}
//-----------------------------------------------------------------------------
//! Check if this object will return extended data (can optimize Reset() calls).
//!
//! @return true - there is extended data.
//! false - there is no extended data.
//-----------------------------------------------------------------------------
inline bool extData() {return (dataBuff != 0);}
//-----------------------------------------------------------------------------
//! Reset object to no message state. Call this method to release appendages.
//-----------------------------------------------------------------------------
inline void Reset()
{if (dataBuff) {dataBuff->Recycle(); dataBuff = 0;}
*ErrInfo.message = 0;
ErrInfo.code = 0;
}
//-----------------------------------------------------------------------------
//! Get user capabilties.
//!
//! @return the user capabilities.
//-----------------------------------------------------------------------------
inline int getUCap() {return ErrInfo.ucap;}
//-----------------------------------------------------------------------------
//! Set user capabilties.
//-----------------------------------------------------------------------------
inline void setUCap(int ucval) {ErrInfo.ucap = ucval;}
//-----------------------------------------------------------------------------
//! Assignment operator
//-----------------------------------------------------------------------------
XrdOucErrInfo &operator =(const XrdOucErrInfo &rhs)
{ErrInfo = rhs.ErrInfo;
ErrCB = rhs.ErrCB;
ErrCBarg= rhs.ErrCBarg;
mID = rhs.mID;
dOff = -1;
if (rhs.dataBuff) dataBuff = rhs.dataBuff->Clone();
else dataBuff = 0;
return *this;
}
//-----------------------------------------------------------------------------
//! Constructor
//!
//! @param user - Pointer to he user string in stable storage.
//! @param cb - Pointer to the callback object (zero if none).
//! @param ca - The callback argument.
//! @param mid - The monitoring identifier.
//! @param uc - The user capabilities.
//-----------------------------------------------------------------------------
XrdOucErrInfo(const char *user=0,XrdOucEICB *cb=0,
unsigned long long ca=0, int mid=0, int uc=0)
: ErrInfo(user, uc), ErrCB(cb), ErrCBarg(ca), mID(mid),
dOff(-1), reserved(0), dataBuff(0) {}
//-----------------------------------------------------------------------------
//! Constructor
//!
//! @param user - Pointer to he user string in stable storage.
//! @param envp - Pointer to the error environment.
//! @param uc - The user capabilities.
//-----------------------------------------------------------------------------
XrdOucErrInfo(const char *user, XrdOucEnv *envp, int uc=0)
: ErrInfo(user, uc), ErrCB(0), ErrEnv(envp), mID(0),
dOff(-1), reserved(0), dataBuff(0) {}
//-----------------------------------------------------------------------------
//! Constructor
//!
//! @param user - Pointer to he user string in stable storage.
//! @param MonID - The monitoring identifier.
//! @param uc - The user capabilities.
//-----------------------------------------------------------------------------
XrdOucErrInfo(const char *user, int MonID, int uc=0)
: ErrInfo(user, uc), ErrCB(0), ErrCBarg(0), mID(MonID),
dOff(-1), reserved(0), dataBuff(0) {}
//-----------------------------------------------------------------------------
//! Destructor
//-----------------------------------------------------------------------------
virtual ~XrdOucErrInfo() {Reset();}
protected:
XrdOucEI ErrInfo;
XrdOucEICB *ErrCB;
union {
unsigned long long ErrCBarg;
XrdOucEnv *ErrEnv;
};
int mID;
short dOff;
short reserved;
XrdOucBuffer *dataBuff;
};
/******************************************************************************/
/* X r d O u c E I C B */
/******************************************************************************/
//-----------------------------------------------------------------------------
//! The XrdOucEICB is the object that instantiates a callback. This abstract
//! class is used to define the callback interface. It is normally handled by
//! classes that know how to deal with this object in a user friendly way
//! (e.g. XrdOucCallBack).
//-----------------------------------------------------------------------------
class XrdOucEICB
{
public:
//-----------------------------------------------------------------------------
//! Invoke a callback after an operation completes.
//!
//! @param Result - the original function's result (may be changed).
//! @param eInfo - Associated error information. The eInfo object may not be
//! modified until it's own callback Done() method is called, if
//! supplied. If the callback function in eInfo is zero, then
//! the eInfo object is deleted by the invoked callback.
//! Otherwise, that method must be invoked by this callback
//! function after the actual callback message is sent. This
//! allows the callback requestor to do post-processing and be
//! asynchronous being assured that the callback completed.
//! @param Path - Optionally, the path related to thid request. It is used
//! for tracing and detailed monitoring purposes.
//-----------------------------------------------------------------------------
virtual void Done(int &Result, //I/O: Function result
XrdOucErrInfo *eInfo, // In: Error Info
const char *Path=0)=0;// In: Relevant path
//-----------------------------------------------------------------------------
//! Determine if two callback arguments refer to the same client.
//!
//! @param arg1 - The first callback argument.
//! @param arg2 - The second callback argument.
//!
//! @return !0 - The arguments refer to the same client.
//! @return =0 - The arguments refer to the different clients.
//-----------------------------------------------------------------------------
virtual int Same(unsigned long long arg1, unsigned long long arg2)=0;
//-----------------------------------------------------------------------------
//! Constructor and destructor
//-----------------------------------------------------------------------------
XrdOucEICB() {}
virtual ~XrdOucEICB() {}
};
#endif