From 5b965a6c5d8dcd22c01404be39eec681c08f28c4 Mon Sep 17 00:00:00 2001
From: Gerardo Ganis <Gerardo.Ganis@cern.ch>
Date: Thu, 10 Jul 2008 09:14:33 +0000
Subject: [PATCH] File forgot in the previous patch

git-svn-id: http://root.cern.ch/svn/root/trunk@24760 27541ba8-7e3a-0410-8455-c3a389f83636
---
 proof/proofd/src/XrdProofdClient.cxx | 103 +++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 5 deletions(-)

diff --git a/proof/proofd/src/XrdProofdClient.cxx b/proof/proofd/src/XrdProofdClient.cxx
index 4c6fd944eab..ca10c315ceb 100644
--- a/proof/proofd/src/XrdProofdClient.cxx
+++ b/proof/proofd/src/XrdProofdClient.cxx
@@ -520,6 +520,27 @@ void XrdProofdClient::EraseServer(int psid)
    }
 }
 
+//______________________________________________________________________________
+int XrdProofdClient::GetTopProofServ()
+{
+   // Return the number of valid proofserv topmaster sessions in the list
+   XPDLOC(CMGR, "Client::GetTopProofServ")
+
+   int nv = 0;
+
+   XrdProofdProofServ *xps = 0;
+   std::vector<XrdProofdProofServ *>::iterator ip;
+   for (ip = fProofServs.begin(); ip != fProofServs.end(); ++ip) {
+      if ((xps = *ip) && xps->IsValid() && (xps->SrvType() == kXPD_TopMaster)) {
+         TRACE(DBG,"found potentially valid topmaster session: pid "<<xps->SrvPID());
+         nv++;
+      }
+   }
+
+   // Done
+   return nv;
+}
+
 //______________________________________________________________________________
 int XrdProofdClient::ResetClientSlot(int ic)
 {
@@ -586,6 +607,7 @@ int XrdProofdClient::SetClientID(int cid, XrdProofdProtocol *p)
 void XrdProofdClient::Broadcast(const char *msg)
 {
    // Broadcast message 'msg' to the connected clients
+   XPDLOC(CMGR, "Client::Broadcast")
 
    int len = 0;
    if (msg && (len = strlen(msg)) > 0) {
@@ -596,6 +618,8 @@ void XrdProofdClient::Broadcast(const char *msg)
       XrdSysMutexHelper mh(fMutex);
       for (ic = 0; ic < (int) fClients.size(); ic++) {
          if ((cid = fClients.at(ic)) && cid->P() && cid->P()->ConnType() == kXPD_ClientMaster) {
+
+            TRACE(ALL," sending to: "<<cid->P()->Link()->ID);
             XrdProofdResponse *response = cid->R();
             if (response)
                response->Send(kXR_attn, kXPD_srvmsg, (char *) msg, len);
@@ -626,7 +650,65 @@ void XrdProofdClient::Touch()
 }
 
 //______________________________________________________________________________
-void XrdProofdClient::SkipSessionsCheck(std::list<XrdProofdProofServ *> *active)
+bool XrdProofdClient::VerifySession(XrdProofdProofServ *xps)
+{
+   // Quick verification of session 'xps' to avoid attaching clients to
+   // non responding sessions. We do here a sort of loose ping.
+   // Return true is responding, false otherwise.
+   XPDLOC(CMGR, "Client::VerifySession")
+
+   if (!xps || !(xps->IsValid())) {
+      TRACE(XERR, " session undefined or invalid");
+      return 0;
+   }
+
+   // Admin path
+   XrdOucString path(xps->AdminPath());
+   if (path.length() <= 0) {
+      TRACE(XERR, "admin path is empty! - protocol error");
+      return 0;
+   }
+
+   // Stat the admin file
+   struct stat st0;
+   if (stat(path.c_str(), &st0) != 0) {
+      TRACE(XERR, "cannot stat admin path: "<<path);
+      return 0;
+   }
+
+   // Take the pid
+   int pid = xps->SrvPID();
+   // If the session is alive ...
+   if (XrdProofdAux::VerifyProcessByID(pid) != 0) {
+      // Send the request (no further propagation)
+      if (xps->VerifyProofServ(0) != 0) {
+         TRACE(XERR, "could not send verify request to proofsrv");
+         return 0;
+      }
+      // Wait for the action for fgMgr->SessionMgr()->VerifyTimeOut() secs,
+      // checking every 1 sec
+      struct stat st1;
+      int ns = 10;
+      while (ns--) {
+         if (stat(path.c_str(), &st1) == 0) {
+            if (st1.st_mtime > st0.st_mtime) {
+               return 1;
+            }
+         }
+         // Wait 1 sec
+         TRACE(HDBG, "waiting "<<ns<<" secs for session "<<pid<<
+                     " to touch the admin path");
+         sleep(1);
+      }
+   }
+
+   // Verification Failed
+   return 0;
+}
+
+//______________________________________________________________________________
+void XrdProofdClient::SkipSessionsCheck(std::list<XrdProofdProofServ *> *active,
+                                        XrdOucString &emsg)
 {
    // Skip the next sessions status check. This is used, for example, when
    // somebody has shown interest in these sessions to give more time for the
@@ -638,8 +720,19 @@ void XrdProofdClient::SkipSessionsCheck(std::list<XrdProofdProofServ *> *active)
    std::vector<XrdProofdProofServ *>::iterator ip;
    for (ip = fProofServs.begin(); ip != fProofServs.end(); ++ip) {
       if ((xps = *ip) && xps->IsValid() && (xps->SrvType() == kXPD_TopMaster)) {
-         xps->SetSkipCheck(); // Skip next validity check
-         if (active) active->push_back(xps);
+         if (VerifySession(xps)) {
+            xps->SetSkipCheck(); // Skip next validity check
+            if (active) active->push_back(xps);
+         } else {
+            if (xps->SrvPID() > 0) {
+               if (emsg.length() <= 0)
+                  emsg = "ignoring (apparently) non-responding session(s): ";
+               else
+                  emsg += " ";
+               emsg += xps->SrvPID();
+            }
+            TRACE(ALL,"session "<<xps->SrvPID()<<" does not react: dead?");
+         }
       }
    }
    if (active)
@@ -650,7 +743,7 @@ void XrdProofdClient::SkipSessionsCheck(std::list<XrdProofdProofServ *> *active)
 }
 
 //______________________________________________________________________________
-XrdOucString XrdProofdClient::ExportSessions()
+XrdOucString XrdProofdClient::ExportSessions(XrdOucString &emsg)
 {
    // Return a string describing the existing sessions
 
@@ -658,7 +751,7 @@ XrdOucString XrdProofdClient::ExportSessions()
 
    // Protect from next session check and get the list of actives
    std::list<XrdProofdProofServ *> active;
-   SkipSessionsCheck(&active);
+   SkipSessionsCheck(&active, emsg);
 
    // Fill info
    XrdProofdProofServ *xps = 0;
-- 
GitLab