/******************************************************************************/ /* */ /* X r d C m s M a n L i s t . c c */ /* */ /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include "XrdCms/XrdCmsManList.hh" #include "XrdNet/XrdNetAddr.hh" #include "XrdOuc/XrdOucTList.hh" #include "XrdOuc/XrdOucTokenizer.hh" #include "XrdSys/XrdSysPlatform.hh" /******************************************************************************/ /* L o c a l C l a s s e s */ /******************************************************************************/ class XrdCmsManRef { public: XrdCmsManRef *Next; char *Manager; unsigned int ManRef; int ManPort; int ManLvl; XrdCmsManRef(unsigned int ref, char *name, int port, int lvl) : Next(0), Manager(name), ManRef(ref), ManPort(port), ManLvl(lvl) {}; ~XrdCmsManRef() {if (Manager) free(Manager);} }; /******************************************************************************/ /* D e s t r u c t o r */ /******************************************************************************/ XrdCmsManList::~XrdCmsManList() { XrdCmsManRef *prp, *mrp = allMans; while(mrp) {prp = mrp; mrp = mrp->Next; delete prp;} } /******************************************************************************/ /* A d d */ /******************************************************************************/ void XrdCmsManList::Add(const XrdNetAddr *netAddr, char *redList, int manPort, int lvl) { XrdOucTokenizer hList((char *)redList); char *hP; int theRef; // Get the manager's reference number and if exists, delete existing entries // if ((theRef = getRef(netAddr)) >= 0) Del(theRef); else theRef = -theRef; // Add eeach redirect target in the list // hP = hList.GetLine(); while((hP = hList.GetToken())) Add(theRef, hP, manPort, lvl); } /******************************************************************************/ void XrdCmsManList::Add(int ref, char *manp, int manport, int lvl) { XrdCmsManRef *prp = 0, *mrp; char *cp, *ipname; int port; // Find the colon in the host name // if (*manp != '[') cp = index(manp, int(':')); else if ((cp = index(manp+1, ']'))) cp = index(cp+1, int(':')); if (!cp) port = manport; else {if (!(port=atoi(cp+1)) || port > 0xffff) port=manport; *cp = '\0'; } // Get the full name of the host target unless it is an actual address // if (XrdNetAddrInfo::isHostName(manp)) ipname = strdup(manp); else {XrdNetAddr redAddr; const char *redName; if (redAddr.Set(manp,0) || !(redName = redAddr.Name())) return; ipname = strdup(redName); } if (cp) *cp = ':'; // Start up // mlMutex.Lock(); mrp = allMans; // Chck if this is a duplicate // while(mrp) {if (!strcmp(mrp->Manager, ipname) && mrp->ManPort == port) {mlMutex.UnLock(); free(ipname); return;} if (mrp->Next) {if (mrp->Next->ManLvl > lvl) prp = mrp;} else if (!prp) prp = mrp; mrp = mrp->Next; } // Create new entry // mrp = new XrdCmsManRef(ref, ipname, port, lvl); if (!prp) nextMan = allMans = mrp; else {mrp->Next = prp->Next; prp->Next = mrp; if (nextMan->ManLvl > lvl) nextMan = mrp; } mlMutex.UnLock(); } /******************************************************************************/ /* D e l */ /******************************************************************************/ void XrdCmsManList::Del(int ref) { XrdCmsManRef *nrp, *prp = 0, *mrp; // If mistakingly called for a newly added reference, do nothing // if (ref < 0) return; // Start up // mlMutex.Lock(); mrp = allMans; // Delete all ref entries // while(mrp) {if (mrp->ManRef == (unsigned int)ref) {nrp = mrp->Next; if (!prp) allMans = nrp; else {prp->Next = nrp; if (mrp == allMans) allMans = nrp; } if (mrp == nextMan) nextMan = nrp; delete mrp; mrp = nrp; } else {prp = mrp; mrp = mrp->Next;} } // All done // mlMutex.UnLock(); } /******************************************************************************/ /* g e t R e f */ /******************************************************************************/ int XrdCmsManList::getRef(const XrdNetAddr *netAddr) { static int refNum = 1; XrdNetAddr theAddr = *netAddr; XrdOucTList *tP; char buff[128]; int theNum; // Convert address to text // theAddr.Format(buff,sizeof(buff),XrdNetAddr::fmtAdv6,XrdNetAddr::old6Map4); // Find the entry in this list // refMutex.Lock(); tP = refList; while(tP && strcmp(buff, tP->text)) tP = tP->next; // If we didn't find one, add it // if (tP) theNum = tP->val; else {refList = new XrdOucTList(buff, refNum, refList); theNum = -refNum++; } // Return the number // refMutex.UnLock(); return theNum; } /******************************************************************************/ /* N e x t */ /******************************************************************************/ int XrdCmsManList::Next(int &port, char *buff, int bsz) { XrdCmsManRef *np; int lvl; mlMutex.Lock(); if (!(np = nextMan)) nextMan = allMans; else {strlcpy(buff, np->Manager, bsz); port = np->ManPort; nextMan = np->Next; } lvl = (np ? np->ManLvl : 0); mlMutex.UnLock(); return lvl; }