Announcement

Collapse
No announcement yet.

monitor disk activy in total

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • monitor disk activy in total

    I'am working on a program which should shutdown/hibernate/suspend a PC. The machine is sometimes heavy loaded, so it would be nice to wait until the work is done. This ca be CPU load or disk activity.
    For the first part i have some useful sources already, but the part with the disk activity seems to be a little more difficult. I cannot say what disk is used and it's not always the same. Just need a % value of disk activity over all disks, so i could set a minimum limit and the execute shutdown/etc...

    Looked up at MSDN: Performance Data Helper could be useful, but never worked with it yet.

    Any help/tips appreciated.
    I'am still confused...but on a higher level.

  • #2
    "In theory" you could set up events (FindFirstChangeNotification + FindNextChangeNotification) on the root folder of all drives available, specifiying you want the subdirectory changes, and then do some kind of 'frequency analysis'... eg "if I get less than 5 hits in a minute I can assume the machine is not really busy anymore and it's safe to shut down."

    This does suffer from one major weakness... if a file is being read or written, there is no event to be recorded until the file is closed.

    But maybe this is a start.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Disk activity monitor

      Here is some sample code to monitor ALL disk activities. I have made the observing part as multithreaded. If you want to observe more than one disk just change ObsDrv="CDEF".

      Have fun with it:

      Code:
      #COMPILE EXE
      #DIM ALL
      #INCLUDE "win32api.inc"
      
      
      GLOBAL hThread()    AS LONG
      GLOBAL HDDAct()     AS LONG
      GLOBAL gLock        AS CRITICAL_SECTION
      GLOBAL gKillThreads AS LONG
      
      
      MACRO ActiveWait
      
          IF PeekMessage (MSG, %NULL, 0,0, %PM_REMOVE) THEN
              TranslateMessage MSG
              DispatchMessage MSG
          END IF
      
      END MACRO
      
      
      '-----------------------------------------------------------------
      ' Function  thDiskActivity
      '           threaded disk activity check
      ' in        DrvAct: drive to observe, 0=cancel/end, 1=A:, 2=B:,...
      ' out       DrvAct: activity => THREAD STATUS
      '------------------------------------------------------------------
      FUNCTION thDiskActivity(BYVAL DrvAct AS LONG) AS LONG
      
          THREADED hDir     AS DWORD
          LOCAL ret       AS DWORD
          LOCAL drv       AS ASCIIZ * 4
          LOCAL t, td   AS QUAD
          LOCAL i         AS LONG
          LOCAL hitCount  AS LONG
          LOCAL MSG      AS tagMSG
          'LOCAL sText     AS STRING
      
          'build Driveletter
          drv = CHR$(DrvAct+64) + ":\"
          hitCount = 0
          'MSGBOX "observing " + drv
      
          DO
              t = TIMER
              hDir = FindFirstChangeNotification(drv, %True, _
                      %FILE_NOTIFY_CHANGE_SIZE OR _
                      %FILE_NOTIFY_CHANGE_FILE_NAME OR _
                      %FILE_NOTIFY_CHANGE_DIR_NAME OR _
                      %FILE_NOTIFY_CHANGE_LAST_WRITE OR _
                      %FILE_NOTIFY_CHANGE_LAST_ACCESS OR _
                      %FILE_NOTIFY_CHANGE_CREATION)
              DO
                  ret = WaitForSingleObject(hDir, 100)
                  ActiveWait
                  EnterCriticalSection(gLock)
                      IF gKillThreads = %True THEN
                          GOTO EndThread
                      END IF
                  LeaveCriticalSection(gLock)
                  td = TIMER - t
                  IF td > 10 THEN
                      'sText = ""
                      EnterCriticalSection(gLock)
                          FOR i = LBOUND(HDDAct) TO UBOUND(HDDAct)-1
                              HDDAct(i) = HDDAct(i+1)
                              'sText = sText + "|" + STR$(HDDAct(i))
                          NEXT i
                          DECR HDDAct(UBOUND(HDDAct)) '= hitCount
                          'sText = sText + "|" + STR$(hitCount)
                          'msgbox "Speicher:" + sText
                      LeaveCriticalSection(gLock)
                      hitCount = 0
                      t = TIMER
                  END IF
              LOOP WHILE ret <> 0
              DO
                  EnterCriticalSection(gLock)
                      IF gKillThreads = %True THEN
                          GOTO EndThread
                      END IF
                  LeaveCriticalSection(gLock)
                  INCR hitCount
                  MSGBOX Drv + " change..Time/Nr." + STR$(td) + "/" + STR$(hitCount)
                  ret = FindNextChangeNotification(hDir)
                  ret = WaitForSingleObject(hDir, 100)
                  EXIT DO
              LOOP
              'ActiveWait
          LOOP
      
      EndThread:
          LeaveCriticalSection(gLock)
          ret = FindCloseChangeNotification( hDir )
          FUNCTION = -1
      
      
      END FUNCTION
      
      
      
      
      
      FUNCTION PBMAIN() AS LONG
      
          ON ERROR GOTO eOut
      
          LOCAL lState        AS LONG
          LOCAL lResult       AS LONG
          LOCAL i, sum        AS LONG
          LOCAL Mittel        AS LONG
          LOCAL sText         AS STRING
          LOCAL ObsDrv        AS STRING
          LOCAL ObsDrvCount   AS LONG
          LOCAL elem          AS STRING
          LOCAL DrvNr         AS LONG
          LOCAL MaxHDD        AS LONG
      
          DIM HDDAct(1 TO 6)
          DIM hThread(1 TO 26)
      
          ObsDrv = "C"
          MaxHDD= 5
      
          FOR i = LBOUND(HDDAct) TO UBOUND(HDDAct)
              HDDAct(i) = MaxHDD
          NEXT i
          InitializeCriticalSection(gLock)
      
          'bring up threads
          ObsDrvCount = LEN(ObsDrv)
          FOR i = 1 TO ObsDrvCount
              elem = MID$(ObsDrv,i,1)
              DrvNr = ASC(elem)-64
              THREAD CREATE thDiskActivity(DrvNr) TO hThread(i)
          NEXT i
          SLEEP 100
          'lResult = MSGBOX("Überwachung beenden mit OK.", %MB_OK, "Observing Disk "+CHR$(DrvNr)+":")
      
          DO
              sum = 0
              sText = ""
              EnterCriticalSection(gLock)
                  FOR i = LBOUND(HDDAct) TO UBOUND(HDDAct)
                      sum = sum + HDDAct(i)
                      sText = sText + "|" + STR$(HDDAct(i))
                  NEXT i
              LeaveCriticalSection(gLock)
              Mittel = ROUND(sum / UBOUND(HDDAct), 0)
              SLEEP 100
          LOOP UNTIL (Mittel < MaxHDD) OR (lResult = %IDOK)
      
          'Threads cleanup
          EnterCriticalSection(gLock)
              gKillThreads = %True
          LeaveCriticalSection(gLock)
          FOR i = 1 TO ObsDrvCount
              THREAD STATUS hThread(i) TO lState
              DO WHILE lState = &H103
                  SLEEP 100
                  THREAD STATUS hThread(i) TO lState
              LOOP
              THREAD CLOSE hThread(i) TO lState
          NEXT i
      
      
          IF Mittel < MaxHDD THEN
              MSGBOX "Stopped because of low disk activity: Hits/Min.:"+STR$(Mittel) + $CRLF + sText
          ELSE
              MSGBOX "User initiated stop: Hits/Min.:"+STR$(Mittel) + $CRLF + sText
          END IF
      
          DeleteCriticalSection(gLock)
          EXIT FUNCTION
      
      eOut:
          MSGBOX "Error occured:"+STR$(ERR) + " " + ERROR$(ERR)
          RESUME NEXT
      
      END FUNCTION
      I'am still confused...but on a higher level.

      Comment


      • #4
        monitor disk activity

        Here is some better code for diskmonitoring.
        For each disk to monitor a thread is created. The thread terminates as soon as disk activity is less the limit.
        Because of restriction to threaded function you have to pass the limit multiplied by 100 to the thread. Disk activity is measured disk access/minute for each disk. When the thread function terminates the last activity value is passed, so store it before you close the thread. If you want to use removable disk, be careful, check if a medium is inserted before you bring up the corresponding thread.

        Have fun with the code:
        Code:
        #COMPILE EXE
        #DIM ALL
        #INCLUDE "win32api.inc"
        
        
        'GLOBAL gLock        AS CRITICAL_SECTION
        GLOBAL gKillThreads AS LONG
        
        
        MACRO ActiveWait
            IF PeekMessage (MSG, %NULL, 0,0, %PM_REMOVE) THEN
                TranslateMessage MSG
                DispatchMessage MSG
            END IF
        END MACRO
        
        
        '-------------------------------------------------------------------------------
        ' Function  thDiskActivity
        '           threaded disk activity check
        '           thread ends up automatically when HDD activity decreases below limit
        ' in        DrvAct: drive to observe, 0=cancel/end, 1=A:, 2=B:,...
        '           DrvAct \ 100 => HDD-activity-limit (disk hits / minute)
        ' out       DrvAct: activity => THREAD STATUS
        '-------------------------------------------------------------------------------
        FUNCTION thDiskActivity(BYVAL DrvAct AS LONG) AS LONG
        
            ON ERROR GOTO EndThread
        
            LOCAL hDir      AS DWORD
            LOCAL ret       AS DWORD
            LOCAL drv       AS ASCIIZ * 4
            LOCAL t, td     AS QUAD
            LOCAL i         AS LONG
            LOCAL hitCount  AS LONG
            LOCAL MSG       AS tagMSG
            LOCAL HDDAct    AS LONG
            LOCAL HDDAct1   AS LONG
            LOCAL ActLimit  AS LONG
        
            'fill activity limits
            ActLimit    = DrvAct \ 100
            HDDAct      = ActLimit
            HDDAct1     = ActLimit
            'build drive letter
            drv = CHR$(DrvAct-HDDAct*100+64) + ":\"
            hitCount = 0
            MSGBOX "observing " + drv + " low-activity-limit:"+STR$(HDDAct)
        
            t = TIMER
            DO
                hDir = FindFirstChangeNotification(drv, %True, _
                        %FILE_NOTIFY_CHANGE_SIZE OR _
                        %FILE_NOTIFY_CHANGE_FILE_NAME OR _
                        %FILE_NOTIFY_CHANGE_DIR_NAME OR _
                        %FILE_NOTIFY_CHANGE_LAST_WRITE OR _
                        %FILE_NOTIFY_CHANGE_LAST_ACCESS OR _
                        %FILE_NOTIFY_CHANGE_CREATION)
                DO
                    ret = WaitForSingleObject(hDir, 200)
                    ActiveWait
                    td = TIMER - t
                    'EnterCriticalSection(gLock)
                    IF gKillThreads = %True OR HDDAct < ActLimit THEN
                        GOTO EndThread
                    END IF
                    IF td > 9 THEN
                        HDDAct1= HDDAct
                        HDDAct = (hitCount * 6 + HDDAct1) / 2
                        'MSGBOX "hitCount/HDD-activity per minute:"+STR$(hitCount)+" / "+STR$(HDDAct)
                        hitCount = 0
                        t = TIMER
                    END IF
                    'LeaveCriticalSection(gLock)
                LOOP WHILE ret <> 0
                DO
                    INCR hitCount
                    'EnterCriticalSection(gLock)
                    IF gKillThreads = %True OR HDDAct < ActLimit THEN
                        GOTO EndThread
                    END IF
                        'td = TIMER - t
                        'HDDAct1= HDDAct
                        'HDDAct = (hitCount * 6 + HDDAct1) / 2
                        'MSGBOX "change: hits="+STR$(hitCount)+" time="+STR$(td)+" / activity="+STR$(HDDAct)
        '                IF td > 9 THEN
        '                    hitCount = 0
        '                    t = TIMER
        '                END IF
                    'LeaveCriticalSection(gLock)
                    ret = FindNextChangeNotification(hDir)
                    ret = WaitForSingleObject(hDir, 200)
                    EXIT DO
                LOOP
                'ActiveWait
            LOOP
        
        EndThread:
            'LeaveCriticalSection(gLock)
            ret = FindCloseChangeNotification( hDir )
            'msgbox drv + " Thread terminated regularily. HDDAct="+str$(HDDAct)
            FUNCTION = HDDAct
        
        
        END FUNCTION
        
        
        
        '-----------------------------------------------------------------------
        ' Function  GetLocalDrives
        '           retrieve all local attached driveletters as one string
        '           you can add a filter with one or more elements (use OR)
        ' in        optional Filter, Filter2, Filter3, Filter4, Filter5
        '           %DRIVE_REMOVABLE The drive can be removed from the drive.
        '           %DRIVE_FIXED     The disk cannot be removed from the drive.
        '           %DRIVE_REMOTE    The drive is a remote (network) drive.
        '           %DRIVE_CDROM     The drive is a CD-ROM drive.
        '           %DRIVE_RAMDISK   The drive is a RAM disk.
        ' out       string with driveletters
        '------------------------------------------------------------------------
        FUNCTION GetAllDrivesString(OPT BYVAL Filter AS LONG, _
                                OPT BYVAL Filter2 AS LONG, _
                                OPT BYVAL Filter3 AS LONG, _
                                OPT BYVAL Filter4 AS LONG, _
                                OPT BYVAL Filter5 AS LONG) AS STRING
        
            LOCAL i             AS LONG
            LOCAL buffer        AS STRING
            LOCAL chz           AS ASCIIZ * 3
            LOCAL ch            AS STRING
            LOCAL AllDrives     AS STRING
            LOCAL FilterDrives  AS STRING
            LOCAL ret           AS LONG
            LOCAL nResult       AS LONG
        
            ret = GetLogicalDriveStrings(0, BYVAL %Null)
            buffer = STRING$(ret, $NUL)
            nResult = GetLogicalDriveStrings( ret, BYVAL STRPTR(buffer))
            AllDrives = REMOVE$( buffer, ANY ":\"+CHR$(0))
            IF Filter = 0 THEN
                FUNCTION = AllDrives
            ELSE
                ret = LEN(AllDrives)
                FOR i = 1 TO ret
                    ch = MID$(AllDrives,i,1)
                    chz= ch + ":"
                    ret = GetDriveType(chz)
                    IF ret > 1 AND (ret = Filter OR ret = Filter2 OR ret = Filter3 OR ret = Filter4 OR ret = Filter5) THEN
                        FilterDrives = FilterDrives + ch
                    END IF
                NEXT i
                FUNCTION = FilterDrives
            END IF
        
        END FUNCTION
        
        
        '###############################################################################
        FUNCTION PBMAIN() AS LONG
        
            ON ERROR GOTO eOut
        
            LOCAL hThread()     AS LONG
            LOCAL lState()      AS LONG
            LOCAL lResult       AS LONG
            LOCAL i, sum        AS LONG
            LOCAL Mittel        AS LONG
            LOCAL sText         AS STRING
            LOCAL ObsDrv        AS STRING
            LOCAL ObsDrvCount   AS LONG
            LOCAL elem          AS STRING
            LOCAL DrvNr         AS LONG
            LOCAL MaxHDD        AS LONG
        
        
            DIM hThread(1 TO 26)
            DIM lState( 1 TO 26)
        
            'ObsDrv = GetAllDrivesString(%DRIVE_FIXED)
            ObsDrv = "C"
            ObsDrvCount = LEN(ObsDrv)
            MaxHDD= 15                                      'max. disk changes/minute
        
            'bring up threads
            FOR i = 1 TO ObsDrvCount
                elem = MID$(ObsDrv,i,1)
                DrvNr = ASC(elem)-64 + MaxHDD * 100
                THREAD CREATE thDiskActivity(DrvNr) TO hThread(i)
            NEXT i
            SLEEP 100
            'lResult = MSGBOX("Überwachung beenden mit OK.", %MB_OK, "Observing Disk "+CHR$(DrvNr)+":")
        
        
            'Wait until threads ended regular
            sum = 0
            FOR i = 1 TO ObsDrvCount
                THREAD STATUS hThread(i) TO lState(i)
                DO WHILE lState(i) = &H103
                    SLEEP 100
                    THREAD STATUS hThread(i) TO lState(i)
                LOOP
                THREAD STATUS hThread(i) TO lState(i)
                sum = sum + lState(i)
                THREAD CLOSE hThread(i) TO lResult
            NEXT i
            Mittel = sum / ObsDrvCount
        
            IF Mittel < MaxHDD THEN
                MSGBOX "Stopped because of low disk activity: Hits/Min.:"+STR$(Mittel) + $CRLF + sText
            ELSE
                MSGBOX "User initiated stop: Hits/Min.:"+STR$(Mittel) + $CRLF + sText
            END IF
        
            'DeleteCriticalSection(gLock)
            EXIT FUNCTION
        
        eOut:
            MSGBOX "Error occured:"+STR$(ERR) + " " + ERROR$(ERR)
            RESUME NEXT
        
        END FUNCTION
        I'am still confused...but on a higher level.

        Comment

        Working...
        X