XrdCmsManTree.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                      X r d C m s M a n T r e e . c c                       */
00004 /*                                                                            */
00005 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdCmsManTree.cc 24468 2008-06-22 16:47:03Z ganis $
00012 
00013 // Original Version: 2007/07/26 15:18:24 ganis
00014 
00015 const char *XrdCmsManTreeCVSID = "$Id: XrdCmsManTree.cc 24468 2008-06-22 16:47:03Z ganis $";
00016 
00017 #include <stdio.h>
00018 
00019 #include "XProtocol/YProtocol.hh"
00020 
00021 #include "XrdCms/XrdCmsManTree.hh"
00022 #include "XrdCms/XrdCmsNode.hh"
00023 #include "XrdCms/XrdCmsTrace.hh"
00024   
00025 using namespace XrdCms;
00026 
00027 /******************************************************************************/
00028 /*                        G l o b a l   O b j e c t s                         */
00029 /******************************************************************************/
00030   
00031 XrdCmsManTree XrdCms::ManTree;
00032 
00033 /******************************************************************************/
00034 /*                               C o n n e c t                                */
00035 /******************************************************************************/
00036   
00037 int XrdCmsManTree::Connect(int nID, XrdCmsNode *nP)
00038 {
00039    static CmsDiscRequest discRequest = {{0, kYR_disc, 0, 0}};
00040    XrdSysMutexHelper Monitor(myMutex);
00041    char mybuff[8];
00042    int i;
00043 
00044 // Rule 1: If we are already connected, thell the caller to disband the
00045 //         connection as we must have a connection to an interior node.
00046 //
00047    if (myStatus == Connected) return 0;
00048    numConn++;
00049    tmInfo[nID].nodeP = nP;
00050 
00051 // Rule 2: If we connected to a root node then consider ourselves connected
00052 //         only if all connections are to the root.
00053 //
00054    if (tmInfo[nID].Level == 0)
00055       {if (numConn == maxConn)
00056           {myStatus = Connected; conLevel = 0; atRoot = 1;
00057            Say.Emsg("ManTree", "Now connected to", buff, "root node(s)");
00058           }
00059        tmInfo[nID].Status = Connected;
00060        return 1;
00061       }
00062 
00063 // Rule 3: We connected to an interior node. Disband all other existing
00064 //         connections (these should only be to root nodes) and consider 
00065 //         ourselves connected.
00066 //
00067    for (i = 0; i < maxTMI; i++)
00068        if (i != nID && tmInfo[i].Status == Connected)
00069           {tmInfo[i].nodeP->Send((char *)&discRequest, sizeof(discRequest));
00070            tmInfo[i].Status = Pending;
00071           }
00072    myStatus = Connected;
00073    conLevel = tmInfo[nID].Level;
00074    conNID   = nID;
00075    atRoot   = 0;
00076 
00077 // Document our connection configuration
00078 //
00079    snprintf(mybuff, sizeof(mybuff), "%d", conLevel);
00080    Say.Emsg("ManTree", "Now connected to supervisor at level", mybuff);
00081    return 1;
00082 }
00083 
00084 /******************************************************************************/
00085 /*                                  D i s c                                   */
00086 /******************************************************************************/
00087   
00088 void XrdCmsManTree::Disc(int nID)
00089 {
00090 
00091 // A connected caller has lost it's connection.
00092 //
00093    myMutex.Lock();
00094    if (tmInfo[nID].Status == Connected || tmInfo[nID].Status == Pending)
00095       numConn--;
00096    tmInfo[nID].Status = Active;
00097    if (atRoot || (conLevel && conNID == nID)) myStatus = Active;
00098    tmInfo[nID].nodeP = 0;
00099    myMutex.UnLock();
00100 }
00101 
00102 /******************************************************************************/
00103 /*                              R e g i s t e r                               */
00104 /******************************************************************************/
00105   
00106 int XrdCmsManTree::Register()
00107 {
00108    int nID;
00109 
00110 // Add this server to the tree table. Register is called only once and there
00111 // can be no more than MTMax connections to a manager. Hence, we dispense with
00112 // error checking (how optimistic :-)
00113 //
00114    myMutex.Lock();
00115    tmInfo[maxTMI].Status= Active;
00116    nID = maxTMI; maxTMI++;
00117    myMutex.UnLock();
00118    return nID;
00119 }
00120 
00121 /******************************************************************************/
00122 /*                             s e t M a x C o n                              */
00123 /******************************************************************************/
00124   
00125 void XrdCmsManTree::setMaxCon(int n)
00126 {
00127     maxConn = n;
00128     snprintf(buff, sizeof(buff), "%d", n);
00129 }
00130 
00131 /******************************************************************************/
00132 /*                                T r y i n g                                 */
00133 /******************************************************************************/
00134   
00135 // This method arranges server connections to a manager to form a minimal B-Tree
00136 // free of phantom arcs. The rule is simple, either all connections are to the
00137 // root of tree or there is only one connection to an interior node. Because
00138 // node discovery is non-determinstic, we must make sure that all root nodes
00139 // are tried so as to discover the full set of supervisor nodes we can contact.
00140 // This method returns True if the caller may continue at the indicated level
00141 // and False if the caller should restart at the root node.
00142 //
00143 int XrdCmsManTree::Trying(int nID, int lvl)
00144 {
00145    int i;
00146 
00147 // Set the current status of the connection
00148 //
00149    myMutex.Lock();
00150    tmInfo[nID].Level  = lvl;
00151 
00152 // Rule 1: If we are already connected at level >0 then the caller must wait
00153 //
00154    if (myStatus == Connected && conLevel > 0) 
00155       {Pause(nID);
00156        return (lvl == tmInfo[nID].Level);
00157       }
00158 
00159 // Rule 2: If the caller is trying level 0 then any waiting threads must be
00160 //         allowed to continue but forced to level 0. This allows us to discover 
00161 //         all the supervisors connected to the root.
00162 //
00163    if (!lvl)
00164       {if (numWaiting)
00165           for (i = 0; i < maxTMI; i++)
00166               if (i != nID && tmInfo[i].Status == Waiting)
00167                  {tmInfo[i].Level = 0; Redrive(i);}
00168           myMutex.UnLock();
00169           return 1;
00170       }
00171 
00172 // Rule 3: If the caller is trying at a non-zero level (interior node) and
00173 //         someone else is trying at a non-zero level, then the caller must
00174 //         wait.
00175 //
00176    for (i = 0; i < maxTMI; i++)
00177         if (i != nID && tmInfo[i].Status == Active && tmInfo[i].Level) break;
00178    if (i < maxTMI) Pause(nID);
00179       else myMutex.UnLock();
00180 
00181 // The caller may continue. Indicate whether the caller must restart at the
00182 // root node. If the caller may continue trying to connect to an interior
00183 // node then it's the only thread trying to do so.
00184 //
00185    return (lvl == tmInfo[nID].Level);
00186 }

Generated on Tue Jul 5 14:46:29 2011 for ROOT_528-00b_version by  doxygen 1.5.1