// $Id: WindowsMultiInstanceMonitor.cpp 81693 2008-05-14 12:35:01Z johnnyw $

#include "ace/MonitorControl/WindowsMultiInstanceMonitor.h"

#if defined (ACE_HAS_WIN32_PDH)

#include "ace/Log_Msg.h"
#include "ace/SString.h"
#include "ace/os_include/os_pdhmsg.h"

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

namespace ACE
{
  namespace Monitor_Control
  {
    WindowsMultiInstanceMonitor::WindowsMultiInstanceMonitor (
      const ACE_TCHAR *wildcard_path)
      : instances_ (0),
        n_instances_ (0),
        status_ (ERROR_SUCCESS)
    {
      this->value_.doubleValue = 0.0;

      /// Create a string which is a concatentation of the path
      /// name of each 'instance' we need to monitor.

      DWORD paths_size = 4096;
      ACE_LPSTR paths = (ACE_LPSTR) GlobalAlloc (GPTR, paths_size);

      this->status_ = ACE_TEXT_PdhExpandCounterPath (wildcard_path,
                                                     paths,
                                                     &paths_size);

      if (PDH_MORE_DATA == static_cast<DWORD> (this->status_))
        {
          ++paths_size;
          GlobalFree (paths);
          paths = (ACE_LPSTR) GlobalAlloc (GPTR, paths_size);

          this->status_ = ACE_TEXT_PdhExpandCounterPath (wildcard_path,
                                                         paths,
                                                         &paths_size);
        }

      if (PDH_CSTATUS_VALID_DATA != static_cast<DWORD> (this->status_))
        {
          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("%s: PdhExpandCounterPath failed\n"),
                      wildcard_path));
        }

      ACE_LPSTR path = paths;
      int index = 0;

      /// Create a regular Windows monitor for each path name.
      while (*path != 0)
        {
          WindowsMonitor *instance = new WindowsMonitor (path);
          this->instances_.enqueue_tail (instance);
          path += lstrlen (path) + 1;
        }

      GlobalFree (paths);
    }

    WindowsMultiInstanceMonitor::~WindowsMultiInstanceMonitor (void)
    {
      WindowsMonitor *instance = 0;

      /// Destroy the single instance monitors created in the constructor.
      while (this->instances_.dequeue_head (instance) == 0)
        {
          delete instance;
        }
    }

    void
    WindowsMultiInstanceMonitor::win_update (void)
    {
      WindowsMonitor **current_instance = 0;

      /// Sum the values of each single instance monitor.
      for (INSTANCES_ITERATOR i (this->instances_); !i.done (); i.advance ())
        {
          i.next (current_instance);

          (*current_instance)->win_update ();

          this->value_.doubleValue +=
            (*current_instance)->value_.doubleValue;
        }
    }
  }
}

ACE_END_VERSIONED_NAMESPACE_DECL

#endif /* defined (ACE_HAS_WIN32_PDH) */
