From 6c9ca6b4ef70130ea837312436e67be76e7677ba Mon Sep 17 00:00:00 2001
From: Michael Davis <michael.davis@cern.ch>
Date: Sun, 4 Jun 2017 04:10:35 +0200
Subject: [PATCH] Adds Metadata and Alert protobuf messages

Metadata can be used for short replies (less overhead than a full reply)
or to provide information about the reply which will follow (e.g. number
of records, response size, etc.)

Alerts can be used to signal the client about the server state.
---
 frontend/TestSsiClient.h            |  2 +-
 frontend/TestSsiRequest.cpp         |  1 +
 frontend/TestSsiRequestProc.cpp     | 33 +++++++++++++++++++++++++++--
 frontend/TestSsiRequestProc.h       | 10 ++++-----
 frontend/TestSsiService.h           |  8 +++----
 frontend/TestSsiServiceProvider.cpp |  2 +-
 frontend/test.proto                 | 12 ++++++++---
 frontend/test_client.cpp            |  2 +-
 8 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/frontend/TestSsiClient.h b/frontend/TestSsiClient.h
index b5a228f51e..4b24861502 100644
--- a/frontend/TestSsiClient.h
+++ b/frontend/TestSsiClient.h
@@ -21,7 +21,7 @@ extern XrdSsiProvider *XrdSsiProviderClient;
 
 
 
-template <typename RequestType, typename ResponseType>
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
 class TestSsiClient
 {
 public:
diff --git a/frontend/TestSsiRequest.cpp b/frontend/TestSsiRequest.cpp
index f8d54cbe3b..31988ae61a 100644
--- a/frontend/TestSsiRequest.cpp
+++ b/frontend/TestSsiRequest.cpp
@@ -40,6 +40,7 @@ bool TestSsiRequest::ProcessResponse(const XrdSsiErrInfo &eInfo, const XrdSsiRes
 
          // do something with metadata
 
+         // A metadata-only response is indicated when XrdSsiRespInfo::rType is set to isNil (i.e. no response data is present).
 #if 0
          // clean up
 
diff --git a/frontend/TestSsiRequestProc.cpp b/frontend/TestSsiRequestProc.cpp
index c5675946e9..2eb3de557f 100644
--- a/frontend/TestSsiRequestProc.cpp
+++ b/frontend/TestSsiRequestProc.cpp
@@ -8,7 +8,7 @@
 // and metadata
 
 template <>
-void RequestProc<xrdssi::test::Request, xrdssi::test::Result>::ExecuteAction()
+void RequestProc<xrdssi::test::Request, xrdssi::test::Result, xrdssi::test::Metadata, xrdssi::test::Alert>::ExecuteAction()
 {
    // Output message in Json format (for debugging)
 
@@ -27,11 +27,40 @@ void RequestProc<xrdssi::test::Request, xrdssi::test::Result>::ExecuteAction()
 }
 
 
+
+// A metadata-only reply is appropriate when we just need to send a short response/acknowledgement,
+// as it has less overhead than a full response. The maximum amount of metadata that may be sent is
+// defined by XrdSsiResponder::MaxMetaDataSZ constant member.
+
 template <>
-void RequestProc<xrdssi::test::Request, xrdssi::test::Result>::ExecuteMetadata()
+void RequestProc<xrdssi::test::Request, xrdssi::test::Result, xrdssi::test::Metadata, xrdssi::test::Alert>::ExecuteMetadata()
 {
    std::cerr << "Sending metadata..." << std::endl;
    const std::string metadata("Have some metadata!");
    SetMetadata(metadata.c_str(), metadata.size());
 }
 
+
+
+/*
+ * Alert messages can be anything you want them to be. The SSI framework enforces
+ * the following rules:
+ *
+ * - alerts are sent in the order posted,
+ * - all outstanding alerts are sent before the final response is sent (i.e. the one
+ * posted using a SetResponse() method),
+ * - once a final response is posted, subsequent alert messages are not sent, and
+ * - if a request is cancelled, all pending alerts are discarded.
+ *
+ * In order to send an alert, you must encapsulate your message using an
+ * XrdSsiRespInfoMsg object. The object provides synchronization between posting
+ * an alert, sending the alert, and releasing storage after the alert was sent. It is defined
+ * in the XrdSsiRespInfo.hh header file.
+ *
+ * The XrdSsiRespInfoMsg object needs to be inherited by whatever class you use to
+ * manage your alert message. The pure abstract class, RecycleMsg() must also be
+ * implemented. This method is called after the message is sent or when it is discarded.
+ * A parameter to the method tells you why it’s being called.
+ *
+ * See example p.45
+ */
diff --git a/frontend/TestSsiRequestProc.h b/frontend/TestSsiRequestProc.h
index 4ac4e5d242..501596253e 100644
--- a/frontend/TestSsiRequestProc.h
+++ b/frontend/TestSsiRequestProc.h
@@ -18,7 +18,7 @@
  * RequestProc is a kind of agent object that the service object creates for each request that it receives.
  */
 
-template <typename RequestType, typename ResponseType>
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
 class RequestProc : public XrdSsiResponder
 {
 public:
@@ -41,8 +41,8 @@ private:
 
 
 
-template <typename RequestType, typename ResponseType>
-void RequestProc<RequestType, ResponseType>::Execute()
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
+void RequestProc<RequestType, ResponseType, MetadataType, AlertType>::Execute()
 {
    using namespace std;
 
@@ -98,8 +98,8 @@ void RequestProc<RequestType, ResponseType>::Execute()
 
 // 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)
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
+void RequestProc<RequestType, ResponseType, MetadataType, AlertType>::Finished(XrdSsiRequest &rqstR, const XrdSsiRespInfo &rInfo, bool cancel)
 {
    using namespace std;
 
diff --git a/frontend/TestSsiService.h b/frontend/TestSsiService.h
index 168faad999..ddcc8b60c5 100644
--- a/frontend/TestSsiService.h
+++ b/frontend/TestSsiService.h
@@ -11,7 +11,7 @@
  * Service Object, obtained using GetService() method of the TestSsiServiceProvider factory
  */
 
-template <typename RequestType, typename ResponseType>
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
 class TestSsiService : public XrdSsiService
 {
 public:
@@ -32,12 +32,12 @@ public:
 
 
 
-template <typename RequestType, typename ResponseType>
-void TestSsiService<RequestType, ResponseType>::ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef)
+template <typename RequestType, typename ResponseType, typename MetadataType, typename AlertType>
+void TestSsiService<RequestType, ResponseType, MetadataType, AlertType>::ProcessRequest(XrdSsiRequest &reqRef, XrdSsiResource &resRef)
 {
    std::cerr << "Called ProcessRequest()" << std::endl;
 
-   RequestProc<RequestType, ResponseType> processor;
+   RequestProc<RequestType, ResponseType, MetadataType, AlertType> processor;
 
    // Bind the processor to the request. Inherits the BindRequest method from XrdSsiResponder.
 
diff --git a/frontend/TestSsiServiceProvider.cpp b/frontend/TestSsiServiceProvider.cpp
index 6e2c24607f..0c7306800d 100644
--- a/frontend/TestSsiServiceProvider.cpp
+++ b/frontend/TestSsiServiceProvider.cpp
@@ -43,7 +43,7 @@ XrdSsiService* TestSsiServiceProvider::GetService(XrdSsiErrInfo &eInfo, const st
 
    cerr << "Called GetService(" << contact << "," << oHold << ")" << endl;
 
-   XrdSsiService *ptr = new TestSsiService<xrdssi::test::Request, xrdssi::test::Result>;
+   XrdSsiService *ptr = new TestSsiService<xrdssi::test::Request, xrdssi::test::Result, xrdssi::test::Metadata, xrdssi::test::Alert>;
 
    return ptr;
 }
diff --git a/frontend/test.proto b/frontend/test.proto
index a1a9ccfb34..9831f5505a 100644
--- a/frontend/test.proto
+++ b/frontend/test.proto
@@ -33,9 +33,15 @@ message Result {
   }
 }
 
-// XRootD SSI Service
+// XRootD SSI Metadata
 
-service XrdSsiService {
-  rpc SendRequest(Request) returns(Result);
+message Metadata {
+  string message_text = 1;          //< Some useful information about the next response
+}
+
+// XRootD SSI Alert
+
+message Alert {
+  string message_text = 1;          //< Some alert message for the client
 }
 
diff --git a/frontend/test_client.cpp b/frontend/test_client.cpp
index ebcf77c702..2b9f5b687c 100644
--- a/frontend/test_client.cpp
+++ b/frontend/test_client.cpp
@@ -17,7 +17,7 @@ int main(int argc, char *argv[])
    {
       // Obtain a Service Provider
 
-      TestSsiClient<xrdssi::test::Request, xrdssi::test::Result> test_ssi_service(host, port);
+      TestSsiClient<xrdssi::test::Request, xrdssi::test::Result, xrdssi::test::Metadata, xrdssi::test::Alert> test_ssi_service(host, port);
 
       // Create a Request object
 
-- 
GitLab