/******************************************************************************/
/* */
/* X r d S s i R e q u e s t . c c */
/* */
/* (c) 2016 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
#include
#include
#include "XrdSsi/XrdSsiPacer.hh"
#include "XrdSsi/XrdSsiRespInfo.hh"
#include "XrdSsi/XrdSsiResponder.hh"
#include "XrdSsi/XrdSsiRequest.hh"
#include "XrdSsi/XrdSsiStream.hh"
/******************************************************************************/
/* S t a t i c M e m b e r s */
/******************************************************************************/
namespace XrdSsi
{
XrdSsiMutex ubMutex(XrdSsiMutex::Recursive);
}
/******************************************************************************/
/* C o n s t r u c t o r */
/******************************************************************************/
XrdSsiRequest::XrdSsiRequest(const char *reqid, uint16_t tmo)
: reqID(reqid), rrMutex(&XrdSsi::ubMutex),
theRespond(0), rsvd1(0), epNode(0),
detTTL(0), tOut(0), onClient(true), rsvd2(0) {}
/******************************************************************************/
/* Private: C l e a n U p */
/******************************************************************************/
void XrdSsiRequest::CleanUp()
{
// Reinitialize the this object in case it is being reused. While we don't
// really need to get a lock, we do so just in case there is a coding error.
//
rrMutex->Lock();
Resp.Init();
errInfo.Clr();
epNode = 0;
XrdSsiMutex *mP = rrMutex;
rrMutex = &XrdSsi::ubMutex;
mP->UnLock();
}
/******************************************************************************/
/* Private: C o p y D a t a */
/******************************************************************************/
bool XrdSsiRequest::CopyData(char *buff, int blen)
{
bool last;
// Make sure the buffer length is valid
//
if (blen <= 0)
{errInfo.Set("Buffer length invalid", EINVAL);
return false;
}
// Check if we have any data here
//
rrMutex->Lock();
if (Resp.blen > 0)
{if (Resp.blen > blen) last = false;
else {blen = Resp.blen; last = true;}
memcpy(buff, Resp.buff, blen);
Resp.buff += blen; Resp.blen -= blen;
} else {blen = 0; last = true;}
rrMutex->UnLock();
// Invoke the callback
//
ProcessResponseData(errInfo, buff, blen, last);
return true;
}
/******************************************************************************/
/* F i n i s h e d */
/******************************************************************************/
bool XrdSsiRequest::Finished(bool cancel)
{
XrdSsiResponder *respP;
// Obtain the responder
//
rrMutex->Lock();
respP = theRespond;
theRespond = 0;
rrMutex->UnLock();
// Tell any responder we are finished (we might not have one)
//
if (respP) respP->Finished(*this, Resp, cancel);
// We are done. The object will be reiniialized when UnBindRequest() is
// called which will call UnBind() in this object. Since the timing is not
// known we can't touch anthing in this object at this point.
// Return false if there was no responder associated with this request.
//
return respP != 0;
}
/******************************************************************************/
/* G e t E n d P o i n t */
/******************************************************************************/
std::string XrdSsiRequest::GetEndPoint()
{
XrdSsiMutexMon lck(rrMutex);
std::string epName(epNode ? epNode : "");
return epName;
}
/******************************************************************************/
/* G e t M e t a d a t a */
/******************************************************************************/
const char *XrdSsiRequest::GetMetadata(int &dlen)
{
XrdSsiMutexMon lck(rrMutex);
if ((dlen = Resp.mdlen)) return Resp.mdata;
return 0;
}
/******************************************************************************/
/* G e t R e s p o n s e D a t a */
/******************************************************************************/
void XrdSsiRequest::GetResponseData(char *buff, int blen)
{
XrdSsiMutexMon mHelper(rrMutex);
// If this is really a stream then just call the stream object to get the data.
// In the degenrate case, it's actually a data response, then we must copy it.
//
if (Resp.rType == XrdSsiRespInfo::isStream)
{if (Resp.strmP->SetBuff(errInfo, buff, blen)) return;}
else if (Resp.rType == XrdSsiRespInfo::isData)
{if (CopyData(buff, blen)) return;}
else errInfo.Set("Not a stream", ENODATA);
// If we got here then an error occured during the setup, reflect the error
// via the callback (in the future we will schedule a new thread).
//
ProcessResponseData(errInfo, buff, -1, true);
}
/******************************************************************************/
/* R e l e a s e R e q u e s t B u f f e r */
/******************************************************************************/
void XrdSsiRequest::ReleaseRequestBuffer()
{
XrdSsiMutexMon lck(rrMutex);
RelRequestBuffer();
}
/******************************************************************************/
/* R e s t a r t D a t a R e s p o n s e */
/******************************************************************************/
XrdSsiRequest::RDR_Info XrdSsiRequest::RestartDataResponse
(XrdSsiRequest::RDR_How rhow,
const char *reqid
)
{
RDR_Info rInfo;
XrdSsiPacer::Run(rInfo, rhow, reqid);
return rInfo;
}