31 #include <sys/types.h>
58 const char *XrdOssSpace::qFname = 0;
59 const char *XrdOssSpace::uFname = 0;
60 const char *XrdOssSpace::uUname = 0;
62 short XrdOssSpace::uDvec[XrdOssSpace::maxEnt] = {0};
63 int XrdOssSpace::fencEnt = 0;
64 int XrdOssSpace::freeEnt =-1;
65 int XrdOssSpace::aFD =-1;
66 int XrdOssSpace::uAdj = 0;
67 int XrdOssSpace::uSync = 0;
68 int XrdOssSpace::Solitary = 0;
69 time_t XrdOssSpace::lastMtime = 0;
70 time_t XrdOssSpace::lastUtime = 0;
85 int uOff = offsetof(
uEnt,Bytes[0]) + (
sizeof(
long long)*stNum);
89 if (Gent < 0 || Gent >= fencEnt)
return;
90 offset =
sizeof(
uEnt)*Gent + uOff;
95 if (Solitary && stNum ==
Serv) stNum = (Space > 0 ?
Pstg :
Purg);
101 {
if (!UsageLock())
return;
102 if (
pread(aFD, &uData[Gent],
sizeof(
uEnt), offset-uOff) < 0)
104 UsageLock(0);
return;
115 if ((uData[Gent].Bytes[stNum] += Space) < 0 && stNum !=
Admin)
116 uData[Gent].
Bytes[stNum] = 0;
121 if (
pwrite(aFD, &uData[Gent].Bytes[stNum], ULen, offset) < 0)
122 OssEroute.
Emsg(
"Adjust", errno,
"update usage file", uFname);
126 if (stNum !=
Serv) utimes(uUname, 0);
132 if (uAdj >= uSync) {
fsync(aFD); uAdj = 0;}
137 if (unlk) UsageLock(0);
148 if ((i = findEnt(GName)) >= 0)
Adjust(i, Space, stNum);
158 int XrdOssSpace::Assign(
const char *GName,
long long &
Usage)
165 if ((i = findEnt(GName)) >= 0)
173 if (freeEnt >= maxEnt || freeEnt < 0)
180 if (!UsageLock())
return -1;
181 memset(&uData[freeEnt], 0,
sizeof(uEnt));
182 strcpy(uData[freeEnt].gName, GName);
183 uData[freeEnt].
Bytes[
addT] =
static_cast<long long>(time(0));
184 offset =
sizeof(uEnt) * freeEnt;
185 if (
pwrite(aFD, &uData[freeEnt],
sizeof(uEnt), offset) < 0)
186 {
OssEroute.
Emsg(
"Adjust", errno,
"update usage file", uFname);
187 UsageLock(0);
return -1;
193 uDvec[fencEnt++] = i = freeEnt;
197 for (freeEnt = freeEnt+1; freeEnt < maxEnt; freeEnt++)
198 if (*uData[freeEnt].gName ==
'\0')
break;
209 int XrdOssSpace::findEnt(
const char *GName)
215 for (i = 0; i < fencEnt; i++)
216 if (!strcmp(uData[uDvec[i]].gName, GName))
return i;
230 static const mode_t theMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
233 char *aP, buff[1048];
234 int i,
opts, updt = 0;
238 memset(uData, 0,
sizeof(uData));
247 {qFname = strdup(qPath);
254 if (!aPath)
return 1;
256 aP = buff + strlen(aPath);
257 if (*(aP-1) !=
'/') *aP++ =
'/';
259 {strcpy(aP, iP); aP += strlen(iP); *aP++ =
'/'; *aP =
'\0';
260 mkdir(buff, S_IRWXU | S_IRWXG);
262 strcpy(aP,
".Usage");
263 uFname = strdup(buff);
264 strcpy(aP,
".Usage.upd");
265 uUname = strdup(buff);
270 if ((i =
open(uUname, O_CREAT|O_TRUNC|O_RDWR, theMode)) < 0)
274 if (!
fstat(i, &buf)) lastUtime = buf.st_mtime;
281 if (
stat(uFname, &buf))
285 }
else opts = O_CREAT|O_TRUNC;
286 else if ( buf.st_size != DataSz && buf.st_size)
287 {
OssEroute.
Emsg(
"Init", uFname,
"has invalid size.");
return 0;}
292 if (us > 1) uSync = us;
293 else opts |= O_DSYNC;
297 if ((aFD = XrdSysFD_Open(uFname,
opts|O_RDWR, theMode)) < 0)
308 if (
opts & O_CREAT || buf.st_size == 0)
309 {
if (!
write(aFD, uData,
sizeof(uData)))
311 UsageLock(0);
return 0;
313 fencEnt = 0; freeEnt = 0;
315 if (!
read(aFD, uData,
sizeof(uData)))
317 UsageLock(0);
return 0;
319 for (i = 0; i < maxEnt; i++)
320 {
if (*uData[i].gName !=
'\0')
321 {uDvec[fencEnt++] = i; updt |= Readjust(i);}
322 else if (freeEnt < 0) freeEnt = i;
329 if (updt &&
pwrite(aFD, uData,
sizeof(uData), 0) < 0)
335 sprintf(buff,
"%d usage log entries in use; %d available.",
336 fencEnt, maxEnt-fencEnt);
356 if (
stat(qFname,&buf))
357 {
OssEroute.
Emsg(
"Quotas", errno,
"process quota file", qFname);
360 if (buf.st_mtime == lastMtime)
return 0;
361 lastMtime = buf.st_mtime;
365 if ( (qFD =
open(qFname, O_RDONLY, 0)) < 0)
378 while((val =
Config.GetMyFirstWord()))
379 {
if (strlen(val) >=
sizeof(cgroup))
385 if (!(val =
Config.GetWord()))
386 {
OssEroute.
Emsg(
"Quotas",
"quota value not specified for", cgroup);
393 while(fsg && strcmp(cgroup, fsg->
group)) fsg = fsg->
next;
394 if (fsg) fsg->
Quota = qval;
397 "cache group not found; quota ignored");
401 return (NoGo ? 0 : 1);
408 int XrdOssSpace::Readjust()
412 int k, rwsz, updt = 0;
419 OssEroute.
Emsg(
"Readjust", errno,
"sync usage file", uFname);
424 if (fencEnt <= 0)
return 0;
425 if (!
stat(uUname, &buf))
426 {
if (buf.st_mtime == lastUtime)
return 0;
427 lastUtime = buf.st_mtime;
429 rwsz =
sizeof(uEnt)*(uDvec[fencEnt-1] + 1);
433 if (!UsageLock())
return 0;
437 if (!
pread(aFD, uData, rwsz, 0))
439 UsageLock(0);
return 0;
444 for (k = 0; k < fencEnt; k++) updt |= Readjust(uDvec[k]);
449 {
if (
pwrite(aFD, uData, rwsz, 0) < 0)
451 else if (uSync &&
fsync(aFD))
452 OssEroute.
Emsg(
"Readjust", errno,
"sync usage file", uFname);
463 int XrdOssSpace::Readjust(
int i)
468 if (uData[i].Bytes[
Pstg] || uData[i].Bytes[
Purg] || uData[i].Bytes[
Admin])
469 {
long long oldVal = uData[i].
Bytes[
Serv];
474 snprintf(buff,
sizeof(buff),
"%lld to %lld bytes",
475 oldVal, uData[i].Bytes[
Serv]);
476 OssEroute.
Emsg(
"Readjust",uData[i].gName,
"space usage adjusted from",buff);
493 for (k = 0; k < fencEnt; k++)
494 if (!strcmp(uData[uDvec[k]].gName, GName))
break;
495 if (k >= fencEnt)
return -1;
500 if (!UsageLock())
return -1;
501 memset(&uData[i], 0,
sizeof(
uEnt));
502 offset =
sizeof(
uEnt) * i;
503 if (
pwrite(aFD, &uData[freeEnt],
sizeof(
uEnt), offset) < 0)
504 {
OssEroute.
Emsg(
"Unassign", errno,
"update usage file", uFname);
505 UsageLock(0);
return -1;
511 if (i < freeEnt) freeEnt = i;
512 for (i = k+1; i < fencEnt; i++) uDvec[k++] = uDvec[i];
528 retVal = (gent < 0 || gent >= maxEnt ? 0 : uData[gent].
Bytes[
Serv]);
543 {
if (fencEnt <= 0)
return -1;
545 rwsz =
sizeof(
uEnt)*(uDvec[fencEnt-1] + 1);
546 if (!
pread(aFD, uData, rwsz, 0))
548 UsageLock(0);
return -1;
555 if ((i = findEnt(GName)) >= 0)
562 memset(&uVal, 0,
sizeof(
uEnt));
575 int XrdOssSpace::UsageLock(
int Dolock)
584 bzero(&lock_args,
sizeof(lock_args));
585 if (Dolock) {lock_args.l_type = F_WRLCK; What =
"lock";}
586 else {lock_args.l_type = F_UNLCK; What =
"unlock";}
590 do {rc =
fcntl(aFD,F_SETLKW,&lock_args);}
while(rc < 0 && errno == EINTR);
591 if (rc < 0) {
OssEroute.
Emsg(
"UsageLock", errno, What, uFname);
return 0;}
void Usage(const char *msg)
ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
int fstat(int fildes, struct stat *buf)
int fcntl(int fd, int cmd,...)
int mkdir(const char *path, mode_t mode)
ssize_t write(int fildes, const void *buf, size_t nbyte)
ssize_t read(int fildes, void *buf, size_t nbyte)
static long long PubQuota
static XrdOssCache_Group * fsgroups
static long long Usage(int gent)
static const int minSNbsz
static const int haveQuota
static const int haveUsage
static void Adjust(int Gent, off_t Space, sType=Serv)
static int Unassign(const char *GName)
static int Export(const char *Var, const char *Val)
static const char * InstName(int TranOpt=0)
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)