Skip to content
Snippets Groups Projects
Commit 0ceb8b40 authored by Michael Davis's avatar Michael Davis
Browse files

Creates generic versions of XrdSsi classes on server side

Protobufs for different message types will now be handled by template
specialization
parent 9e31f3d3
Branches
Tags
No related merge requests found
...@@ -6,7 +6,7 @@ all: test_client frontend_ssi.so ...@@ -6,7 +6,7 @@ all: test_client frontend_ssi.so
# XrdSsi server plugin # XrdSsi server plugin
frontend_ssi.so: TestSsiServiceProvider.o TestSsiService.o TestSsiRequestProc.o test.pb.o frontend_ssi.so: TestSsiServiceProvider.o TestSsiRequestProc.o test.pb.o
$(LINK.cc) -shared $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LINK.cc) -shared $^ $(LOADLIBES) $(LDLIBS) -o $@
# XrdSsi test client # XrdSsi test client
...@@ -35,4 +35,4 @@ clean: ...@@ -35,4 +35,4 @@ clean:
rm -f frontend_ssi.o frontend_ssi.so \ rm -f frontend_ssi.o frontend_ssi.so \
test_client test_client.o TestSsiRequest.o \ test_client test_client.o TestSsiRequest.o \
test.pb.cc test.pb.h test.pb.o \ test.pb.cc test.pb.h test.pb.o \
TestSsiRequestProc.o TestSsiService.o TestSsiServiceProvider.o TestSsiRequestProc.o TestSsiServiceProvider.o
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
#define __TEST_SSI_CLIENT_H #define __TEST_SSI_CLIENT_H
#include <iostream> #include <iostream>
#include <stdexcept>
#include <XrdSsi/XrdSsiProvider.hh> #include <XrdSsi/XrdSsiProvider.hh>
#include <XrdSsi/XrdSsiService.hh> #include <XrdSsi/XrdSsiService.hh>
#include "XrdSsiException.h"
#include "TestSsiRequest.h" #include "TestSsiRequest.h"
// Probably we want to allow multiple resources, e.g. streaming and non-streaming versions of the service // Probably we want to allow multiple resources, e.g. streaming and non-streaming versions of the service
...@@ -15,22 +15,6 @@ const std::string TestSsiResource("/test"); ...@@ -15,22 +15,6 @@ const std::string TestSsiResource("/test");
// Class to convert a XRootD error into a std::exception
class XrdSsiException : public std::exception
{
public:
XrdSsiException(const std::string &err_msg) : error_msg(err_msg) {}
XrdSsiException(const XrdSsiErrInfo &eInfo) : error_msg(eInfo.Get()) {}
const char* what() const noexcept { return error_msg.c_str(); }
private:
std::string error_msg;
};
// XrdSsiProviderClient is instantiated and managed by the SSI library // XrdSsiProviderClient is instantiated and managed by the SSI library
extern XrdSsiProvider *XrdSsiProviderClient; extern XrdSsiProvider *XrdSsiProviderClient;
...@@ -84,17 +68,17 @@ public: ...@@ -84,17 +68,17 @@ public:
// Serialize the request object // Serialize the request object
std::string data; std::string request_str;
if(!request_msg.SerializeToString(&data)) if(!request_msg.SerializeToString(&request_str))
{ {
throw XrdSsiException("SerializeToString() failed"); throw XrdSsiException("SerializeToString() failed");
} }
requestP = new TestSsiRequest(data, timeout); requestP = new TestSsiRequest(request_str, timeout);
// Transfer ownership of the request to the service object // Transfer ownership of the request to the service object
// TestSsiRequest handles deletion of the data buffer, so we can allow the pointer to go out-of-scope // TestSsiRequest handles deletion of the request buffer, so we can allow the pointer to go out-of-scope
serverP->ProcessRequest(*requestP, resource); serverP->ProcessRequest(*requestP, resource);
......
#include <iostream> #include <iostream>
#include "XrdSsiException.h"
#include "TestSsiRequestProc.h" #include "TestSsiRequestProc.h"
#include "TestSsiProtobuf.h"
void RequestProc::Execute() // This is for specialized private methods called by RequestProc::Execute to handle actions, alerts
{ // and metadata
using namespace std;
const string metadata("Have some metadata!");
const string response("Have a response!");
cerr << "Execute()" << endl;
// Deserialize the Request
//int reqLen;
//const char *reqData = GetRequest(reqLen);
// Parse the request
ReleaseRequestBuffer(); // Optional
// Perform the requested action
// Optional: send alerts
// Optional: send metadata ahead of the response
SetMetadata(metadata.c_str(), metadata.size()); template <>
void RequestProc<xrdssi::test::Request, xrdssi::test::Result>::ExecuteMetadata()
// Send the response
SetResponse(response.c_str(), response.size());
}
void RequestProc::Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel)
{ {
using namespace std; const std::string metadata("Have some metadata!");
SetMetadata(metadata.c_str(), metadata.size());
cerr << "Finished()" << endl;
// Reclaim any allocated resources
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __TEST_SSI_REQUEST_PROC_H #define __TEST_SSI_REQUEST_PROC_H
#include <XrdSsi/XrdSsiResponder.hh> #include <XrdSsi/XrdSsiResponder.hh>
#include "XrdSsiException.h"
/* /*
* The XrdSsiResponder class knows how to safely interact with the request object. It allows handling asynchronous * The XrdSsiResponder class knows how to safely interact with the request object. It allows handling asynchronous
...@@ -17,14 +18,92 @@ ...@@ -17,14 +18,92 @@
* RequestProc is a kind of agent object that the service object creates for each request that it receives. * RequestProc is a kind of agent object that the service object creates for each request that it receives.
*/ */
template <typename RequestType, typename ResponseType>
class RequestProc : public XrdSsiResponder class RequestProc : public XrdSsiResponder
{ {
public: public:
RequestProc() {} RequestProc() {}
virtual ~RequestProc() {} virtual ~RequestProc() {}
void Execute(); void Execute();
virtual void Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel=false) override; virtual void Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel=false) override;
private:
void ExecuteAction() {}
void ExecuteAlerts() {}
void ExecuteMetadata() {}
RequestType request;
ResponseType response;
}; };
template <typename RequestType, typename ResponseType>
void RequestProc<RequestType, ResponseType>::Execute()
{
using namespace std;
cerr << "Execute()" << endl;
// Unpack the Request buffer into a string object.
//
// We need to construct this with an explicit length, as request_buffer is a binary buffer, not a
// null-terminated string.
int request_len;
const char *request_buffer = GetRequest(request_len);
const std::string request_str(request_buffer, request_len);
// Deserialize the Request
if(!request.ParseFromString(request_str))
{
throw XrdSsiException("ParseFromString() failed");
}
// Release the request buffer (optional, perhaps it is more efficient to reuse it)
ReleaseRequestBuffer();
// Perform the requested action
ExecuteAction();
// Optional: send alerts
ExecuteAlerts();
// Optional: send metadata ahead of the response
ExecuteMetadata();
// Serialize the Response
std::string response_str;
if(!response.SerializeToString(&response_str))
{
throw XrdSsiException("SerializeToString() failed");
}
// Send the response
SetResponse(response_str.c_str(), response_str.length());
}
// Create specialized versions of this method to handle cancellation/cleanup for specific message types
template <typename RequestType, typename ResponseType>
void RequestProc<RequestType, ResponseType>::Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel)
{
using namespace std;
cerr << "Finished()" << endl;
// Reclaim any allocated resources
}
#endif #endif
#include <iostream>
#include "TestSsiService.h"
#include "TestSsiRequestProc.h"
void TestSsiService::ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef)
{
using namespace std;
cerr << "Called ProcessRequest()" << endl;
RequestProc theProcessor;
// Bind the processor to the request. This works because the
// it inherited the BindRequest method from XrdSsiResponder.
theProcessor.BindRequest(reqRef);
// Execute the request, upon return the processor is deleted
theProcessor.Execute();
// Unbind the request from the responder (required)
theProcessor.UnBindRequest();
cerr << "ProcessRequest.UnBind()" << endl;
}
...@@ -3,30 +3,55 @@ ...@@ -3,30 +3,55 @@
#include <XrdSsi/XrdSsiService.hh> #include <XrdSsi/XrdSsiService.hh>
#include "TestSsiRequestProc.h"
/* /*
* Service Object, obtained using GetService() method of the TestSsiServiceProvider factory * Service Object, obtained using GetService() method of the TestSsiServiceProvider factory
*/ */
template <typename RequestType, typename ResponseType>
class TestSsiService : public XrdSsiService class TestSsiService : public XrdSsiService
{ {
public: public:
TestSsiService() {}
virtual ~TestSsiService() {}
// The pure abstract method ProcessRequest() is called when the client calls its ProcessRequest() method to hand off
// its request and resource objects. The client’s request and resource objects are transmitted to the server and passed
// into the service’s ProcessRequest() method.
// The pure abstract method ProcessRequest() is called when the client calls its ProcessRequest() method to hand off virtual void ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef) override;
// its request and resource objects. The client’s request and resource objects are transmitted to the server and passed
// into the service’s ProcessRequest() method.
virtual void ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef) override; // Additional virtual methods:
//
// Attach(): optimize handling of detached requests
// Prepare(): perform preauthorization and resource optimization
};
// Additional virtual methods:
//
// Attach(): optimize handling of detached requests
// Prepare(): perform preauthorization and resource optimization
TestSsiService() {}
virtual ~TestSsiService() {}
}; template <typename RequestType, typename ResponseType>
void TestSsiService<RequestType, ResponseType>::ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef)
{
std::cerr << "Called ProcessRequest()" << std::endl;
RequestProc<RequestType, ResponseType> processor;
// Bind the processor to the request. Inherits the BindRequest method from XrdSsiResponder.
processor.BindRequest(reqRef);
// Execute the request, upon return the processor is deleted
processor.Execute();
// Unbind the request from the responder (required)
processor.UnBindRequest();
std::cerr << "ProcessRequest.UnBind()" << std::endl;
}
#endif #endif
...@@ -43,7 +43,7 @@ XrdSsiService* TestSsiServiceProvider::GetService(XrdSsiErrInfo &eInfo, const st ...@@ -43,7 +43,7 @@ XrdSsiService* TestSsiServiceProvider::GetService(XrdSsiErrInfo &eInfo, const st
cerr << "Called GetService(" << contact << "," << oHold << ")" << endl; cerr << "Called GetService(" << contact << "," << oHold << ")" << endl;
XrdSsiService *ptr = new TestSsiService; XrdSsiService *ptr = new TestSsiService<xrdssi::test::Request, xrdssi::test::Result>;
return ptr; return ptr;
} }
......
#ifndef __XRD_SSI_EXCEPTION_H
#define __XRD_SSI_EXCEPTION_H
// Class to convert a XRootD error into a std::exception
// Perhaps should be part of XRootD?
#include <stdexcept>
#include <XrdSsi/XrdSsiErrInfo.hh>
class XrdSsiException : public std::exception
{
public:
XrdSsiException(const std::string &err_msg) : error_msg(err_msg) {}
XrdSsiException(const XrdSsiErrInfo &eInfo) : error_msg(eInfo.Get()) {}
const char* what() const noexcept { return error_msg.c_str(); }
private:
std::string error_msg;
};
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment