Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cmanager_win32.py   Sprache: Python

 
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import struct
from ctypes import (
    Structure,
    Union,
    byref,
    c_double,
    c_longlong,
    create_string_buffer,
    memmove,
    pointer,
    windll,
)
from ctypes.wintypes import DWORD, HANDLE, LONG, LPCSTR, LPCWSTR, LPSTR

import six

from talos.cmanager_base import CounterManager
from talos.utils import TalosError

pdh = windll.pdh

_LONGLONG = c_longlong


class _PDH_COUNTER_PATH_ELEMENTS_A(Structure):
    _fields_ = [
        ("szMachineName", LPSTR),
        ("szObjectName", LPSTR),
        ("szInstanceName", LPSTR),
        ("szParentInstance", LPSTR),
        ("dwInstanceIndex", DWORD),
        ("szCounterName", LPSTR),
    ]


_PDH_MORE_DATA = -2147481646  # the need more space error


def _getExpandedCounterPaths(processName, counterName):
    """
    Get list of expanded counter paths given a counter name. Returns a
    list of strings or Noneif no counter paths can be created
    """
    pcchPathListLength = DWORD(0)
    szWildCardPath = LPSTR("\\process(%s)\\%s" % (processName, counterName))
    if (
        pdh.PdhExpandCounterPathA(
            szWildCardPath, LPSTR(None), pointer(pcchPathListLength)
        )
        != _PDH_MORE_DATA
    ):
        return []

    pathListLength = pcchPathListLength.value
    szExpandedPathList = LPCSTR("\0" * pathListLength)
    if (
        pdh.PdhExpandCounterPathA(
            szWildCardPath, szExpandedPathList, pointer(pcchPathListLength)
        )
        != 0
    ):
        return []
    buffer = create_string_buffer(pcchPathListLength.value)
    memmove(buffer, szExpandedPathList, pcchPathListLength.value)

    paths = []
    i = 0
    path = ""
    for j in six.moves.range(0, pcchPathListLength.value):
        c = struct.unpack_from("c", buffer, offset=j)[0]
        if c == "\0":
            if j == i:
                # double null: we're done
                break
            paths.append(path)
            path = ""
            i = j + 1
        else:
            path += c

    return paths


class _PDH_Counter_Union(Union):
    _fields_ = [
        ("longValue", LONG),
        ("doubleValue", c_double),
        ("largeValue", _LONGLONG),
        ("AnsiStringValue", LPCSTR),
        ("WideStringValue", LPCWSTR),
    ]


class _PDH_FMT_COUNTERVALUE(Structure):
    _fields_ = [("CStatus", DWORD), ("union", _PDH_Counter_Union)]


_PDH_FMT_LONG = 0x00000100


class WinCounterManager(CounterManager):
    def __init__(
        self, process_name, process, counters, childProcess="plugin-container"
    ):
        CounterManager.__init__(self)
        self.childProcess = childProcess
        self.registeredCounters = {}
        self.registerCounters(counters)
        # PDH might need to be "refreshed" if it has been queried while the
        # browser is closed
        pdh.PdhEnumObjectsA(NoneNone, 0, 1, 0, True)

        for counter in self.registeredCounters:
            try:
                # Add the counter path for the default process.
                self._addCounter(process_name, "process", counter)
            except TalosError:
                # Assume that this is a memory counter for the system,
                # not a process counter
                # If we got an error that has nothing to do with that,
                # the exception will almost certainly be re-raised
                self._addCounter(process_name, "Memory", counter)

            self._updateCounterPathsForChildProcesses(counter)

    def _addCounter(self, processName, counterType, counterName):
        pCounterPathElements = _PDH_COUNTER_PATH_ELEMENTS_A(
            LPSTR(None),
            LPSTR(counterType),
            LPSTR(processName),
            LPSTR(None),
            DWORD(-1),
            LPSTR(counterName),
        )

        pcchbufferSize = DWORD(0)

        # First run we just try to get the buffer size so we can allocate a
        # string big enough to fill it
        if (
            pdh.PdhMakeCounterPathA(
                pointer(pCounterPathElements),
                LPCSTR(0),
                pointer(pcchbufferSize),
                DWORD(0),
            )
            != _PDH_MORE_DATA
        ):
            raise TalosError(
                "Could not create counter path for counter %s for %s"
                % (counterName, processName)
            )

        szFullPathBuffer = LPCSTR("\0" * pcchbufferSize.value)
        # Then we run to get the actual value
        if (
            pdh.PdhMakeCounterPathA(
                pointer(pCounterPathElements),
                szFullPathBuffer,
                pointer(pcchbufferSize),
                DWORD(0),
            )
            != 0
        ):
            raise TalosError(
                "Could not create counter path for counter %s for %s"
                % (counterName, processName)
            )

        path = szFullPathBuffer.value

        hq = HANDLE()
        if pdh.PdhOpenQuery(NoneNone, byref(hq)) != 0:
            raise TalosError("Could not open win32 counter query")

        hc = HANDLE()
        if pdh.PdhAddCounterA(hq, path, 0, byref(hc)) != 0:
            raise TalosError("Could not add win32 counter %s" % path)

        self.registeredCounters[counterName] = [hq, [(hc, path)]]

    def registerCounters(self, counters):
        # self.registeredCounters[counter][0] is a counter query handle
        # self.registeredCounters[counter][1] is a list of tuples, the first
        # member of which is a counter handle, the second a counter path
        for counter in counters:
            # Main_RSS is collected inside of pageloader
            if counter.strip() == "Main_RSS":
                continue

            # mainthread_io is collected from the browser via environment
            # variables
            if counter.strip() == "mainthread_io":
                continue

            self.registeredCounters[counter] = []

    def _updateCounterPathsForChildProcesses(self, counter):
        # Create a counter path for each instance of the child process that
        # is running.  If any of these paths are not in our counter list,
        # add them to our counter query and append them to the counter list,
        # so that we'll begin tracking their statistics.  We don't need to
        # worry about removing invalid paths from the list, as
        # getCounterValue() will generate a value of 0 for those.
        hq = self.registeredCounters[counter][0]
        oldCounterListLength = len(self.registeredCounters[counter][1])

        pdh.PdhEnumObjectsA(NoneNone, 0, 1, 0, True)

        expandedPaths = _getExpandedCounterPaths(self.childProcess, counter)
        if not expandedPaths:
            return
        for expandedPath in expandedPaths:
            alreadyInCounterList = False
            for singleCounter in self.registeredCounters[counter][1]:
                if expandedPath == singleCounter[1]:
                    alreadyInCounterList = True
            if not alreadyInCounterList:
                try:
                    newhc = HANDLE()
                    if pdh.PdhAddCounterA(hq, expandedPath, 0, byref(newhc)) != 0:
                        raise TalosError(
                            "Could not add expanded win32 counter %s" % expandedPath
                        )
                    self.registeredCounters[counter][1].append((newhc, expandedPath))
                except Exception:
                    continue

        if oldCounterListLength != len(self.registeredCounters[counter][1]):
            pdh.PdhCollectQueryData(hq)

    def getCounterValue(self, counter):
        # Update counter paths, to catch any new child processes that might
        # have been launched since last call.  Then iterate through all
        # counter paths for this counter, and return a combined value.
        if counter not in self.registeredCounters:
            return None

        if self.registeredCounters[counter] == []:
            return None

        self._updateCounterPathsForChildProcesses(counter)
        hq = self.registeredCounters[counter][0]

        # we'll just ignore the return value here, in case no counters
        # are valid anymore
        pdh.PdhCollectQueryData(hq)

        aggregateValue = 0
        for singleCounter in self.registeredCounters[counter][1]:
            hc = singleCounter[0]
            dwType = DWORD(0)
            value = _PDH_FMT_COUNTERVALUE()

            # if we can't get a value, just assume a value of 0
            if (
                pdh.PdhGetFormattedCounterValue(
                    hc, _PDH_FMT_LONG, byref(dwType), byref(value)
                )
                == 0
            ):
                aggregateValue += value.union.longValue

        return aggregateValue

Messung V0.5
C=88 H=85 G=86

¤ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge