xosview  1.23
About: xosview is an X Windows based system monitor (cpu, memory, swap and network usage; interrupt and serial activities; load average).
  Fossies Dox: xosview-1.23.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sarmeter.cc
Go to the documentation of this file.
1 //
2 // Initial port performed by Stefan Eilemann (eilemann@gmail.com)
3 //
4 
5 #include "sarmeter.h"
6 
7 #include <fcntl.h>
8 
10 
12 {
13  if( _instance == NULL )
14  _instance = new SarMeter();
15 
16  return _instance;
17 }
18 
20  : _bufSize(0)
21 {
22  _input = setupSadc();
23 
24  _gi.last.gswapbuf = 0;
25  _gi.info.swapBuf = 0;
26 
27  for( int i=0; i<MAX_DISKS; i++ )
28  {
29  _di.last[i].stat.io_bcnt = 0;
30  _di.last[i].stat.io_wbcnt = 0;
31 
32  _di.info.nDevices = 0;
33  _di.info.read[i] = 0;
34  _di.info.write[i] = 0;
35  }
36 }
37 
38 bool SarMeter::readLine( void )
39 {
40  while( _bufSize < BUFSIZE-100 )
41  {
42  int ret = read( _input, &_buf[_bufSize], 100);
43 
44  if( ret < 0 )
45  return false; // error equals eof in our case
46 
47  _bufSize += ret;
48 
49  if( ret < 100 ) // eof reached
50  return false;
51  }
52 
53  // buffer full
54  return true;
55 }
56 
57 void SarMeter::checkSadc( void )
58 {
59  bool dataInPipe = true;
60 
61  while( dataInPipe )
62  {
63  dataInPipe = readLine();
64  parseBuffer();
65  }
66 }
67 
69 {
70  while( _bufSize > 100 )
71  {
72  // look for 'S' (starting of Sarmagic)
73  char *ptr = (char *)memchr( _buf, 'S', _bufSize );
74 
75  // not found -- discard this buffer
76  if( ptr == NULL )
77  {
78  _bufSize = 0;
79  return;
80  }
81 
82  // not enough data read
83  if( (ptr+100) > (_buf+_bufSize) )
84  return;
85 
86 
87  // check for SarmagicGFX
88  if( memcmp( ptr, "SarmagicGFX", 11 ) == 0 )
89  {
90  forwardBufferTo( ptr );
91 
92  // data is not complete in buffer
93  if( _bufSize < 24 + sizeof( gfxinfo ))
94  return;
95 
96  // retrieve gfxinfo structure
97  ptr = _buf + 24;
98  memcpy( &_gi.current, ptr, sizeof( gfxinfo ));
99  ptr += sizeof( gfxinfo );
100 
101  forwardBufferTo( ptr );
102  newGfxInfo();
103  }
104  // check for SarmagicNEODISK
105  else if( memcmp( ptr, "SarmagicNEODISK", 15 ) == 0 )
106  {
107  forwardBufferTo( ptr );
108 
109  ptr = _buf + 20;
110 
111  // number of records [devices]
112  int num;
113  memcpy( &num, ptr, 4 );
114  ptr += 4;
115 
116  if( num > MAX_DISKS ) num = MAX_DISKS;
117 
118  // data is not complete in buffer
119  if( _bufSize < 24 + num*sizeof( diskinfo ))
120  return;
121 
122  _di.info.nDevices = num;
123 
124  // read disk info
125  for( int i=0; i<num; i++ )
126  {
127  memcpy( &_di.current[i], ptr, sizeof( diskinfo ));
128  ptr += sizeof( diskinfo );
129  }
130 
131  forwardBufferTo( ptr );
132  newDiskInfo();
133  }
134  else // no known Sarmagic record
135  forwardBufferTo( ptr+1 );
136  }
137 }
138 
140 {
141  if( _gi.last.gswapbuf == 0 )
142  {
143  _gi.last.gswapbuf = _gi.current.gswapbuf;
144  return;
145  }
146 
147  _gi.info.swapBuf = _gi.current.gswapbuf - _gi.last.gswapbuf;
148  _gi.last.gswapbuf = _gi.current.gswapbuf;
149 }
150 
152 {
153  for( int i=0; i<_di.info.nDevices; i++ )
154  {
155  _di.info.read[i] =
156  (_di.current[i].stat.io_bcnt - _di.current[i].stat.io_wbcnt) -
157  (_di.last[i].stat.io_bcnt - _di.last[i].stat.io_wbcnt) ;
158 
159  _di.info.write[i] =
160  _di.current[i].stat.io_wbcnt - _di.last[i].stat.io_wbcnt;
161 
162  _di.info.read[i] *= 512;
163  _di.info.write[i] *= 512;
164 
165  _di.last[i].stat.io_bcnt = _di.current[i].stat.io_bcnt;
166  _di.last[i].stat.io_wbcnt = _di.current[i].stat.io_wbcnt;
167  }
168 }
169 
170 void SarMeter::forwardBufferTo( char *ptr )
171 {
172  size_t moveBytes = ptr-_buf;
173  size_t bytesLeft = _bufSize - moveBytes;
174  memmove( _buf, ptr, bytesLeft );
175  _bufSize = bytesLeft;
176 };
177 
178 
179 // starts /usr/bin/sar, from where data is read
181 {
182  char sarPath[] = "/usr/lib/sa/sadc";
183  int fd[2];
184  int input = 0;
185 
186  if (pipe(fd) == -1)
187  {
188  perror("setupSar: pipe");
189  return 0;
190  }
191 
192  if ( fork()==0 ) // child
193  {
194  close(1); // move fd[write] to stdout
195  dup(fd[1]);
196  close(fd[1]);
197  close(fd[0]); // close other end of the pipe
198  close(2); // close stderr
199  setbuf(stdout,NULL); // unbuffered stdout
200 
201  // sar wants number of loops: 31536000 is one year
202  if (execlp (sarPath, sarPath, "1", "31536000", 0) == -1)
203  perror("setupSar: exec sar");
204 
205  // not reached
206  exit(0);
207  }
208 
209  input = fd[0];
210  close(fd[1]); // Close other end of the pipe
211 
212  fcntl( input, F_SETFL, FNONBLK );
213 
214  return input;
215 }
off_t _bufSize
Definition: sarmeter.h:78
SarMeter()
Definition: sarmeter.cc:19
void forwardBufferTo(char *ptr)
Definition: sarmeter.cc:170
void newGfxInfo(void)
Definition: sarmeter.cc:139
static SarMeter * _instance
Definition: sarmeter.h:76
int setupSadc(void)
Definition: sarmeter.cc:180
void parseBuffer(void)
Definition: sarmeter.cc:68
static SarMeter * Instance()
Definition: sarmeter.cc:11
struct SarMeter::@1 _di
void checkSadc(void)
Definition: sarmeter.cc:57
int _input
Definition: sarmeter.h:77
void newDiskInfo(void)
Definition: sarmeter.cc:151
char _buf[0x2000]
Definition: sarmeter.h:79
bool readLine(void)
Definition: sarmeter.cc:38
struct SarMeter::@0 _gi
#define MAX_DISKS
Definition: sarmeter.h:28
#define BUFSIZE
Definition: sarmeter.h:29