Commit b7341d17 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 bfa3c5a0
......@@ -6,7 +6,7 @@ all: test_client frontend_ssi.so
# 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 $@
# XrdSsi test client
......@@ -35,4 +35,4 @@ clean:
rm -f frontend_ssi.o frontend_ssi.so \
test_client test_client.o TestSsiRequest.o \
test.pb.cc test.pb.h test.pb.o \
TestSsiRequestProc.o TestSsiService.o TestSsiServiceProvider.o
TestSsiRequestProc.o TestSsiServiceProvider.o
......@@ -2,10 +2,10 @@
#define __TEST_SSI_CLIENT_H
#include <iostream>
#include <stdexcept>
#include <XrdSsi/XrdSsiProvider.hh>
#include <XrdSsi/XrdSsiService.hh>
#include "XrdSsiException.h"
#include "TestSsiRequest.h"
// 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");
// 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
extern XrdSsiProvider *XrdSsiProviderClient;
......@@ -84,17 +68,17 @@ public:
// 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");
}
requestP = new TestSsiRequest(data, timeout);
requestP = new TestSsiRequest(request_str, timeout);
// 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);
......
#include <iostream>
#include "XrdSsiException.h"
#include "TestSsiRequestProc.h"
#include "TestSsiProtobuf.h"
void RequestProc::Execute()
{
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
// This is for specialized private methods called by RequestProc::Execute to handle actions, alerts
// and metadata
SetMetadata(metadata.c_str(), metadata.size());
// Send the response
SetResponse(response.c_str(), response.size());
}
void RequestProc::Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel)
template <>
void RequestProc<xrdssi::test::Request, xrdssi::test::Result>::ExecuteMetadata()
{
using namespace std;
cerr << "Finished()" << endl;
// Reclaim any allocated resources
const std::string metadata("Have some metadata!");
SetMetadata(metadata.c_str(), metadata.size());
}
......@@ -2,6 +2,7 @@
#define __TEST_SSI_REQUEST_PROC_H
#include <XrdSsi/XrdSsiResponder.hh>
#include "XrdSsiException.h"
/*
* The XrdSsiResponder class knows how to safely interact with the request object. It allows handling asynchronous
......@@ -17,14 +18,92 @@
* 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
{
public:
RequestProc() {}
virtual ~RequestProc() {}
RequestProc() {}
virtual ~RequestProc() {}
void Execute();
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
#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 @@
#include <XrdSsi/XrdSsiService.hh>
#include "TestSsiRequestProc.h"
/*
* Service Object, obtained using GetService() method of the TestSsiServiceProvider factory
*/
template <typename RequestType, typename ResponseType>
class TestSsiService : public XrdSsiService
{
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
// 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;
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
......@@ -43,7 +43,7 @@ XrdSsiService* TestSsiServiceProvider::GetService(XrdSsiErrInfo &eInfo, const st
cerr << "Called GetService(" << contact << "," << oHold << ")" << endl;
XrdSsiService *ptr = new TestSsiService;
XrdSsiService *ptr = new TestSsiService<xrdssi::test::Request, xrdssi::test::Result>;
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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment