Back to index

nordugrid-arc-nox  1.1.0~rc6
commfifo.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <unistd.h>
00006 #include <fcntl.h>
00007 #include <errno.h>
00008 #include <string.h>
00009 
00010 #include <sys/types.h>
00011 #include <sys/stat.h>
00012 
00013 #include "commfifo.h"
00014 
00015 
00016 CommFIFO::CommFIFO(void) {
00017   timeout_=-1;
00018   lock.lock();
00019   int filedes[2];
00020   kick_in=-1; kick_out=-1;
00021   if(pipe(filedes) == 0) {
00022     kick_in=filedes[1];
00023     kick_out=filedes[0];
00024     long arg;
00025     arg=fcntl(kick_in,F_GETFL);
00026     if(arg != -1) { arg|=O_NONBLOCK; fcntl(kick_in,F_SETFL,&arg); };
00027     arg=fcntl(kick_out,F_GETFL);
00028     if(arg != -1) { arg|=O_NONBLOCK; fcntl(kick_out,F_SETFL,&arg); };
00029   };
00030   lock.unlock();
00031 }
00032 
00033 CommFIFO::~CommFIFO(void) {
00034 }
00035 
00036 JobUser* CommFIFO::wait(int timeout) {
00037   time_t start_time = time(NULL);
00038   time_t end_time = start_time + timeout;
00039   for(;;) {
00040     fd_set fin,fout,fexc;
00041     FD_ZERO(&fin); FD_ZERO(&fout); FD_ZERO(&fexc);
00042     int maxfd=-1;
00043     if(kick_out >= 0) { maxfd=kick_out; FD_SET(kick_out,&fin); };
00044     lock.lock();
00045     for(std::list<elem_t>::iterator i = fds.begin();i!=fds.end();++i) {
00046       if(i->fd < 0) continue;
00047       if(i->fd>maxfd) maxfd=i->fd;
00048       FD_SET(i->fd,&fin);
00049     };
00050     lock.unlock();
00051     int n;
00052     maxfd++;
00053     if(timeout >= 0) {
00054       struct timeval t;
00055       if(((int)(end_time-start_time)) < 0) return NULL;
00056       t.tv_sec=end_time-start_time;
00057       t.tv_usec=0;
00058       n = select(maxfd,&fin,&fout,&fexc,&t);
00059       start_time = time(NULL);
00060     } else {
00061       n = select(maxfd,&fin,&fout,&fexc,NULL);
00062     };
00063     if(n == 0) return NULL;
00064     if(n == -1) {
00065       // One of fifos must be broken ?
00066 
00067     };
00068     if(kick_out >= 0) {
00069       if(FD_ISSET(kick_out,&fin)) {
00070         char buf[256]; (read(kick_out,buf,256) != -1);
00071         continue;
00072       };
00073     };
00074     lock.lock();
00075     for(std::list<elem_t>::iterator i = fds.begin();i!=fds.end();++i) {
00076       if(i->fd < 0) continue;
00077       if(FD_ISSET(i->fd,&fin)) {
00078         lock.unlock();
00079         char buf[256];
00080         ssize_t l = read(i->fd,buf,sizeof(buf));
00081         // -1 ???
00082         // 0 means kick, 1 - ping, rest undefined yet
00083         if(l > 0) if(memchr(buf,0,sizeof(buf))) return i->user;
00084       };
00085     };
00086     lock.unlock();
00087   };
00088 }
00089 
00090 bool CommFIFO::add(JobUser& user) {
00091   std::string path = user.ControlDir() + "/gm." + user.UnixName() + ".fifo";
00092   if(mkfifo(path.c_str(),S_IRUSR | S_IWUSR) != 0) {
00093     if(errno != EEXIST) {
00094       return false; 
00095     };
00096   };
00097   (void)chmod(path.c_str(),S_IRUSR | S_IWUSR);
00098   uid_t uid = user.get_uid();
00099   gid_t gid = user.get_gid();
00100   (lchown(path.c_str(),uid,gid) != 0);
00101   int fd = open(path.c_str(),O_RDONLY | O_NONBLOCK);
00102   if(fd == -1) return false;
00103   int fd_keep = open(path.c_str(),O_WRONLY | O_NONBLOCK);
00104   if(fd_keep == -1) { close(fd); return false; };
00105   elem_t el; el.user=&user; el.fd=fd; el.fd_keep=fd_keep;
00106   lock.lock();
00107   fds.push_back(el);
00108   lock.unlock();
00109   if(kick_in >= 0) {
00110     char c = 0;
00111     (write(kick_in,&c,1) != -1);
00112   };
00113   return true;
00114 }
00115 
00116 static int OpenFIFO(const JobUser& user) {
00117   // Here O_NONBLOCK ensures open() will fail if nothing listens
00118   std::string path = user.ControlDir() + "/gm." + user.UnixName() + ".fifo";
00119   int fd = open(path.c_str(),O_WRONLY | O_NONBLOCK);
00120   if(fd == -1) {
00121     // If there is no fifo for this user, try to use common one
00122     path=user.ControlDir() + "/gm..fifo";
00123     fd=open(path.c_str(),O_WRONLY | O_NONBLOCK);
00124   };
00125   // If fd == -1 here there is no FIFO or nothing is listening on another end
00126   return fd;
00127 }
00128 
00129 bool SignalFIFO(const JobUser& user) {
00130   int fd = OpenFIFO(user);
00131   if(fd == -1) return false;
00132   char c = 0;
00133   if(write(fd,&c,1) != 1) { close(fd); return false; };
00134   close(fd);
00135   return true;
00136 }
00137 
00138 bool PingFIFO(const JobUser& user) {
00139   int fd = OpenFIFO(user);
00140   // If nothing is listening open() will fail
00141   // so there is no need to send anything.
00142   if(fd == -1) return false;
00143   close(fd);
00144   return true;
00145 }
00146