TestSsiRequestProc.h 3.17 KB
Newer Older
1
2
3
4
#ifndef __TEST_SSI_REQUEST_PROC_H
#define __TEST_SSI_REQUEST_PROC_H

#include <XrdSsi/XrdSsiResponder.hh>
5
#include "XrdSsiException.h"
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

/*
 * The XrdSsiResponder class knows how to safely interact with the request object. It allows handling asynchronous
 * requests such as cancellation, broken TCP connections, etc.
 *
 * The XrdSsiResponder class contains all the methods needed to interact with the request object: get the request,
 * release storage, send alerts, and post a response.
 *
 * The Request object will be bound to the XrdSsiResponder object via a call to XrdSsiResponder::BindRequest().
 * Once the relationship is established, you no longer need to keep a reference to the request object. The SSI
 * framework keeps track of the request object for you.
 *
 * RequestProc is a kind of agent object that the service object creates for each request that it receives.
 */

21
template <typename RequestType, typename ResponseType>
22
23
24
class RequestProc : public XrdSsiResponder
{
public:
25
26
                RequestProc() {}
   virtual     ~RequestProc() {}
27
28
29

           void Execute();
   virtual void Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel=false) override;
30
31

private:
32
33
34
35
36
   // These methods should be specialized according to the needs of each <RequestType, ResponseType> pair

   void ExecuteAction()   { std::cerr << "Called default ExecuteAction()" << std::endl; }
   void ExecuteAlerts()   { std::cerr << "Called default ExecuteAlerts()" << std::endl; }
   void ExecuteMetadata() { std::cerr << "Called default ExecuteMetadata()" << std::endl; }
37
38
39

   RequestType  request;
   ResponseType response;
40
41
};

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66


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");
   }

67
   // Release the request buffer (optional, perhaps it is more efficient to reuse it?)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

   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
}

111
#endif