XRootD
Loading...
Searching...
No Matches
XrdFrcCID.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d F r c C I D . c c */
4/* */
5/* (c) 2010 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <cstring>
32#include <strings.h>
33#include <cstdio>
34#include <fcntl.h>
35#include <unistd.h>
36#include <cerrno>
37#include <sys/param.h>
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <sys/uio.h>
41
42#include "XrdFrc/XrdFrcCID.hh"
43#include "XrdFrc/XrdFrcTrace.hh"
44#include "XrdOuc/XrdOucEnv.hh"
46#include "XrdSys/XrdSysError.hh"
47#include "XrdSys/XrdSysFD.hh"
49
50using namespace XrdFrc;
51
52/******************************************************************************/
53/* S t a t i c V a r i a b l e s */
54/******************************************************************************/
55
56XrdFrcCID XrdFrc::CID;
57
58XrdSysMutex XrdFrcCID::cidMon::cidMutex;
59
60/******************************************************************************/
61/* A d d */
62/******************************************************************************/
63
64int XrdFrcCID::Add(const char *iName, const char *cName, time_t addT, pid_t Pid)
65{
66 cidMon cidMonitor;
67 cidEnt *cP;
68 int ckp = 0;
69
70// If this is a new entry, create one
71//
72 if (!(cP = Find(iName)))
73 {First = new cidEnt(First, iName, cName, addT, Pid);
74 if (!strcmp(iName, "anon")) Dflt = First;
75 Update();
76 return 1;
77 }
78
79// Ignore this update if this request is older than the previous one
80//
81 if (cP->addT >= addT) return 0;
82
83// Update existing entry
84//
85 if (strcmp(cP->cName, cName))
86 {free(cP->cName);
87 cP->cName = strdup(cName);
88 cP->cNLen = strlen(cName);
89 ckp = 1;
90 }
91 if (cP->Pid != Pid) {cP->Pid = Pid; ckp = 1;}
92 cP->addT = addT;
93 if (ckp) Update();
94 return ckp;
95}
96
97/******************************************************************************/
98/* Private: F i n d */
99/******************************************************************************/
100
101XrdFrcCID::cidEnt *XrdFrcCID::Find(const char *iName)
102{
103 cidEnt *cP;
104
105// If no instance name, then return default
106//
107 if (!iName || !(*iName)) return Dflt;
108
109
110// Prepare to find the name
111//
112 cP = First;
113 while(cP && strcmp(iName, cP->iName)) cP = cP->Next;
114
115// Return result
116//
117 return cP;
118}
119
120/******************************************************************************/
121/* Public: G e t */
122/******************************************************************************/
123
124int XrdFrcCID::Get(const char *iName, char *buff, int blen)
125{
126 cidMon cidMonitor;
127 cidEnt *cP;
128
129// Find the entry
130//
131 if (!(cP = Find(iName))) {*buff = 0; return 0;}
132
133// Copy out the cluster name
134//
135 strlcpy(buff, cP->cName, blen);
136 return 1;
137}
138/******************************************************************************/
139
140int XrdFrcCID::Get(const char *iName, const char *vName, XrdOucEnv *evP)
141{
142 cidMon cidMonitor;
143 cidEnt *cP;
144
145// Find the entry
146//
147 if (!(cP = Find(iName))) return 0;
148
149// Set cluster name in the environment
150//
151 if (vName && evP) evP->Put(vName, cP->cName);
152 return 1;
153}
154
155/******************************************************************************/
156/* Public: I n i t */
157/******************************************************************************/
158
159int XrdFrcCID::Init(const char *aPath)
160{
161 EPNAME("Init");
162 XrdOucStream cidFile(&Say);
163 char Path[1024], *lP, *Pfn;
164 int cidFD, n, NoGo = 0;
165
166// Construct the appropriate file names
167//
168 strcpy(Path, aPath);
169 n = strlen(aPath);
170 if (Path[n-1] != '/') Path[n++] = '/';
171 Pfn = Path+n;
172 strcpy(Pfn, "CIDS.new"); cidFN2 = strdup(Path);
173 strcpy(Pfn, "CIDS"); cidFN = strdup(Path);
174
175// Try to open the cluster checkpoint file.
176//
177 if ( (cidFD = open(cidFN, O_RDONLY, 0)) < 0)
178 {if (errno == ENOENT) return 0;
179 Say.Emsg("Init", errno, "open cluster chkpnt file", cidFN);
180 return 1;
181 }
182 cidFile.Attach(cidFD);
183
184// Now start reading records until eof.
185//
186 while((lP = cidFile.GetLine()))
187 if (*lP)
188 {DEBUG("Recovering cid entry: " <<lP);
189 NoGo |= Init(cidFile);
190 }
191
192// Now check if any errors occurred during file i/o
193//
194 if (NoGo) Say.Emsg("Init", "Errors processing chkpnt file", cidFN);
195 else if ((n = cidFile.LastError()))
196 NoGo = Say.Emsg("Init", n, "read cluster chkpnt file", cidFN);
197 cidFile.Close();
198
199// Return final return code
200//
201 return NoGo;
202}
203
204/******************************************************************************/
205
206int XrdFrcCID::Init(XrdOucStream &cidFile)
207{
208 EPNAME("Init");
209 char *iP, *cP, *tP, *uP;
210 time_t addT;
211 pid_t Pid;
212
213// The record is <iname> <cname> <addt> <pid>
214//
215 if (!(iP = cidFile.GetToken()))
216 {Say.Emsg("Init","Missing cluster instance name."); return 1;}
217 if (!(cP = cidFile.GetToken()))
218 {Say.Emsg("Init","Missing cluster name for", iP); return 1;}
219 if (!(tP = cidFile.GetToken()))
220 {Say.Emsg("Init","Missing timestamp for", iP); return 1;}
221 addT = static_cast<time_t>(strtoll(tP, &uP, 10));
222 if (!addT || *uP)
223 {Say.Emsg("Init","Invalid timestamp for", iP); return 1;}
224 if (!(tP = cidFile.GetToken()))
225 {Say.Emsg("Init","Missing process id for", iP); return 1;}
226 Pid = static_cast<pid_t>(strtol(tP, &uP, 10));
227 if (*uP)
228 {Say.Emsg("Init","Invalid process id for", iP); return 1;}
229
230// Validate the process ID
231//
232 if (Pid && kill(Pid, 0) < 0 && errno == ESRCH)
233 {DEBUG("Process " <<Pid <<" not found for instance " <<iP);
234 Pid = 0;
235 }
236
237// Now add the entry
238//
239 First = new cidEnt(First, iP, cP, addT, Pid);
240 if (!strcmp(iP, "anon")) Dflt = First;
241 return 0;
242}
243
244/******************************************************************************/
245/* Public: R e f */
246/******************************************************************************/
247
248void XrdFrcCID::Ref(const char *iName)
249{
250 cidMon cidMonitor;
251 cidEnt *cP;
252
253// Find the entry
254//
255 if ((cP = Find(iName))) cP->useCnt = 1;
256}
257
258/******************************************************************************/
259/* Private: U p d a t e */
260/******************************************************************************/
261
262int XrdFrcCID::Update()
263{
264 EPNAME("Update");
265 static char buff[40];
266 static const int Mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
267 static struct iovec iov[] = {{0,0}, {(char *)" ", 1}, // 0: Instance
268 {0,0}, // 2: Cluster
269 {buff, 0}}; // 3: Timestamp pid
270 static const int iovn = sizeof(iov)/sizeof(struct iovec);
271 FLOCK_t lock_args;
272 cidEnt *cP = First, *cPP = 0, *cPN;
273 int rc, cidFD;
274
275// Open the temp file first in r/w mode
276//
277 if ((cidFD = XrdSysFD_Open(cidFN2, O_RDWR|O_CREAT, Mode)) < 0)
278 {Say.Emsg("Init",errno,"open",cidFN2);
279 return 0;
280 }
281
282// Lock the file
283//
284 bzero(&lock_args, sizeof(lock_args));
285 lock_args.l_type = F_WRLCK;
286 do {rc = fcntl(cidFD,F_SETLKW,&lock_args);} while(rc < 0 && errno == EINTR);
287 if (rc < 0)
288 {Say.Emsg("Update", errno, "lock", cidFN2);
289 close(cidFD);
290 return 0;
291 }
292
293// Now truncate the file to zero
294//
295 if (ftruncate(cidFD, 0) < 0)
296 {Say.Emsg("Update", errno, "truncate", cidFN2);
297 close(cidFD);
298 return 0;
299 }
300
301// Write out the cluster information
302//
303 while(cP)
304 {if (!(cP->Pid) && !(cP->useCnt) && strcmp(cP->iName, "anon"))
305 {DEBUG("Removing dead instance " <<cP->iName);
306 if (cPP) cPN = cPP->Next = cP->Next;
307 else cPN = First = cP->Next;
308 delete cP;
309 cP = cPN;
310 continue;
311 }
312 iov[0].iov_base = cP->iName; iov[0].iov_len = cP->iNLen;
313 iov[2].iov_base = cP->cName; iov[2].iov_len = cP->cNLen;
314 iov[3].iov_len = sprintf(buff, " %ld %d",
315 static_cast<long>(cP->addT),
316 static_cast<int> (cP->Pid)) + 1;
317 if (writev(cidFD, iov, iovn) < 0)
318 {Say.Emsg("Update", errno, "writing", cidFN2);
319 close(cidFD);
320 return 0;
321 }
322 cPP = cP; cP = cP->Next;
323 }
324
325// Now rename the file to be the original while we hav the file open
326//
327 if (rename(cidFN2, cidFN) < 0)
328 {Say.Emsg("Update", errno, "rename", cidFN2);
329 close(cidFD);
330 return 0;
331 }
332
333// All done
334//
335 close(cidFD);
336 return 1;
337}
#define DEBUG(x)
#define EPNAME(x)
XrdOucPup XrdCmsParser::Pup & Say
#define close(a)
Definition XrdPosix.hh:48
#define open
Definition XrdPosix.hh:76
#define writev(a, b, c)
Definition XrdPosix.hh:117
#define rename(a, b)
Definition XrdPosix.hh:92
#define ftruncate(a, b)
Definition XrdPosix.hh:70
int Mode
XrdOucString Path
size_t strlcpy(char *dst, const char *src, size_t sz)
#define FLOCK_t
int Add(const char *iName, const char *cName, time_t addT, pid_t Pid)
Definition XrdFrcCID.cc:64
int Get(const char *iName, char *buff, int blen)
Definition XrdFrcCID.cc:124
int Init(const char *qPath)
Definition XrdFrcCID.cc:159
void Ref(const char *iName)
Definition XrdFrcCID.cc:248
void Put(const char *varname, const char *value)
Definition XrdOucEnv.hh:85
char * GetLine()
int Attach(int FileDescriptor, int bsz=2047)
void Close(int hold=0)
char * GetToken(int lowcase=0)