Package org.rzo.yajsw.os.ms.win.w32

Source Code of org.rzo.yajsw.os.ms.win.w32.Cluster$ClusterGroupInfo

package org.rzo.yajsw.os.ms.win.w32;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.rzo.yajsw.os.ms.win.w32.Cluster.Clusapi.ClusterGroupState;
import org.rzo.yajsw.os.ms.win.w32.WindowsXPProcess.MyKernel32;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.ptr.IntByReference;

public class Cluster
{
  static Logger  _log    = Logger.getLogger(Cluster.class.getCanonicalName());
  ExecutorService  threadPool  = Executors.newSingleThreadExecutor();

  public interface Clusapi extends com.sun.jna.win32.StdCallLibrary
  {
    Clusapi  INSTANCE  = (Clusapi) Native.loadLibrary("ClusApi", Clusapi.class);

    /*
     * HCLUSTER WINAPI OpenCluster( __in_opt LPCWSTR lpszClusterName );
     */
    Pointer OpenCluster(WString lpszClusterName);

    /*
     * BOOL WINAPI CloseCluster( __in HCLUSTER hCluster );
     */
    boolean CloseCluster(Pointer hCluster);

    /*
     * HCHANGE WINAPI CreateClusterNotifyPort( __in HCHANGE hChange, __in
     * HCLUSTER hCluster, __in DWORD dwFilter, __in DWORD_PTR dwNotifyKey );
     */
    Pointer CreateClusterNotifyPort(Pointer hChange, Pointer hCluster, int dwFilter, IntByReference dwNotifyKey);

    final static int  CLUSTER_CHANGE_GROUP_STATE      = 0x00001000;
    final static int  CLUSTER_CHANGE_HANDLE_CLOSE      = 0x80000000;
    final static int  CLUSTER_CHANGE_CLUSTER_RECONNECT  = 0x00080000;
    final static int  CLUSTER_CHANGE_CLUSTER_STATE    = 0x20000000;
    final static int  CLUSTER_CHANGE_GROUP_DELETED    = 0x00002000;
    final static int  CLUSTER_CHANGE_GROUP_ADDED      = 0x00004000;

    // Results
    final static int  WAIT_TIMEOUT            = 0x102;
    final static int  ERROR_SUCCESS            = 0x0;
    final static int  ERROR_NO_MORE_ITEMS          = 0x103;

    // GetClusterGroupState results
    final static int  CLUSTER_GROUP_STATE_UNKNOWN      = -1;
    final static int  CLUSTER_GROUP_ONLINE        = 0;
    final static int  CLUSTER_GROUP_OFFLINE        = 1;
    final static int  CLUSTER_GROUP_FAILED        = 2;
    final static int  CLUSTER_GROUP_PARTIAL_ONLINE    = 3;
    final static int  CLUSTER_GROUP_PENDING        = 4;

    enum ClusterGroupState
    {
      Unknown, Online, Offline, Failed, PartialOnline, Pending;
      public static ClusterGroupState parse(int val)
      {
        switch (val)
        {
        case CLUSTER_GROUP_STATE_UNKNOWN:
          return Unknown;
        case CLUSTER_GROUP_ONLINE:
          return Online;
        case CLUSTER_GROUP_OFFLINE:
          return Offline;
        case CLUSTER_GROUP_FAILED:
          return Failed;
        case CLUSTER_GROUP_PARTIAL_ONLINE:
          return PartialOnline;
        case CLUSTER_GROUP_PENDING:
          return Pending;
        default:
          _log.severe("unknown cluster state: " + val);
          return Unknown;
        }
      }
    }

    /*
     * DWORD WINAPI GetClusterNotify( __in HCHANGE hChange, __out DWORD_PTR
     * *lpdwNotifyKey, __out LPDWORD lpdwFilterType, __out LPWSTR lpszName,
     * __inout LPDWORD lpcchName, __in_opt DWORD dwMilliseconds );
     */
    int GetClusterNotify(Pointer hChange, IntByReference lpdwNotifyKey, IntByReference lpdwFilterType, Memory lpszName, IntByReference lpcchName,
        int dwMilliseconds);

    /*
     * BOOL WINAPI CloseClusterNotifyPort( __in HCHANGE hChange );
     */
    boolean CloseClusterNotifyPort(Pointer hChange);

    /*
     * HNODE WINAPI OpenClusterNode( __in HCLUSTER hCluster, __in LPCWSTR
     * lpszNodeName );
     */
    Pointer OpenClusterNode(Pointer hCluster, WString lpszNodeName);

    /*
     * BOOL WINAPI CloseClusterNode( __in HNODE hNode );
     */
    boolean CloseClusterNode(Pointer hNode);

    /*
     * CLUSTER_NODE_STATE WINAPI GetClusterNodeState( __in HNODE hNode );
     */
    int GetClusterNodeState(Pointer hNode);

    /*
     * HCLUSENUM WINAPI ClusterOpenEnum( __in HCLUSTER hCluster, __in DWORD
     * dwType );
     */
    Pointer ClusterOpenEnum(Pointer hCluster, int dwType);

    Pointer ClusterNodeOpenEnum(Pointer hNode, int dwType);

    static int  CLUSTER_ENUM_NODE      = 1;
    static int  CLUSTER_ENUM_RESOURCE    = 4;
    static int  CLUSTER_ENUM_NETINTERFACE  = 32;
    static int  CLUSTER_ENUM_GROUP      = 8;

    /*
     * DWORD WINAPI ClusterCloseEnum( __in HCLUSENUM hEnum );
     */
    int ClusterCloseEnum(Pointer hEnum);

    /*
     * DWORD WINAPI ClusterEnum( __in HCLUSENUM hEnum, __in DWORD dwIndex,
     * __out LPDWORD lpdwType, __out LPWSTR lpszName, __inout LPDWORD
     * lpcchName );
     */
    int ClusterEnum(Pointer hEnum, int dwIndex, IntByReference lpdwType, Memory lpszName, IntByReference lpcchName);

    int ClusterNodeEnum(Pointer hEnum, int dwIndex, IntByReference lpdwType, Memory lpszName, IntByReference lpcchName);

    /*
     * HRESOURCE WINAPI OpenClusterResource( __in HCLUSTER hCluster, __in
     * LPCWSTR lpszResourceName );
     */
    Pointer OpenClusterResource(Pointer hCluster, WString lpszResourceName);

    /*
     * HGROUP WINAPI OpenClusterGroup( __in HCLUSTER hCluster, __in LPCWSTR
     * lpszGroupName );
     */
    Pointer OpenClusterGroup(Pointer hCluster, WString lpszGroupName);

    /*
     * CLUSTER_GROUP_STATE WINAPI GetClusterGroupState( __in HGROUP hGroup,
     * __out_opt LPWSTR lpszNodeName, __inout_opt LPDWORD lpcchNodeName );
     */
    int GetClusterGroupState(Pointer hGroup, Memory lpszNodeName, IntByReference lpcchNodeName);
  }

  ArrayList<ClusterNodeChangeListener>  _listeners  = new ArrayList<ClusterNodeChangeListener>();
  boolean                  _stopped  = true;

  public String getActiveNode()
  {
    String activeNode = null;

    try
    {
      Pointer cluster = Clusapi.INSTANCE.OpenCluster(null);
      Pointer hEnum = Clusapi.INSTANCE.ClusterOpenEnum(cluster, Clusapi.CLUSTER_ENUM_GROUP);
      int dwIndex = 0;
      IntByReference lpdwType = new IntByReference();
      IntByReference lpcchName = new IntByReference();
      Memory lpszName = new Memory(256);
      lpszName.clear();
      lpcchName.setValue(256);
      int result = 0;
      do
      {
        result = Clusapi.INSTANCE.ClusterEnum(hEnum, dwIndex, lpdwType, lpszName, lpcchName);
        if (result == Clusapi.ERROR_SUCCESS)
        {
          String group = lpszName.getString(0, true);
          ClusterGroupInfo info = getGroupNodeInfo(cluster, group);
          if (info != null)
            activeNode = info.getLocation();
        }
        dwIndex++;
      }
      while (result == 0);
    }
    catch (Exception ex)
    {
      _log.log(Level.SEVERE, "Error getting cluster information", ex);
    }
    return activeNode;
  }

  private ClusterGroupInfo getGroupNodeInfo(Pointer cluster, String groupName)
  {
    ClusterGroupInfo result = null;
    try
    {
      Pointer hGroup = Clusapi.INSTANCE.OpenClusterGroup(cluster, new WString(groupName));

      if (hGroup == null)
        throw new RuntimeException("Clusapi call to OpenClusterGroup returned err code " + MyKernel32.INSTANCE.GetLastError());

      IntByReference lpcchNodeName = new IntByReference();
      Memory lpszNodeName = new Memory(256);
      lpszNodeName.clear();
      lpcchNodeName.setValue(256);

      int state = Clusapi.INSTANCE.GetClusterGroupState(hGroup, lpszNodeName, lpcchNodeName);
      String location = lpszNodeName.getString(0, true);

      if (state == Clusapi.CLUSTER_GROUP_STATE_UNKNOWN)
        _log.severe("unknown group state for group " + groupName + " err code " + MyKernel32.INSTANCE.GetLastError());

      result = new ClusterGroupInfo(groupName, state, location);

      MyKernel32.INSTANCE.CloseHandle(hGroup);
    }
    catch (Exception e)
    {
      _log.log(Level.SEVERE, "Error while getting GroupActiveNode", e);
    }
    return result;
  }

  public Set<ClusterGroupInfo> getGroupInfo()
  {
    Pointer hCluster = Clusapi.INSTANCE.OpenCluster(null);
    if (hCluster == null)
      throw new RuntimeException("Clusapi call to OpenClusterGroup returned err code " + MyKernel32.INSTANCE.GetLastError());

    Pointer hEnum = Clusapi.INSTANCE.ClusterOpenEnum(hCluster, Clusapi.CLUSTER_ENUM_GROUP);
    if (hEnum == null)
      throw new RuntimeException("Clusapi call to ClusterOpenEnum returned err code " + MyKernel32.INSTANCE.GetLastError());

    Set<ClusterGroupInfo> result = new LinkedHashSet<ClusterGroupInfo>();

    try
    {
      IntByReference lpdwType = new IntByReference();
      IntByReference lpcchName = new IntByReference(0);
      Memory lpszName = new Memory(256);

      int dwIndex = 0;

      int returnValue = 0;
      do
      {
        lpdwType.setValue(0);
        lpcchName.setValue(0);
        lpszName.clear();
        lpcchName.setValue(256);

        returnValue = Clusapi.INSTANCE.ClusterEnum(hEnum, dwIndex, lpdwType, lpszName, lpcchName);

        if (returnValue == Clusapi.ERROR_SUCCESS)
        {
          String group = lpszName.getString(0, true);
          ClusterGroupInfo info = getGroupNodeInfo(hCluster, group);
          if (info != null)
            result.add(info);
        }

        if ((returnValue != Clusapi.ERROR_NO_MORE_ITEMS) && (returnValue != Clusapi.ERROR_SUCCESS))
          _log.log(Level.SEVERE, "strange returnValue from ClusApi" + returnValue);

        dwIndex++;
      }
      while (returnValue == 0);
    }
    catch (Exception e)
    {
      _log.log(Level.SEVERE, "Error while getting Cluster group information", e);
    }
    finally
    {
      MyKernel32.INSTANCE.CloseHandle(hEnum);
      MyKernel32.INSTANCE.CloseHandle(hCluster);
    }
    return result;
  }

  public void start()
  {
    Runnable check = null;
    synchronized (this)
    {
      if (_stopped)
      {
        check = new Runnable()
        {
          public void run()
          {
            IntByReference lpdwNotifyKey = new IntByReference();
            IntByReference lpdwFilterType = new IntByReference();
            IntByReference lpcchName = new IntByReference();
            IntByReference dwNotifyKey = new IntByReference();
            Memory lpszName = new Memory(256);
            Pointer minusOne = Pointer.createConstant(-1);
            int dwMilliseconds = 300 * 1000;
            final int dwFilter = Clusapi.CLUSTER_CHANGE_GROUP_STATE | Clusapi.CLUSTER_CHANGE_HANDLE_CLOSE
                | Clusapi.CLUSTER_CHANGE_GROUP_DELETED | Clusapi.CLUSTER_CHANGE_CLUSTER_STATE
                | Clusapi.CLUSTER_CHANGE_CLUSTER_RECONNECT | Clusapi.CLUSTER_CHANGE_GROUP_ADDED;

            while (!_stopped)
            {
              Pointer hCluster = null;
              Pointer hChange = null;

              long started = System.currentTimeMillis();

              try
              {
                lpdwNotifyKey.setValue(0);
                lpdwFilterType.setValue(0);
                lpcchName.setValue(0);
                dwNotifyKey.setValue(0);
                lpszName.clear();
                lpcchName.setValue(256);

                hCluster = Clusapi.INSTANCE.OpenCluster(null);
                if (hCluster == null)
                  _log.severe("ClusApi.OpenCluster returned err code " + MyKernel32.INSTANCE.GetLastError());
                else
                {
                  hChange = Clusapi.INSTANCE.CreateClusterNotifyPort(minusOne, hCluster, dwFilter, dwNotifyKey);
                  if (hChange == null)
                    _log.severe("ClusApi.CreateClusterNotifyPort returned err code " + MyKernel32.INSTANCE.GetLastError());
                }

                if (hCluster == null || hChange == null)
                  Thread.sleep(5000);
                else
                {
                  int result = Clusapi.INSTANCE.GetClusterNotify(hChange, lpdwNotifyKey, lpdwFilterType, lpszName, lpcchName,
                      dwMilliseconds);

                  if (result == Clusapi.ERROR_SUCCESS)
                    doListeners(null, lpdwFilterType.getValue(), lpszName.getString(0, true));
                  else if (result != Clusapi.WAIT_TIMEOUT) // 258
                                        // =
                                        // Wait
                                        // Time
                                        // Out
                    _log.warning("ClusApi.GetClusterNotify result=" + result);
                }
              }
              catch (Throwable e)
              {
                _log.log(Level.SEVERE, "Error getting ClusterInformation", e);
              }
              finally
              {
                _log.info("check cluster took " + (System.currentTimeMillis() - started) + " ms");
                if (hChange != null)
                {
                  try
                  {
                    Clusapi.INSTANCE.CloseClusterNotifyPort(hChange);
                  }
                  catch (Throwable e2)
                  {
                    e2.printStackTrace();
                  }

                  MyKernel32.INSTANCE.CloseHandle(hChange);
                }

                if (hCluster != null)
                  MyKernel32.INSTANCE.CloseHandle(hCluster);
              }
            }
          }
        };
        _stopped = false;
      }
    }
    new Thread(check, "cluster listener thread").start();
  }

  private void doListeners(String activeNode, int lpdwFilterType, String lpszName)
  {
    // LOGGING
    try
    {
      switch (lpdwFilterType)
      {
      case Clusapi.CLUSTER_CHANGE_GROUP_ADDED:
        _log.severe("cluster group added: " + lpszName);
        break;

      case Clusapi.CLUSTER_CHANGE_GROUP_DELETED:
        _log.severe("cluster group deleted: " + lpszName);
        break;

      case Clusapi.CLUSTER_CHANGE_GROUP_STATE:
        _log.severe("cluster group state changed: " + lpszName);
        break;

      case Clusapi.CLUSTER_CHANGE_HANDLE_CLOSE:
        _log.severe("The queue receives a notification when a handle associated with a cluster object is closed. " + lpszName);
        break;

      case Clusapi.CLUSTER_CHANGE_CLUSTER_RECONNECT:
        _log.severe("The queue receives a notification when the connection to the cluster "
            + "identified by hCluster is reestablished after a brief disconnect. Some events "
            + "generated immediately before or after this event may have been lost. val=" + lpszName);
        break;

      case Clusapi.CLUSTER_CHANGE_CLUSTER_STATE:
        _log.severe("all attempts to communicate with the cluster failed, val=" + lpszName);
        break;

      default:
        _log.severe("unknown event id=" + Integer.toHexString(lpdwFilterType) + ", val=" + lpszName);
        break;
      }
    }
    catch (Throwable e)
    {
      _log.log(Level.SEVERE, "Error in Cluster Logging", e);
    }

    threadPool.execute(new Runnable()
    {
      public void run()
      {
        ArrayList<ClusterNodeChangeListener> listeners = new ArrayList<ClusterNodeChangeListener>();
        synchronized (_listeners)
        {
          listeners.addAll(_listeners);
        }

        for (ClusterNodeChangeListener l : listeners)
          try
          {
            l.nodeChanged();
          }
          catch (Throwable e)
          {
            _log.log(Level.SEVERE, "Error in ClusterNodeChangeListener.nodeChanged()", e);
          }
      }
    });
  }

  public void addNodeChangeListener(ClusterNodeChangeListener listener)
  {
    synchronized (_listeners)
    {
      _listeners.add(listener);
    }
  }

  public void stop()
  {
    _stopped = true;
  }

  public static void main(String[] args) throws UnknownHostException
  {
    final Cluster c = new Cluster();
    c.addNodeChangeListener(new ClusterNodeChangeListener()
    {
      public void nodeChanged()
      {
        try
        {
          System.out.println("new GroupInfo" + c.getGroupInfo());
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
    c.start();
    try
    {
      Thread.sleep(Integer.MAX_VALUE);
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
  }

  public class ClusterGroupInfo
  {
    final private String  _groupName;
    final private String  _location;
    ClusterGroupState    _state  = ClusterGroupState.Unknown;

    public ClusterGroupInfo(String groupName, int state, String location)
    {
      _groupName = groupName;
      _location = location;
      _state = ClusterGroupState.parse(state);
    }

    public String getGroupName()
    {
      return _groupName;
    }

    public String getLocation()
    {
      return _location;
    }

    public ClusterGroupState getState()
    {
      return _state;
    }

    public boolean equals(ClusterGroupInfo info)
    {
      if (super.equals(info))
        return true;

      if (StringUtils.equals(_location, info._location) && StringUtils.equals(_groupName, info._groupName) && _state == info._state)
        return true;

      return false;
    }

    @Override
    public String toString()
    {
      return _groupName + "(" + _state + ", " + _location + ")";
    }
  }
}
TOP

Related Classes of org.rzo.yajsw.os.ms.win.w32.Cluster$ClusterGroupInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.