Logo Search packages:      
Sourcecode: yudit version File versions

bool SEventBSD::next (  )  [virtual]

Process a next event. Return false if exit was called.

Reimplemented from SEventHandlerImpl.

Definition at line 560 of file SEventBSD.cpp.

References addTimer(), SBinVector< Type >::array(), SClient::data, SEventTarget::done(), SEventTarget::error(), SBinHashtable< Type >::get(), SClient::getType(), SClient::id, SClient::progress, SEventTarget::readable(), SBinVector< Type >::remove(), remove(), sendData(), SEventTarget::serve(), SBinVector< Type >::size(), SClient::source, SClient::target, SEventTarget::timeout(), and SEventTarget::write().

{
  if (!up)
  {
#ifndef USE_WINAPI
    fprintf (stderr, "SEventBSD::next - down...\n");
#endif
    return false;
  }
#ifdef USE_WINAPI
  int dummy;
  dummy = initsockets (true);
  if (dummy < 0)
  {
    fprintf (stderr, "SEventBSD::next - no socket...\n");
    return false;
  }
#endif
  unsigned int i;
  struct timeval timeout;
  struct timeval timenow;
  struct timeval* tp= 0;
//fprintf (stderr, "readvector=%u writeVector=%u timeoutVector=%u jobVector=%u\n",
 //readVector.size(), writeVector.size(), timeoutVector.size(), jobVector.size());
  if (readVector.size() == 0 && writeVector.size()==0
    && timeoutVector.size() == 0 && jobVector.size()==0)
  {
    fprintf (stderr, "SEventBSD::next - nothing to do\n");
    return false;
  }

  int more = true;

  // Get the jobs done first
  if (jobClient.size() != 0)
  {
    // This is no rocket science here... Just a job
    while (more && jobVector.size())
    {
      more = false;
      roundRobin++;
      unsigned int  k = roundRobin % jobVector.size();
      SClient* c = jobClient[k];

      SJob *j= (SJob*)c->source;
      SEventTarget *t=c->target;

      remove (c);
      int status = j->run();
      t->done(j);
      if (status>0) more = true;
    }
  }
  /* jobs can affect up flag */
  if (!up)
  {
#ifndef USE_WINAPI
    fprintf (stderr, "SEventBSD::next - down...\n");
#endif
    return false;
  }
  
  // Create a timeout
  if (timeoutVector.size() != 0)
  {
    gettimeofday (&timenow, 0);

    // If time is set back 
    if (timenow.tv_sec < ((SEventDelegate*)delegate)->baseTime.tv_sec)
    {
      ((SEventDelegate*)delegate)->baseTime.tv_sec = timenow.tv_sec;
      ((SEventDelegate*)delegate)->baseTime.tv_usec = timenow.tv_usec;
    }
    long diff = timeoutVector[0] - substract (timenow, ((SEventDelegate*)delegate)->baseTime);
    unsigned long next = (unsigned long) diff;
    if (diff < 0)
    {
       next = 0;
    }
    timeout.tv_sec = next/1000;
    timeout.tv_usec = (next%1000) * 1000;
    tp = &timeout;
  }

  fd_set ro;
  fd_set wo;

  memcpy (&ro, &((SEventDelegate*)delegate)->readFD, sizeof (fd_set)); 
  memcpy (&wo, &((SEventDelegate*)delegate)->writeFD, sizeof (fd_set)); 

//Does not always get the SIGPIPE on Linux Alpha
//fprintf (stderr, "Before select %d %d\n", FD_ISSET (5, &wo), FD_ISSET (5, &ro));
  //fprintf (stderr, "s=%u %u %u %u\n", 
  //  readVector.size(), writeVector.size(), timeoutVector.size(),
  //  jobVector.size());

/*
  if (readVector.size() == 0 && writeVector.size() ==0
      && timeoutVector.size() == 0)
  {
    return (jobVector.size() != 0);
  }
*/

  int selected = selectHack (readMax, &ro, writeMax, &wo, 0, 0, tp);
//fprintf (stderr, "After select %d %d\n", FD_ISSET (4, &wo), FD_ISSET (5, &ro));

#ifdef USE_WINAPI
  /* -2 is windows event */
  if (selected == -2)
  {
    return true;
  }
#endif
  if (selected == -1)
  {
#ifdef USE_WINAPI
    int last = WSAGetLastError();
    fprintf (stderr, "SEventBSD:select ERROR %d\n", last);
#endif
    return false;
  }

  /*
   * Timer event
   */
  if (selected == 0)
  {
    if (timeoutClient.size() ==0)
    {
       fprintf (stderr, "unexpected timeout in : SEventBSD::next\n");
    }
    else
    {
       // FIXME: something is wrong with this array.
       // maybe it is the sorted nature.
       SClient* c = timeoutClient[0];
       SEventSource *s=c->source;
       SEventTarget *t=c->target;
       SString id = SString((const SString&)c->id);
       if (clientHashtable.get (id)!=0)
       {
         if (!t->timeout(s))
         {
           if (clientHashtable.get (id)!=0)
           {
             remove (c);
           }
         }
         else
         {
           if (clientHashtable.get (id)!=0)
           {
             remove (c);
             addTimer (s, t);
           }
         }
       }
       else
       {
         fprintf (stderr, "SEventBSD: miracle happened with timer...\n");
         timeoutVector.remove (0);
         timeoutClient.remove (0);
       }
       //return true;
    }
  }

  // See sockets. Let's see reading...
  for (i=0; i<readVector.size(); i++)
  {
   int fd = (int)readVector[i];
   if (FD_ISSET (fd, &ro))
   {
     SClient *c=readClient[i];
     SEventSource *s=c->source;
     SEventTarget *t=c->target;
     if (c->getType()==SClient::SERVER)
     {
        if (!t->serve (s))
        {
           remove (c);
        }
        FD_CLR (fd, &ro);
        break;
     }
     if (t->readable(s)==0)
     {
       FD_CLR (fd, &ro);
       continue;
     }
     char* buffer = new char[4096];
     CHECK_NEW (buffer);
     int progress = 0;
     int n;
#ifdef USE_WINAPI
     n = recv(fd, &buffer[progress], 4096, 0);
#else
     n = ::read(fd, &buffer[progress], 4096);
#endif

     if (n<0 && (errno == EINTR || errno==EAGAIN || errno==EWOULDBLOCK)) n = 0;
     if (n<0)
     {
        remove (c);
        t->error(s);
        delete buffer;
        break;
     }
     else if (!sendData(c, buffer, n))
     {
       remove (c);
       delete buffer;
       break;
     }
     delete buffer;
     FD_CLR (fd, &ro);
   }
  }

  // See sockets. Let's see writing...
  for (i=0; i<writeVector.size(); i++)
  {
   int fd = (int)writeVector[i];
   if (FD_ISSET (fd, &wo)) 
   {
     SClient *c=writeClient[i];
     SEventSource *s=c->source;
     SEventTarget *t=c->target;
     // finally...
     int n;
     sEventBSDSignal = 0;
#ifdef USE_WINAPI
     n = ::send(fd, &c->data.array()[c->progress], c->data.size()-c->progress, 0);
#else
     n = ::write(fd, &c->data.array()[c->progress], c->data.size()-c->progress);
#endif
     if (n<0 && (errno == EINTR || errno==EAGAIN || errno==EWOULDBLOCK)) n = 0;
     if (sEventBSDSignal!=0)
     {
       sEventBSDSignal=0; n=-1;
     }
     if (n<0)
     {
        remove (c);
        t->error(s);
        break;
     }
     else if ((unsigned int) n  == (c->data.size() - c->progress))
     {
       remove (c);
       t->write(s);
       break;
     }
     else
     {
       c->progress += n;
     }
     FD_CLR (fd, &wo);
   }
  }
  return true;
}


Generated by  Doxygen 1.6.0   Back to index