"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.166/src/agent/subagents/sunos/iostat.cpp" (23 Feb 2021, 10432 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "iostat.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** NetXMS subagent for SunOS/Solaris
    3 ** Copyright (C) 2004-2011 Victor Kirhenshtein
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License as published by
    7 ** the Free Software Foundation; either version 2 of the License, or
    8 ** (at your option) any later version.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13 ** GNU General Public License for more details.
   14 **
   15 ** You should have received a copy of the GNU General Public License
   16 ** along with this program; if not, write to the Free Software
   17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18 **
   19 ** File: iostat.cpp
   20 **
   21 **/
   22 
   23 #include "sunos_subagent.h"
   24 
   25 
   26 //
   27 // Constants
   28 //
   29 
   30 #define MAX_DEVICES     255
   31 #define HISTORY_SIZE        60
   32 
   33 
   34 //
   35 // Device I/O stats structure
   36 //
   37 
   38 struct IO_STATS
   39 {
   40    // device name
   41    char dev[KSTAT_STRLEN];
   42 
   43    // current values
   44    QWORD currBytesRead;
   45    QWORD currBytesWritten;
   46    DWORD currReadOps;
   47    DWORD currWriteOps;
   48    DWORD currQueue;
   49 
   50    // history - totals for queue, deltas for others
   51    QWORD histBytesRead[HISTORY_SIZE];
   52    QWORD histBytesWritten[HISTORY_SIZE];
   53    DWORD histReadOps[HISTORY_SIZE];
   54    DWORD histWriteOps[HISTORY_SIZE];
   55    DWORD histQueue[HISTORY_SIZE];
   56 };
   57 
   58 /**
   59  * Static data
   60  */
   61 static IO_STATS s_data[MAX_DEVICES + 1];
   62 static int s_currSlot = 0;  // current history slot
   63 
   64 /**
   65  * Process stats for single device
   66  */
   67 static void ProcessDeviceStats(const char *dev, kstat_io_t *kio)
   68 {
   69    int i;
   70 
   71    // find device
   72    for(i = 1; i <= MAX_DEVICES; i++)
   73       if (!strcmp(dev, s_data[i].dev) || (s_data[i].dev[0] == 0))
   74          break;
   75    if (i > MAX_DEVICES)
   76       return;       // No more free slots
   77 
   78    if (s_data[i].dev[0] == 0)
   79    {
   80       // new device
   81       AgentWriteDebugLog(5, _T("SunOS: device %hs added to I/O stat collection"), dev);
   82       strcpy(s_data[i].dev, dev);
   83    }
   84    else
   85    {
   86       // existing device - update history
   87       s_data[i].histBytesRead[s_currSlot] = kio->nread - s_data[i].currBytesRead;
   88       s_data[i].histBytesWritten[s_currSlot] = kio->nwritten - s_data[i].currBytesWritten;
   89       s_data[i].histReadOps[s_currSlot] = kio->reads - s_data[i].currReadOps;
   90       s_data[i].histWriteOps[s_currSlot] = kio->writes - s_data[i].currWriteOps;
   91       s_data[i].histQueue[s_currSlot] = kio->wcnt + kio->rcnt;
   92    }
   93 
   94    // update current values
   95    s_data[i].currBytesRead = kio->nread;
   96    s_data[i].currBytesWritten = kio->nwritten;
   97    s_data[i].currReadOps = kio->reads;
   98    s_data[i].currWriteOps = kio->writes;
   99    s_data[i].currQueue = kio->wcnt + kio->rcnt;
  100 }
  101 
  102 /**
  103  * Calculate total values for all devices
  104  */
  105 static void CalculateTotals()
  106 {
  107    QWORD br = 0, bw = 0;
  108    DWORD r = 0, w = 0, q = 0;
  109 
  110    for(int i = 1; (i <= MAX_DEVICES) && (s_data[i].dev[0] != 0); i++)
  111    {
  112       br += s_data[i].histBytesRead[s_currSlot];
  113       bw += s_data[i].histBytesWritten[s_currSlot];
  114       r += s_data[i].histReadOps[s_currSlot];
  115       w += s_data[i].histWriteOps[s_currSlot];
  116       q += s_data[i].histQueue[s_currSlot];
  117    }
  118 
  119    s_data[0].histBytesRead[s_currSlot] = br;
  120    s_data[0].histBytesWritten[s_currSlot] = bw;
  121    s_data[0].histReadOps[s_currSlot] = r;
  122    s_data[0].histWriteOps[s_currSlot] = w;
  123    s_data[0].histQueue[s_currSlot] = q;
  124 }
  125 
  126 /**
  127  * I/O stat collector
  128  */
  129 THREAD_RESULT THREAD_CALL IOStatCollector(void *arg)
  130 {
  131    kstat_ctl_t *kc;
  132    kstat_t *kp;
  133    kstat_io_t kio;
  134 
  135    kstat_lock();
  136    kc = kstat_open();
  137    kstat_unlock();
  138    if (kc == NULL)
  139    {
  140       AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("SunOS::IOStatCollector: call to kstat_open failed (%s), I/O statistic will not be collected"), _tcserror(errno));
  141       return THREAD_OK;
  142    }
  143 
  144    memset(s_data, 0, sizeof(IO_STATS) * (MAX_DEVICES + 1));
  145    AgentWriteDebugLog(1, _T("SunOS: I/O stat collector thread started"));
  146 
  147    while(!g_bShutdown)
  148    {
  149       kstat_lock();
  150       kstat_chain_update(kc);
  151       for(kp = kc->kc_chain; kp != NULL; kp = kp->ks_next)
  152       {
  153          if (kp->ks_type == KSTAT_TYPE_IO)
  154          {
  155             kstat_read(kc, kp, &kio);
  156             ProcessDeviceStats(kp->ks_name, &kio);
  157          }
  158       }
  159       kstat_unlock();
  160       CalculateTotals();
  161       s_currSlot++;
  162       if (s_currSlot == HISTORY_SIZE)
  163          s_currSlot = 0;
  164       ThreadSleepMs(1000);
  165    }
  166 
  167    AgentWriteDebugLog(1, _T("SunOS: I/O stat collector thread stopped"));
  168    kstat_lock();
  169    kstat_close(kc);
  170    kstat_unlock();
  171    return THREAD_OK;
  172 }
  173 
  174 /**
  175  * Calculate average value for 32bit series
  176  */
  177 static double CalculateAverage32(DWORD *series)
  178 {
  179    double sum = 0;
  180    for(int i = 0; i < HISTORY_SIZE; i++)
  181       sum += series[i];
  182    return sum / (double)HISTORY_SIZE;
  183 }
  184 
  185 /**
  186  * Calculate min value for 32bit series
  187  */
  188 static DWORD CalculateMin32(DWORD *series)
  189 {
  190    DWORD val = series[0];
  191    for(int i = 1; i < HISTORY_SIZE; i++)
  192       if (series[i] < val)
  193          val = series[i];
  194    return val;
  195 }
  196 
  197 /**
  198  * Calculate max value for 32bit series
  199  */
  200 static DWORD CalculateMax32(DWORD *series)
  201 {
  202    DWORD val = series[0];
  203    for(int i = 1; i < HISTORY_SIZE; i++)
  204       if (series[i] > val)
  205          val = series[i];
  206    return val;
  207 }
  208 
  209 /**
  210  * Calculate average value for 64bit series
  211  */
  212 static QWORD CalculateAverage64(QWORD *series)
  213 {
  214    QWORD sum = 0;
  215    for(int i = 0; i < HISTORY_SIZE; i++)
  216       sum += series[i];
  217    return sum / HISTORY_SIZE;
  218 }
  219 
  220 /**
  221  * Calculate min value for 64bit series
  222  */
  223 static QWORD CalculateMin64(QWORD *series)
  224 {
  225    QWORD val = series[0];
  226    for(int i = 1; i < HISTORY_SIZE; i++)
  227       if (series[i] < val)
  228          val = series[i];
  229    return val;
  230 }
  231 
  232 /**
  233  * Calculate max value for 64bit series
  234  */
  235 static QWORD CalculateMax64(QWORD *series)
  236 {
  237    QWORD val = series[0];
  238    for(int i = 1; i < HISTORY_SIZE; i++)
  239       if (series[i] > val)
  240          val = series[i];
  241    return val;
  242 }
  243 
  244 /**
  245  * Get total I/O stat value
  246  */
  247 LONG H_IOStatsTotal(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
  248 {
  249    LONG rc = SYSINFO_RC_SUCCESS;
  250 
  251    switch(CAST_FROM_POINTER(arg, int))
  252    {
  253       case IOSTAT_NUM_READS:
  254          ret_double(value, CalculateAverage32(s_data[0].histReadOps));
  255          break;
  256       case IOSTAT_NUM_READS_MIN:
  257          ret_uint(value, CalculateMin32(s_data[0].histReadOps));
  258          break;
  259       case IOSTAT_NUM_READS_MAX:
  260          ret_uint(value, CalculateMax32(s_data[0].histReadOps));
  261          break;
  262       case IOSTAT_NUM_WRITES:
  263          ret_double(value, CalculateAverage32(s_data[0].histWriteOps));
  264          break;
  265       case IOSTAT_NUM_WRITES_MIN:
  266          ret_uint(value, CalculateMin32(s_data[0].histWriteOps));
  267          break;
  268       case IOSTAT_NUM_WRITES_MAX:
  269          ret_uint(value, CalculateMax32(s_data[0].histWriteOps));
  270          break;
  271       case IOSTAT_QUEUE:
  272          ret_double(value, CalculateAverage32(s_data[0].histQueue));
  273          break;
  274       case IOSTAT_QUEUE_MIN:
  275          ret_uint(value, CalculateMin32(s_data[0].histQueue));
  276          break;
  277       case IOSTAT_QUEUE_MAX:
  278          ret_uint(value, CalculateMax32(s_data[0].histQueue));
  279          break;
  280       case IOSTAT_NUM_RBYTES:
  281          ret_uint64(value, CalculateAverage64(s_data[0].histBytesRead));
  282          break;
  283       case IOSTAT_NUM_RBYTES_MIN:
  284          ret_uint64(value, CalculateMin64(s_data[0].histBytesRead));
  285          break;
  286       case IOSTAT_NUM_RBYTES_MAX:
  287          ret_uint64(value, CalculateMax64(s_data[0].histBytesRead));
  288          break;
  289       case IOSTAT_NUM_WBYTES:
  290          ret_uint64(value, CalculateAverage64(s_data[0].histBytesWritten));
  291          break;
  292       case IOSTAT_NUM_WBYTES_MIN:
  293          ret_uint64(value, CalculateMin64(s_data[0].histBytesWritten));
  294          break;
  295       case IOSTAT_NUM_WBYTES_MAX:
  296          ret_uint64(value, CalculateMax64(s_data[0].histBytesWritten));
  297          break;
  298       default:
  299          rc = SYSINFO_RC_UNSUPPORTED;
  300          break;
  301    }
  302    return rc;
  303 }
  304 
  305 /**
  306  * Get I/O stat for specific device
  307  */
  308 LONG H_IOStats(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
  309 {
  310    char device[KSTAT_STRLEN];
  311    LONG rc = SYSINFO_RC_SUCCESS;
  312    int i;
  313 
  314    if (!AgentGetParameterArgA(cmd, 1, device, KSTAT_STRLEN))
  315       return SYSINFO_RC_UNSUPPORTED;
  316 
  317    // find device
  318    for(i = 1; (i <= MAX_DEVICES) && (s_data[i].dev[0] != 0); i++)
  319       if (!strcmp(device, s_data[i].dev))
  320          break;
  321    if ((i > MAX_DEVICES) || (s_data[i].dev[0] == 0))
  322       return SYSINFO_RC_UNSUPPORTED;    // unknown device
  323 
  324    switch(CAST_FROM_POINTER(arg, int))
  325    {
  326       case IOSTAT_NUM_READS:
  327          ret_double(value, CalculateAverage32(s_data[i].histReadOps));
  328          break;
  329       case IOSTAT_NUM_READS_MIN:
  330          ret_uint(value, CalculateMin32(s_data[i].histReadOps));
  331          break;
  332       case IOSTAT_NUM_READS_MAX:
  333          ret_uint(value, CalculateMax32(s_data[i].histReadOps));
  334          break;
  335       case IOSTAT_NUM_WRITES:
  336          ret_double(value, CalculateAverage32(s_data[i].histWriteOps));
  337          break;
  338       case IOSTAT_NUM_WRITES_MIN:
  339          ret_uint(value, CalculateMin32(s_data[i].histWriteOps));
  340          break;
  341       case IOSTAT_NUM_WRITES_MAX:
  342          ret_uint(value, CalculateMax32(s_data[i].histWriteOps));
  343          break;
  344       case IOSTAT_QUEUE:
  345          ret_double(value, CalculateAverage32(s_data[i].histQueue));
  346          break;
  347       case IOSTAT_QUEUE_MIN:
  348          ret_uint(value, CalculateMin32(s_data[i].histQueue));
  349          break;
  350       case IOSTAT_QUEUE_MAX:
  351          ret_uint(value, CalculateMax32(s_data[i].histQueue));
  352          break;
  353       case IOSTAT_NUM_RBYTES:
  354          ret_uint64(value, CalculateAverage64(s_data[i].histBytesRead));
  355          break;
  356       case IOSTAT_NUM_RBYTES_MIN:
  357          ret_uint64(value, CalculateMin64(s_data[i].histBytesRead));
  358          break;
  359       case IOSTAT_NUM_RBYTES_MAX:
  360          ret_uint64(value, CalculateMax64(s_data[i].histBytesRead));
  361          break;
  362       case IOSTAT_NUM_WBYTES:
  363          ret_uint64(value, CalculateAverage64(s_data[i].histBytesWritten));
  364          break;
  365       case IOSTAT_NUM_WBYTES_MIN:
  366          ret_uint64(value, CalculateMin64(s_data[i].histBytesWritten));
  367          break;
  368       case IOSTAT_NUM_WBYTES_MAX:
  369          ret_uint64(value, CalculateMax64(s_data[i].histBytesWritten));
  370          break;
  371       default:
  372          rc = SYSINFO_RC_UNSUPPORTED;
  373          break;
  374    }
  375    return rc;
  376 }
  377