LCOV - code coverage report
Current view: top level - src - IOSource.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 78 91.0 %
Date: 2010-12-13 Functions: 6 8 75.0 %
Branches: 40 56 71.4 %

           Branch data     Line data    Source code
       1                 :            : // $Id: IOSource.cc 4771 2007-08-11 05:50:24Z vern $
       2                 :            : 
       3                 :            : #include <sys/types.h>
       4                 :            : #include <sys/time.h>
       5                 :            : #include <unistd.h>
       6                 :            : #include <assert.h>
       7                 :            : 
       8                 :            : #include "util.h"
       9                 :            : #include "IOSource.h"
      10                 :            : 
      11                 :          6 : IOSourceRegistry io_sources;
      12                 :            : 
      13                 :          3 : IOSourceRegistry::~IOSourceRegistry()
      14                 :            :         {
      15 [ +  + ][ #  # ]:          5 :         for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i )
      16                 :          2 :                 delete *i;
      17                 :            : 
      18                 :          3 :         sources.clear();
      19                 :          3 :         }
      20                 :            : 
      21                 :          0 : void IOSourceRegistry::RemoveAll()
      22                 :            :         {
      23                 :            :         // We're cheating a bit here ...
      24                 :          0 :         dont_counts = sources.size();
      25                 :          0 :         }
      26                 :            : 
      27                 :      21349 : IOSource* IOSourceRegistry::FindSoonest(double* ts)
      28                 :            :         {
      29                 :            :         // Remove sources which have gone dry. For simplicity, we only
      30                 :            :         // remove at most one each time.
      31         [ +  + ]:      64046 :         for ( SourceList::iterator i = sources.begin();
      32                 :            :               i != sources.end(); ++i )
      33         [ +  + ]:      42698 :                 if ( ! (*i)->src->IsOpen() )
      34                 :            :                         {
      35                 :          1 :                         delete *i;
      36                 :          1 :                         sources.erase(i);
      37                 :          1 :                         break;
      38                 :            :                         }
      39                 :            : 
      40                 :            :         // Ideally, we would always call select on the fds to see which
      41                 :            :         // are ready, and return the soonest. Unfortunately, that'd mean
      42                 :            :         // one select-call per packet, which we can't afford in high-volume
      43                 :            :         // environments.  Thus, we call select only every SELECT_FREQUENCY
      44                 :            :         // call (or if all sources report that they are dry).
      45                 :            : 
      46                 :      21349 :         ++call_count;
      47                 :            : 
      48                 :      21349 :         IOSource* soonest_src = 0;
      49                 :      21349 :         double soonest_ts = 1e20;
      50                 :      21349 :         double soonest_local_network_time = 1e20;
      51                 :      21349 :         bool all_idle = true;
      52                 :            : 
      53                 :            :         // Find soonest source of those which tell us they have something to
      54                 :            :         // process.
      55         [ +  + ]:      64046 :         for ( SourceList::iterator i = sources.begin(); i != sources.end(); ++i )
      56                 :            :                 {
      57         [ +  + ]:      42697 :                 if ( ! (*i)->src->IsIdle() )
      58                 :            :                         {
      59                 :      21348 :                         all_idle = false;
      60                 :      21348 :                         double local_network_time = 0;
      61                 :      21348 :                         double ts = (*i)->src->NextTimestamp(&local_network_time);
      62   [ +  +  +  - ]:      21348 :                         if ( ts > 0 && ts < soonest_ts )
      63                 :            :                                 {
      64                 :      21347 :                                 soonest_ts = ts;
      65                 :      21347 :                                 soonest_src = (*i)->src;
      66                 :            :                                 soonest_local_network_time =
      67                 :            :                                         local_network_time ?
      68         [ -  + ]:      21347 :                                                 local_network_time : ts;
      69                 :            :                                 }
      70                 :            :                         }
      71                 :            :                 }
      72                 :            : 
      73                 :            :         // If we found one and aren't going to select this time,
      74                 :            :         // return it.
      75                 :      21349 :         int maxx = 0;
      76                 :            : 
      77 [ +  + ][ +  + ]:      21349 :         if ( soonest_src && (call_count % SELECT_FREQUENCY) != 0 )
      78                 :      20494 :                 goto finished;
      79                 :            : 
      80                 :            :         // Select on the join of all file descriptors.
      81                 :            :         fd_set fd_read, fd_write, fd_except;
      82                 :            : 
      83                 :        855 :         FD_ZERO(&fd_read);
      84                 :        855 :         FD_ZERO(&fd_write);
      85                 :        855 :         FD_ZERO(&fd_except);
      86                 :            : 
      87         [ +  + ]:       2564 :         for ( SourceList::iterator i = sources.begin();
      88                 :            :               i != sources.end(); ++i )
      89                 :            :                 {
      90                 :       1709 :                 Source* src = (*i);
      91                 :            : 
      92         [ +  + ]:       1709 :                 if ( ! src->src->IsIdle() )
      93                 :            :                         // No need to select on sources which we know to
      94                 :            :                         // be ready.
      95                 :        853 :                         continue;
      96                 :            : 
      97                 :        856 :                 src->fd_read = src->fd_write = src->fd_except = 0;
      98                 :        856 :                 src->src->GetFds(&src->fd_read, &src->fd_write, &src->fd_except);
      99                 :            : 
     100                 :        856 :                 FD_SET(src->fd_read, &fd_read);
     101                 :        856 :                 FD_SET(src->fd_write, &fd_write);
     102                 :        856 :                 FD_SET(src->fd_except, &fd_except);
     103                 :            : 
     104                 :        856 :                 maxx = max(src->fd_read, maxx);
     105                 :        856 :                 maxx = max(src->fd_write, maxx);
     106                 :        856 :                 maxx = max(src->fd_except, maxx);
     107                 :            :                 }
     108                 :            : 
     109                 :            :         // We can't block indefinitely even when all sources are dry:
     110                 :            :         // we're doing some IOSource-independent stuff in the main loop,
     111                 :            :         // so we need to return from time to time. (Instead of no time-out
     112                 :            :         // at all, we use a very small one. This lets FreeBSD trigger a
     113                 :            :         // BPF buffer switch on the next read when the hold buffer is empty
     114                 :            :         // while the store buffer isn't filled yet.
     115                 :            : 
     116                 :            :         struct timeval timeout;
     117                 :            : 
     118         [ +  + ]:        855 :         if ( all_idle )
     119                 :            :                 {
     120                 :            :                 // Interesting: when all sources are dry, simply sleeping a
     121                 :            :                 // bit *without* watching for any fd becoming ready may
     122                 :            :                 // decrease CPU load. I guess that's because it allows
     123                 :            :                 // the kernel's packet buffers to fill. - Robin
     124                 :          1 :                 timeout.tv_sec = 0;
     125                 :          1 :                 timeout.tv_usec = 20; // SELECT_TIMEOUT;
     126                 :          1 :                 select(0, 0, 0, 0, &timeout);
     127                 :            :                 }
     128                 :            : 
     129         [ -  + ]:        855 :         if ( ! maxx )
     130                 :            :                 // No selectable fd at all.
     131                 :          0 :                 goto finished;
     132                 :            : 
     133                 :        855 :         timeout.tv_sec = 0;
     134                 :        855 :         timeout.tv_usec = 0;
     135                 :            : 
     136         [ +  + ]:        855 :         if ( select(maxx + 1, &fd_read, &fd_write, &fd_except, &timeout) > 0 )
     137                 :            :                 { // Find soonest.
     138         [ +  + ]:       2534 :                 for ( SourceList::iterator i = sources.begin();
     139                 :            :                       i != sources.end(); ++i )
     140                 :            :                         {
     141                 :       1689 :                         Source* src = (*i);
     142                 :            : 
     143         [ +  + ]:       1689 :                         if ( ! src->src->IsIdle() )
     144                 :        843 :                                 continue;
     145                 :            : 
     146 [ +  + ][ -  + ]:        846 :                         if ( FD_ISSET(src->fd_read, &fd_read) ||
         [ #  # ][ +  - ]
     147                 :            :                              FD_ISSET(src->fd_write, &fd_write) ||
     148                 :            :                              FD_ISSET(src->fd_except, &fd_except) )
     149                 :            :                                 {
     150                 :        846 :                                 double local_network_time = 0;
     151                 :        846 :                                 double ts = src->src->NextTimestamp(&local_network_time);
     152   [ -  +  #  # ]:        846 :                                 if ( ts > 0.0 && ts < soonest_ts )
     153                 :            :                                         {
     154                 :          0 :                                         soonest_ts = ts;
     155                 :          0 :                                         soonest_src = src->src;
     156                 :            :                                         soonest_local_network_time =
     157                 :            :                                                 local_network_time ?
     158         [ #  # ]:          0 :                                                         local_network_time : ts;
     159                 :            :                                         }
     160                 :            :                                 }
     161                 :            :                         }
     162                 :            :                 }
     163                 :            : 
     164                 :      21349 : finished:
     165                 :      21349 :         *ts = soonest_local_network_time;
     166                 :      21349 :         return soonest_src;
     167                 :            :         }
     168                 :            : 
     169                 :          3 : void IOSourceRegistry::Register(IOSource* src, bool dont_count)
     170                 :            :         {
     171                 :          3 :         Source* s = new Source;
     172                 :          3 :         s->src = src;
     173         [ +  + ]:          3 :         if ( dont_count )
     174                 :          2 :                 ++dont_counts;
     175                 :          3 :         return sources.push_back(s);
     176 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8