/**
   * Get a list of "other" vms, along with stop modes. The "other" vms are any vms other than the
   * currently executing vm. The stop mode for each VM is chosen from util.StopStartPrms.stopMode.
   *
   * @param numVMsToTarget The number of VMs to target for a stop/start.
   * @param clientMatchStr A string the must be contained in the client name to be included in the
   *     vms to target, or null.
   * @throws TestException if there aren't numToTarget VMs available.
   * @returns Object[0] - a List of ClientVmInfos. Object[1] - a List of stop modes. Object[2] - a
   *     List of vms eligible but not chosen.
   */
  public static Object[] getOtherVMs(int numToTarget, String clientMatchStr) {
    Log.getLogWriter().info("Choosing " + numToTarget + " vms (other than this one)");
    // get the VMs; vmList and stopModeList are parallel lists
    ArrayList vmList = new ArrayList();
    ArrayList stopModeList = new ArrayList();
    int myVmID = RemoteTestModule.getMyVmid();

    // get VMs that contain the clientMatchStr
    List vmInfoList = getAllVMs();
    vmInfoList = getMatchVMs(vmInfoList, clientMatchStr);

    // now all vms in vmInfoList match the clientMatchStr
    do {
      if (vmInfoList.size() == 0) {
        throw new TestException(
            "Unable to find "
                + numToTarget
                + " vms to stop with client match string "
                + clientMatchStr
                + "; either a test problem or add StopStartVMs.StopStart_initTask to the test");
      }
      // add a VmId to the list of vms to stop
      int randInt = TestConfig.tab().getRandGen().nextInt(0, vmInfoList.size() - 1);
      ClientVmInfo info = (ClientVmInfo) (vmInfoList.get(randInt));
      if (info.getVmid().intValue() != myVmID) { // info is not the current VM
        vmList.add(info);

        // choose a stopMode
        String choice = TestConfig.tab().stringAt(StopStartPrms.stopModes);
        stopModeList.add(choice);
      }
      vmInfoList.remove(randInt);
    } while (vmList.size() < numToTarget);
    return new Object[] {vmList, stopModeList, vmInfoList};
  }
  /**
   * Get a list of "other" vms, along with stop modes. The "other" vms are any vms other than the
   * currently executing vm. The stop mode for each VM is chosen from util.StopStartPrms.stopMode.
   *
   * @param numVMsToTarget The number of VMs to target for a stop/start.
   * @param clientExcludeStr Any vm name that contains this string as a substring is excluded from
   *     consideration.
   * @throws TestException if there aren't numToTarget VMs available.
   * @returns Object[0] - a List of ClientVmInfos. Object[1] - a List of stop modes. Object[2] - a
   *     List of vms eligible but not chosen.
   */
  public static Object[] getOtherVMsWithExclude(int numToTarget, String clientExcludeStr) {
    Log.getLogWriter().info("Choosing " + numToTarget + " vms (other than this one)");
    // get the VMs; vmList and stopModeList are parallel lists
    ArrayList vmList = new ArrayList();
    ArrayList stopModeList = new ArrayList();
    int myVmID = RemoteTestModule.getMyVmid();

    // put numToTarget in vmList
    List vmInfoList = getAllVMs();
    do {
      if (vmInfoList.size() == 0) {
        throw new TestException(
            "Unable to find "
                + numToTarget
                + " vms to stop with client exclude string "
                + clientExcludeStr
                + "; either a test problem or add StopStartVMs.StopStart_initTask to the test");
      }
      // add a VmId to the list of vms to stop
      int randInt = TestConfig.tab().getRandGen().nextInt(0, vmInfoList.size() - 1);
      Object anObj = vmInfoList.get(randInt);
      if (anObj instanceof ClientVmInfo) {
        ClientVmInfo info = (ClientVmInfo) (anObj);
        if (info.getVmid().intValue() != myVmID) { // info is not the current VM
          if ((clientExcludeStr != null) && (info.getClientName().indexOf(clientExcludeStr) >= 0)) {
            // exclude this vm
          } else {
            vmList.add(info);

            // choose a stopMode
            String choice = TestConfig.tab().stringAt(StopStartPrms.stopModes);
            stopModeList.add(choice);
          }
        }
      }
      vmInfoList.remove(randInt);
    } while (vmList.size() < numToTarget);
    return new Object[] {vmList, stopModeList, vmInfoList};
  }
  /**
   * Check event counters. If numCloseIsExact is true, then the number of close events must be an
   * exact match, otherwise allow numClose events to be the minimum of the expected numClose
   * counter. This is useful in tests where the timing of shutting down the VMs/C clients may or may
   * not cause a close event.
   *
   * @param eventCountExact - True if the event counters must exactly match the expected value,
   *     false if the event counters must be no less than the expected counter.
   */
  protected void checkEventCounters(boolean eventCountExact) {

    SharedCounters counters = BridgeNotifyBB.getBB().getSharedCounters();
    long numCreate = counters.read(BridgeNotifyBB.NUM_CREATE);
    long numUpdate = counters.read(BridgeNotifyBB.NUM_UPDATE);
    long numPutAllCreate = counters.read(BridgeNotifyBB.NUM_PUTALL_CREATE);
    long numPutAllUpdate = counters.read(BridgeNotifyBB.NUM_PUTALL_UPDATE);
    long numDestroy = counters.read(BridgeNotifyBB.NUM_DESTROY);
    long numInval = counters.read(BridgeNotifyBB.NUM_INVALIDATE);
    long numRegionCreate = counters.read(BridgeNotifyBB.NUM_REGION_CREATE);
    long numRegionDestroy = counters.read(BridgeNotifyBB.NUM_REGION_DESTROY);
    long numRegionInval = counters.read(BridgeNotifyBB.NUM_REGION_INVALIDATE);
    long numLocalDestroy = counters.read(BridgeNotifyBB.NUM_LOCAL_DESTROY);
    long numLocalInval = counters.read(BridgeNotifyBB.NUM_LOCAL_INVALIDATE);
    long numLocalRegionDestroy = counters.read(BridgeNotifyBB.NUM_LOCAL_REGION_DESTROY);
    long numLocalRegionInval = counters.read(BridgeNotifyBB.NUM_LOCAL_REGION_INVALIDATE);
    long numClose = counters.read(BridgeNotifyBB.NUM_CLOSE);

    /* the ALL_KEYS client will always get events (including creates on new keys)
     * the ALL_KEYS and one of the KeyList (odd/even) clients will always get all events
     * on the original keySet
     * we'll get 3 events per operation if we happen to select the singleKey client's key
     * This is written to the BB by the VM performing the operation (it knows how many
     * clients should get the update)
     */
    // factor this out to separate lines to track down an NPE issue
    // 2006-08-29 jpenney
    BridgeNotifyBB bnbb = BridgeNotifyBB.getBB();
    SharedMap sm = bnbb.getSharedMap();
    Object nl = sm.get(BridgeNotifyBB.numListeners);
    int numVmsWithList = ((Integer) nl).intValue();
    Log.getLogWriter().info("num VMs with listener installed: " + numVmsWithList);

    // This mixedBridgeNotify test always uses notifyBySubscription/registerInterest
    // Note:  to some degree we have to know if this key was in the original keyList
    ArrayList al = new ArrayList();
    al.add(
        new ExpCounterValue(
            "numAfterCreateEvents_isNotExp",
            (numCreate * numVmsWithList + numPutAllCreate * numVmsWithList),
            eventCountExact));
    al.add(
        new ExpCounterValue(
            "numAfterDestroyEvents_isNotExp", (numDestroy * numVmsWithList), eventCountExact));
    al.add(
        new ExpCounterValue(
            "numAfterInvalidateEvents_isNotExp", (numInval * numVmsWithList), eventCountExact));
    al.add(
        new ExpCounterValue(
            "numAfterUpdateEvents_isNotExp",
            (numUpdate * numVmsWithList + numPutAllUpdate * numVmsWithList),
            eventCountExact));
    al.add(new ExpCounterValue("numAfterRegionDestroyEvents_isNotExp", 0, eventCountExact));
    al.add(new ExpCounterValue("numAfterRegionInvalidateEvents_isNotExp", 0, eventCountExact));
    al.add(new ExpCounterValue("numClose", numClose, eventCountExact));

    EventCountersBB.getBB().checkEventCounters(al);

    // This only works on a serial basis, since each operation performed has a different
    // number of listeners with registered interest, therefore, we must clean the
    // BridgeNotifyBB operation counters each time
    counters.zero(BridgeNotifyBB.NUM_CREATE);
    counters.zero(BridgeNotifyBB.NUM_UPDATE);
    counters.zero(BridgeNotifyBB.NUM_PUTALL_CREATE);
    counters.zero(BridgeNotifyBB.NUM_PUTALL_UPDATE);
    counters.zero(BridgeNotifyBB.NUM_DESTROY);
    counters.zero(BridgeNotifyBB.NUM_INVALIDATE);

    // clear EventCountersBB as well (for actual event counters recv'd)
    EventCountersBB.getBB().zeroAllCounters();
  }