Daniel Doubrovkine bio photo

Daniel Doubrovkine

aka dB., @awscloud, former CTO @artsy, +@vestris, NYC

Email Twitter LinkedIn Github Strava
Creative Commons License

Did I tell you how much I love yield return?

One of the peculiar VIX COM API constructs is the combination that returns arrays of properties. This is done with two functions: GetNumProperties and GetNthProperties. The first returns the number of property arrays returned by the job and the second fetches a property array at a given index. The first obvious step is to wrap the functions within the job class.

public T GetNthProperties<T>(int index, object[] properties) {
  object result = null;
  VMWareInterop.Check(_handle.GetNthProperties(index, properties, ref result));
  return (T) result;
}

public int GetNumProperties(int property) {
  return _handle.GetNumProperties(property);
}

We can now write such properties as RunningVirtualMachines.

public IEnumerable<VMWareVirtualMachine> RunningVirtualMachines {
   get
   {
      VMWareJob job = new VMWareJob(_handle.FindItems(
         Constants.VIX_FIND_RUNNING_VMS, null, -1, null));
      job.Wait(VMWareInterop.Timeouts.FindItemsTimeout);
      object[] properties = { Constants.VIX_PROPERTY_FOUND_ITEM_LOCATION };
      for (int i = 0; i < job.GetNumProperties((int) properties[0]); i++)
      {
         yield return this.Open(
            (string) job.GetNthProperties<object[]>(
               i, properties)[0]);
      }
   }
}

This is still not good enough. Let’s combine the number of results and the results themselves in a YieldWait method.

public IEnumerable<object[]> YieldWait(object[] properties, int timeoutInSeconds) {
   Wait(timeoutInSeconds);
   for (int i = 0; i < GetNumProperties((int)properties[0]); i++)
   {
      yield return GetNthProperties<object[]>(i, properties);
   }
}

This results in a nice improvement over the previous implementation: we’re interating over a resultset rather than calling methods for how many results are available and to fetch each result.

public IEnumerable<VMWareVirtualMachine> RunningVirtualMachines {
   get
   {
      VMWareJob job = new VMWareJob(_handle.FindItems(
         Constants.VIX_FIND_RUNNING_VMS, null, -1, null));
      object[] properties = { Constants.VIX_PROPERTY_FOUND_ITEM_LOCATION };
      foreach (object[] runningVirtualMachine in job.YieldWait(
         properties, VMWareInterop.Timeouts.FindItemsTimeout))
      {
         yield return this.Open((string) runningVirtualMachine[0]);
      }
   }
}