Announcement

Collapse
No announcement yet.

monitor disk activy in total

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

  • Michael Zimmer
    replied
    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

    Leave a comment:


  • Michael Zimmer
    replied
    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

    Leave a comment:


  • Michael Mattias
    replied
    "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.

    Leave a comment:


  • Michael Zimmer
    started a topic monitor disk activy in total

    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.
Working...
X