"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.193/src/agent/subagents/hpux/iostat.cpp" (4 Mar 2021, 8986 Bytes) of package /linux/misc/netxms-3.8.193.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 HP-UX
    3 ** Copyright (C) 2006 Alex Kirhenshtein
    4 ** Copyright (C) 2010 Victor Kirhenshtein
    5 **
    6 ** This program is free software; you can redistribute it and/or modify
    7 ** it under the terms of the GNU General Public License as published by
    8 ** the Free Software Foundation; either version 2 of the License, or
    9 ** (at your option) any later version.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 ** GNU General Public License for more details.
   15 **
   16 ** You should have received a copy of the GNU General Public License
   17 ** along with this program; if not, write to the Free Software
   18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   19 **
   20 */
   21 
   22 #include "hpux.h"
   23 #include <sys/pstat.h>
   24 
   25 #define MAX_DEVICES     256
   26 #define SAMPLE_COUNT    60
   27 
   28 #define PSTTIME_TO_MS(x) (((QWORD)x.pst_sec * 1000) + ((QWORD)x.pst_usec / 1000))
   29 
   30 
   31 //
   32 // Disk information structure
   33 //
   34 
   35 struct DISK_INFO
   36 {
   37     int devMajor;
   38     int devMinor;
   39     char hwPath[PS_MAX_HW_ELEMS];
   40     int queueLen[SAMPLE_COUNT];
   41     QWORD transfers[SAMPLE_COUNT];
   42     QWORD reads[SAMPLE_COUNT];
   43     QWORD writes[SAMPLE_COUNT];
   44     QWORD bytesRead[SAMPLE_COUNT];
   45     QWORD bytesWritten[SAMPLE_COUNT];
   46     QWORD waitTime[SAMPLE_COUNT];
   47     struct pst_diskinfo last;
   48 };
   49 
   50 
   51 //
   52 // Static data
   53 //
   54 
   55 static DISK_INFO s_total;
   56 static DISK_INFO s_devices[MAX_DEVICES];
   57 static int s_currSlot = 0;
   58 static THREAD s_collectorThread = INVALID_THREAD_HANDLE;
   59 static MUTEX s_dataLock = INVALID_MUTEX_HANDLE;
   60 static CONDITION s_condShutdown = INVALID_CONDITION_HANDLE;
   61 
   62 
   63 //
   64 // Calculate total values
   65 //
   66 
   67 static void CalculateTotals()
   68 {
   69     s_total.queueLen[s_currSlot] = 0;
   70     s_total.transfers[s_currSlot] = 0;
   71     s_total.reads[s_currSlot] = 0;
   72     s_total.writes[s_currSlot] = 0;
   73     s_total.bytesRead[s_currSlot] = 0;
   74     s_total.bytesWritten[s_currSlot] = 0;
   75     s_total.waitTime[s_currSlot] = 0;
   76 
   77     for(int i = 0; i < MAX_DEVICES; i++)
   78     {
   79         if ((s_devices[i].devMajor == 0) && (s_devices[i].devMinor == 0))
   80             break;
   81 
   82         s_total.queueLen[s_currSlot] += s_devices[i].queueLen[s_currSlot];
   83         s_total.transfers[s_currSlot] += s_devices[i].transfers[s_currSlot];
   84         s_total.reads[s_currSlot] += s_devices[i].reads[s_currSlot];
   85         s_total.writes[s_currSlot] += s_devices[i].writes[s_currSlot];
   86         s_total.bytesRead[s_currSlot] += s_devices[i].bytesRead[s_currSlot];
   87         s_total.bytesWritten[s_currSlot] += s_devices[i].bytesWritten[s_currSlot];
   88         s_total.waitTime[s_currSlot] += s_devices[i].waitTime[s_currSlot];
   89     }
   90 }
   91 
   92 
   93 //
   94 // Process stats for single disk
   95 //
   96 
   97 static void ProcessDiskStats(struct pst_diskinfo *di)
   98 {
   99     DISK_INFO *dev;
  100     int i;
  101 
  102     for(i = 0; i < MAX_DEVICES; i++)
  103     {
  104         if ((di->psd_dev.psd_major == s_devices[i].devMajor) &&
  105             (di->psd_dev.psd_minor == s_devices[i].devMinor))
  106         {
  107             dev = &s_devices[i];
  108             break;
  109         }
  110         if ((s_devices[i].devMajor == 0) && (s_devices[i].devMinor == 0))
  111         {
  112             // End of device list, take new slot
  113             dev = &s_devices[i];
  114             dev->devMajor = di->psd_dev.psd_major;
  115             dev->devMinor = di->psd_dev.psd_minor;
  116             strcpy(dev->hwPath, di->psd_hw_path.psh_name);
  117             memcpy(&dev->last, di, sizeof(struct pst_diskinfo));
  118             AgentWriteDebugLog(4, _T("HPUX: device %d.%d hwpath %s added to I/O stat collection"),
  119                                dev->devMajor, dev->devMinor, dev->hwPath);
  120             return;  // No prev data for new device, ignore this sample
  121         }
  122     }
  123 
  124     if (i == MAX_DEVICES)
  125         return; // New device and no more free slots
  126 
  127     dev->queueLen[s_currSlot] = di->psd_dkqlen_curr;
  128     dev->transfers[s_currSlot] = di->psd_dkxfer - dev->last.psd_dkxfer;
  129 #if HAVE_DISKINFO_RWSTATS
  130     dev->reads[s_currSlot] = di->psd_dkread - dev->last.psd_dkread;
  131     dev->writes[s_currSlot] = di->psd_dkwrite - dev->last.psd_dkwrite;
  132     dev->bytesRead[s_currSlot] = di->psd_dkbyteread - dev->last.psd_dkbyteread;
  133     dev->bytesWritten[s_currSlot] = di->psd_dkbytewrite - dev->last.psd_dkbytewrite;
  134 #else
  135     dev->reads[s_currSlot] = 0;
  136     dev->writes[s_currSlot] = 0;
  137     dev->bytesRead[s_currSlot] = 0;
  138     dev->bytesWritten[s_currSlot] = 0;
  139 #endif
  140     dev->waitTime[s_currSlot] = PSTTIME_TO_MS(di->psd_dkwait) - PSTTIME_TO_MS(dev->last.psd_dkwait);
  141 
  142     memcpy(&dev->last, di, sizeof(struct pst_diskinfo));
  143 }
  144 
  145 /**
  146  * I/O stat collector
  147  */
  148 static THREAD_RESULT THREAD_CALL IOStatCollector(void *arg)
  149 {
  150     struct pst_diskinfo di[64];
  151     int index, count;
  152 
  153     AgentWriteDebugLog(1, _T("HPUX: I/O stat collector thread started"));
  154 
  155     while(!ConditionWait(s_condShutdown, 1000))
  156     {
  157         MutexLock(s_dataLock);
  158         for(index = 0, count = 64; count == 64; index += 64)
  159         {
  160             count = pstat_getdisk(di, sizeof(struct pst_diskinfo), 64, index);
  161             for(int i = 0; i < count; i++)
  162             {
  163                 ProcessDiskStats(&di[i]);
  164             }
  165         }
  166         CalculateTotals();
  167         s_currSlot++;
  168         if (s_currSlot == SAMPLE_COUNT)
  169             s_currSlot = 0;
  170         MutexUnlock(s_dataLock);
  171     }
  172 
  173     AgentWriteDebugLog(1, _T("HPUX: I/O stat collector thread stopped"));
  174     return THREAD_OK;
  175 }
  176 
  177 /**
  178  * Initialize I/O stat collector
  179  */
  180 void StartIOStatCollector()
  181 {
  182     memset(&s_total, 0, sizeof(s_total));
  183     memset(s_devices, 0, sizeof(s_devices));
  184     s_dataLock = MutexCreate();
  185     s_condShutdown = ConditionCreate(TRUE);
  186     s_collectorThread = ThreadCreateEx(IOStatCollector, 0, NULL);
  187 }
  188 
  189 /**
  190  * Shutdown I/O stat collector
  191  */
  192 void ShutdownIOStatCollector()
  193 {
  194     ConditionSet(s_condShutdown);
  195     ThreadJoin(s_collectorThread);
  196     MutexDestroy(s_dataLock);
  197     ConditionDestroy(s_condShutdown);
  198 }
  199 
  200 /**
  201  * Calculate average value for 32bit series
  202  */
  203 static double CalculateAverage32(int *series)
  204 {
  205     double sum = 0;
  206     for(int i = 0; i < SAMPLE_COUNT; i++)
  207         sum += series[i];
  208     return sum / (double)SAMPLE_COUNT;
  209 }
  210 
  211 /**
  212  * Calculate average value for 64bit series
  213  */
  214 static QWORD CalculateAverage64(QWORD *series)
  215 {
  216     QWORD sum = 0;
  217     for(int i = 0; i < SAMPLE_COUNT; i++)
  218         sum += series[i];
  219     return sum / SAMPLE_COUNT;
  220 }
  221 
  222 /**
  223  * Calculate average wait time
  224  */
  225 static DWORD CalculateAverageTime(QWORD *opcount, QWORD *times)
  226 {
  227     QWORD totalOps = 0;
  228     QWORD totalTime = 0;
  229 
  230     for(int i = 0; i < SAMPLE_COUNT; i++)
  231     {
  232         totalOps += opcount[i];
  233         totalTime += times[i];
  234     }
  235     return totalOps == 0 ? 0 : (DWORD)(totalTime / totalOps);
  236 }
  237 
  238 /**
  239  * Get total I/O stat value
  240  */
  241 LONG H_IOStatsTotal(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
  242 {
  243     LONG rc = SYSINFO_RC_SUCCESS;
  244 
  245     MutexLock(s_dataLock);
  246     switch(CAST_FROM_POINTER(arg, int))
  247     {
  248         case IOSTAT_NUM_READS:
  249             ret_double(value, CalculateAverage64(s_total.reads));
  250             break;
  251         case IOSTAT_NUM_WRITES:
  252             ret_double(value, CalculateAverage64(s_total.writes));
  253             break;
  254         case IOSTAT_NUM_XFERS:
  255             ret_double(value, CalculateAverage64(s_total.transfers));
  256             break;
  257         case IOSTAT_QUEUE:
  258             ret_double(value, CalculateAverage32(s_total.queueLen));
  259             break;
  260         case IOSTAT_NUM_RBYTES:
  261             ret_uint64(value, CalculateAverage64(s_total.bytesRead));
  262             break;
  263         case IOSTAT_NUM_WBYTES:
  264             ret_uint64(value, CalculateAverage64(s_total.bytesWritten));
  265             break;
  266         case IOSTAT_WAIT_TIME:
  267             ret_uint(value, CalculateAverageTime(s_total.transfers, s_total.waitTime));
  268             break;
  269         default:
  270             rc = SYSINFO_RC_UNSUPPORTED;
  271             break;
  272     }
  273     MutexUnlock(s_dataLock);
  274     return rc;
  275 }
  276 
  277 /**
  278  * Get I/O stat for specific device
  279  */
  280 LONG H_IOStats(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
  281 {
  282     char device[MAX_PATH];
  283     struct stat devInfo;
  284     LONG rc = SYSINFO_RC_SUCCESS;
  285     int i;
  286 
  287     if (!AgentGetParameterArgA(cmd, 1, device, MAX_PATH))
  288         return SYSINFO_RC_UNSUPPORTED;
  289 
  290     if (stat(device, &devInfo) != 0)
  291         return (errno == EIO) ? SYSINFO_RC_ERROR : SYSINFO_RC_UNSUPPORTED;
  292     if (!S_ISBLK(devInfo.st_mode))
  293         return SYSINFO_RC_UNSUPPORTED;
  294     int devMajor = major(devInfo.st_rdev);
  295     int devMinor = minor(devInfo.st_rdev);
  296 
  297     // find device
  298     for(i = 0; (i < MAX_DEVICES) && (makedev(s_devices[i].devMajor, s_devices[i].devMinor) != 0); i++)
  299         if ((s_devices[i].devMajor == devMajor) && (s_devices[i].devMinor == devMinor))
  300             break;
  301     if ((i == MAX_DEVICES) || ((s_devices[i].devMajor == 0) && (s_devices[i].devMinor == 0)))
  302         return SYSINFO_RC_UNSUPPORTED;  // unknown device
  303 
  304     MutexLock(s_dataLock);
  305     switch(CAST_FROM_POINTER(arg, int))
  306     {
  307         case IOSTAT_NUM_READS:
  308             ret_double(value, CalculateAverage64(s_devices[i].reads));
  309             break;
  310         case IOSTAT_NUM_WRITES:
  311             ret_double(value, CalculateAverage64(s_devices[i].writes));
  312             break;
  313         case IOSTAT_NUM_XFERS:
  314             ret_double(value, CalculateAverage64(s_devices[i].transfers));
  315             break;
  316         case IOSTAT_QUEUE:
  317             ret_double(value, CalculateAverage32(s_devices[i].queueLen));
  318             break;
  319         case IOSTAT_NUM_RBYTES:
  320             ret_uint64(value, CalculateAverage64(s_devices[i].bytesRead));
  321             break;
  322         case IOSTAT_NUM_WBYTES:
  323             ret_uint64(value, CalculateAverage64(s_devices[i].bytesWritten));
  324             break;
  325         case IOSTAT_WAIT_TIME:
  326             ret_uint(value, CalculateAverageTime(s_devices[i].transfers, s_devices[i].waitTime));
  327             break;
  328         default:
  329             rc = SYSINFO_RC_UNSUPPORTED;
  330             break;
  331     }
  332     MutexUnlock(s_dataLock);
  333     return rc;
  334 }
  335