[libvirt] [PATCH] esx: Improve object-by-type lookup performance

Matthias Bolte matthias.bolte at googlemail.com
Sat Aug 21 17:02:03 UTC 2010


Instead of using one big traversal spec for lookup use a set of
more fine grained traversal specs that are selected based on the
actual needs of the lookup.

This gives up to 20% speedup for certain operations like domain
listing due to less HTTP(S) traffic.
---
 src/esx/esx_driver.c |    1 -
 src/esx/esx_vi.c     |  223 +++++++++++++++++++++++++-------------------------
 src/esx/esx_vi.h     |   16 ++--
 3 files changed, 121 insertions(+), 119 deletions(-)

diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index c6bd3b8..9fef1df 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -3734,7 +3734,6 @@ esxNodeGetFreeMemory(virConnectPtr conn)
         esxVI_LookupObjectContentByType(priv->primary,
                                         priv->primary->computeResource->resourcePool,
                                         "ResourcePool", propertyNameList,
-                                        esxVI_Boolean_False,
                                         &resourcePool) < 0) {
         goto cleanup;
     }
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index 3773a5f..b531798 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -104,8 +104,12 @@ ESX_VI__TEMPLATE__FREE(Context,
     esxVI_Datacenter_Free(&item->datacenter);
     esxVI_ComputeResource_Free(&item->computeResource);
     esxVI_HostSystem_Free(&item->hostSystem);
-    esxVI_SelectionSpec_Free(&item->fullTraversalSpecList);
-    esxVI_SelectionSpec_Free(&item->fullTraversalSpecList2);
+    esxVI_SelectionSpec_Free(&item->selectSet_folderToChildEntity);
+    esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToParent);
+    esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToVm);
+    esxVI_SelectionSpec_Free(&item->selectSet_hostSystemToDatastore);
+    esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToHost);
+    esxVI_SelectionSpec_Free(&item->selectSet_computeResourceToParentToParent);
 });
 
 static size_t
@@ -450,23 +454,7 @@ esxVI_Context_Connect(esxVI_Context *ctx, const char *url,
     }
 
     if (esxVI_Login(ctx, username, password, NULL, &ctx->session) < 0 ||
-        esxVI_BuildFullTraversalSpecList(&ctx->fullTraversalSpecList) < 0) {
-        return -1;
-    }
-
-    /* Folder -> parent (Folder, Datacenter) */
-    if (esxVI_BuildFullTraversalSpecItem(&ctx->fullTraversalSpecList2,
-                                         "managedEntityToParent",
-                                         "ManagedEntity", "parent",
-                                         NULL) < 0) {
-        return -1;
-    }
-
-    /* ComputeResource -> parent (Folder) */
-    if (esxVI_BuildFullTraversalSpecItem(&ctx->fullTraversalSpecList2,
-                                         "computeResourceToParent",
-                                         "ComputeResource", "parent",
-                                         "managedEntityToParent\0") < 0) {
+        esxVI_BuildSelectSetCollection(ctx) < 0) {
         return -1;
     }
 
@@ -495,7 +483,6 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
                                            "hostFolder\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, ctx->service->rootFolder,
                                         "Datacenter", propertyNameList,
-                                        esxVI_Boolean_True,
                                         &datacenterList) < 0) {
         goto cleanup;
     }
@@ -545,7 +532,6 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
                                            "resourcePool\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, ctx->datacenter->hostFolder,
                                         "ComputeResource", propertyNameList,
-                                        esxVI_Boolean_True,
                                         &computeResourceList) < 0) {
         goto cleanup;
     }
@@ -607,7 +593,6 @@ esxVI_Context_LookupObjectsByPath(esxVI_Context *ctx,
                                            "name\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, ctx->computeResource->_reference,
                                         "HostSystem", propertyNameList,
-                                        esxVI_Boolean_True,
                                         &hostSystemList) < 0) {
         goto cleanup;
     }
@@ -684,7 +669,7 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
                        &managedObjectReference) < 0 ||
         esxVI_LookupObjectContentByType(ctx, managedObjectReference,
                                         "HostSystem", propertyNameList,
-                                        esxVI_Boolean_False, &hostSystem) < 0) {
+                                        &hostSystem) < 0) {
         goto cleanup;
     }
 
@@ -708,7 +693,6 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
                                            "resourcePool\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, hostSystem->obj,
                                         "ComputeResource", propertyNameList,
-                                        esxVI_Boolean_True,
                                         &computeResource) < 0) {
         goto cleanup;
     }
@@ -733,14 +717,6 @@ esxVI_Context_LookupObjectsByHostSystemIp(esxVI_Context *ctx,
                                            "hostFolder\0") < 0 ||
         esxVI_LookupObjectContentByType(ctx, computeResource->obj,
                                         "Datacenter", propertyNameList,
-                                        /* FIXME: Passing Undefined here is a hack until
-                                         * esxVI_LookupObjectContentByType supports more
-                                         * fine grained traversal configuration. Looking
-                                         * up the Datacenter from the ComputeResource
-                                         * requiers an upward search. Putting this in the
-                                         * list with the other downward traversal rules
-                                         * would result in cyclic searching */
-                                        esxVI_Boolean_Undefined,
                                         &datacenter) < 0) {
         goto cleanup;
     }
@@ -1406,15 +1382,15 @@ esxVI_Alloc(void **ptrptr, size_t size)
 
 
 int
-esxVI_BuildFullTraversalSpecItem(esxVI_SelectionSpec **fullTraversalSpecList,
-                                 const char *name, const char *type,
-                                 const char *path, const char *selectSetNames)
+esxVI_BuildSelectSet(esxVI_SelectionSpec **selectSet,
+                     const char *name, const char *type,
+                     const char *path, const char *selectSetNames)
 {
     esxVI_TraversalSpec *traversalSpec = NULL;
     esxVI_SelectionSpec *selectionSpec = NULL;
     const char *currentSelectSetName = NULL;
 
-    if (fullTraversalSpecList == NULL) {
+    if (selectSet == NULL || *selectSet != NULL) {
         ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
         return -1;
     }
@@ -1445,7 +1421,7 @@ esxVI_BuildFullTraversalSpecItem(esxVI_SelectionSpec **fullTraversalSpecList,
         }
     }
 
-    if (esxVI_SelectionSpec_AppendToList(fullTraversalSpecList,
+    if (esxVI_SelectionSpec_AppendToList(selectSet,
                                          esxVI_SelectionSpec_DynamicCast
                                            (traversalSpec)) < 0) {
         goto failure;
@@ -1461,86 +1437,87 @@ esxVI_BuildFullTraversalSpecItem(esxVI_SelectionSpec **fullTraversalSpecList,
 }
 
 
-
 int
-esxVI_BuildFullTraversalSpecList(esxVI_SelectionSpec **fullTraversalSpecList)
+esxVI_BuildSelectSetCollection(esxVI_Context *ctx)
 {
-    if (fullTraversalSpecList == NULL || *fullTraversalSpecList != NULL) {
-        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
-        return -1;
-    }
-
     /* Folder -> childEntity (ManagedEntity) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "folderToChildEntity",
-                                         "Folder", "childEntity",
-                                         "folderToChildEntity\0") < 0) {
-        goto failure;
+    if (esxVI_BuildSelectSet(&ctx->selectSet_folderToChildEntity,
+                             "folderToChildEntity",
+                             "Folder", "childEntity",
+                             "folderToChildEntity\0") < 0) {
+        return -1;
     }
 
     /* ComputeResource -> host (HostSystem) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "computeResourceToHost",
-                                         "ComputeResource", "host",
-                                         NULL) < 0) {
-        goto failure;
+    if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToHost,
+                             "computeResourceToHost",
+                             "ComputeResource", "host", NULL) < 0) {
+        return -1;
     }
 
-    /* ComputeResource -> datastore (Datastore) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "computeResourceToDatastore",
-                                         "ComputeResource", "datastore",
-                                         NULL) < 0) {
-        goto failure;
-    }
+    /* ComputeResource -> datastore (Datastore) *//*
+    if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToDatastore,
+                             "computeResourceToDatastore",
+                             "ComputeResource", "datastore", NULL) < 0) {
+        return -1;
+    }*/
 
-    /* ResourcePool -> resourcePool (ResourcePool) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "resourcePoolToResourcePool",
-                                         "ResourcePool", "resourcePool",
-                                         "resourcePoolToResourcePool\0"
-                                         "resourcePoolToVm\0") < 0) {
-        goto failure;
-    }
+    /* ResourcePool -> resourcePool (ResourcePool) *//*
+    if (esxVI_BuildSelectSet(&ctx->selectSet_resourcePoolToVm,
+                             "resourcePoolToResourcePool",
+                             "ResourcePool", "resourcePool",
+                             "resourcePoolToResourcePool\0"
+                             "resourcePoolToVm\0") < 0) {
+        return -1;
+    }*/
 
-    /* ResourcePool -> vm (VirtualMachine) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "resourcePoolToVm",
-                                         "ResourcePool", "vm", NULL) < 0) {
-        goto failure;
-    }
+    /* ResourcePool -> vm (VirtualMachine) *//*
+    if (esxVI_BuildSelectSet(&ctx->selectSet_resourcePoolToVm,
+                             "resourcePoolToVm",
+                             "ResourcePool", "vm", NULL) < 0) {
+        return -1;
+    }*/
 
     /* HostSystem -> parent (ComputeResource) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "hostSystemToParent",
-                                         "HostSystem", "parent", NULL) < 0) {
-        goto failure;
+    if (esxVI_BuildSelectSet(&ctx->selectSet_hostSystemToParent,
+                             "hostSystemToParent",
+                             "HostSystem", "parent", NULL) < 0) {
+        return -1;
     }
 
     /* HostSystem -> vm (VirtualMachine) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "hostSystemToVm",
-                                         "HostSystem", "vm", NULL) < 0) {
-        goto failure;
+    if (esxVI_BuildSelectSet(&ctx->selectSet_hostSystemToVm,
+                             "hostSystemToVm",
+                             "HostSystem", "vm", NULL) < 0) {
+        return -1;
     }
 
     /* HostSystem -> datastore (Datastore) */
-    if (esxVI_BuildFullTraversalSpecItem(fullTraversalSpecList,
-                                         "hostSystemToDatastore",
-                                         "HostSystem", "datastore", NULL) < 0) {
-        goto failure;
+    if (esxVI_BuildSelectSet(&ctx->selectSet_hostSystemToDatastore,
+                             "hostSystemToDatastore",
+                             "HostSystem", "datastore", NULL) < 0) {
+        return -1;
     }
 
-    return 0;
+    /* Folder -> parent (Folder, Datacenter) */
+    if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToParentToParent,
+                             "managedEntityToParent",
+                             "ManagedEntity", "parent", NULL) < 0) {
+        return -1;
+    }
 
-  failure:
-    esxVI_SelectionSpec_Free(fullTraversalSpecList);
+    /* ComputeResource -> parent (Folder) */
+    if (esxVI_BuildSelectSet(&ctx->selectSet_computeResourceToParentToParent,
+                             "computeResourceToParent",
+                             "ComputeResource", "parent",
+                             "managedEntityToParent\0") < 0) {
+        return -1;
+    }
 
-    return -1;
+    return 0;
 }
 
 
-
 /*
  * Can't use the SessionIsActive() function here, because at least
  * 'ESX Server 3.5.0 build-64607' returns an 'method not implemented' fault if
@@ -1591,7 +1568,6 @@ esxVI_EnsureSession(esxVI_Context *ctx)
                                        "currentSession") < 0 ||
         esxVI_LookupObjectContentByType(ctx, ctx->service->sessionManager,
                                         "SessionManager", propertyNameList,
-                                        esxVI_Boolean_False,
                                         &sessionManager) < 0) {
         goto cleanup;
     }
@@ -1642,7 +1618,6 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
                                 esxVI_ManagedObjectReference *root,
                                 const char *type,
                                 esxVI_String *propertyNameList,
-                                esxVI_Boolean recurse,
                                 esxVI_ObjectContent **objectContentList)
 {
     int result = -1;
@@ -1650,11 +1625,6 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
     esxVI_PropertySpec *propertySpec = NULL;
     esxVI_PropertyFilterSpec *propertyFilterSpec = NULL;
 
-    if (ctx->fullTraversalSpecList == NULL) {
-        ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid call"));
-        return -1;
-    }
-
     if (objectContentList == NULL || *objectContentList != NULL) {
         ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
         return -1;
@@ -1667,10 +1637,45 @@ esxVI_LookupObjectContentByType(esxVI_Context *ctx,
     objectSpec->obj = root;
     objectSpec->skip = esxVI_Boolean_False;
 
-    if (recurse == esxVI_Boolean_True) {
-        objectSpec->selectSet = ctx->fullTraversalSpecList;
-    } else if (recurse == esxVI_Boolean_Undefined) {
-        objectSpec->selectSet = ctx->fullTraversalSpecList2;
+    if (STRNEQ(root->type, type)) {
+        if (STREQ(root->type, "Folder")) {
+            if (STREQ(type, "Datacenter") || STREQ(type, "ComputeResource")) {
+                objectSpec->selectSet = ctx->selectSet_folderToChildEntity;
+            } else {
+                ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             _("Invalid lookup of '%s' from '%s'"),
+                             type, root->type);
+                goto cleanup;
+            }
+        } else if (STREQ(root->type, "ComputeResource")) {
+            if (STREQ(type, "HostSystem")) {
+                objectSpec->selectSet = ctx->selectSet_computeResourceToHost;
+            } else if (STREQ(type, "Datacenter")) {
+                objectSpec->selectSet = ctx->selectSet_computeResourceToParentToParent;
+            } else {
+                ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             _("Invalid lookup of '%s' from '%s'"),
+                             type, root->type);
+                goto cleanup;
+            }
+        } else if (STREQ(root->type, "HostSystem")) {
+            if (STREQ(type, "ComputeResource")) {
+                objectSpec->selectSet = ctx->selectSet_hostSystemToParent;
+            } else if (STREQ(type, "VirtualMachine")) {
+                objectSpec->selectSet = ctx->selectSet_hostSystemToVm;
+            } else if (STREQ(type, "Datastore")) {
+                objectSpec->selectSet = ctx->selectSet_hostSystemToDatastore;
+            } else {
+                ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             _("Invalid lookup of '%s' from '%s'"),
+                             type, root->type);
+                goto cleanup;
+            }
+        } else {
+            ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("Invalid lookup from '%s'"), root->type);
+            goto cleanup;
+        }
     }
 
     if (esxVI_PropertySpec_Alloc(&propertySpec) < 0) {
@@ -2210,7 +2215,7 @@ int esxVI_LookupHostSystemProperties(esxVI_Context *ctx,
 {
     return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
                                            "HostSystem", propertyNameList,
-                                           esxVI_Boolean_False, hostSystem);
+                                           hostSystem);
 }
 
 
@@ -2224,7 +2229,6 @@ esxVI_LookupVirtualMachineList(esxVI_Context *ctx,
      *        for cluster support */
     return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
                                            "VirtualMachine", propertyNameList,
-                                           esxVI_Boolean_True,
                                            virtualMachineList);
 }
 
@@ -2267,7 +2271,6 @@ esxVI_LookupVirtualMachineByUuid(esxVI_Context *ctx, const unsigned char *uuid,
 
     if (esxVI_LookupObjectContentByType(ctx, managedObjectReference,
                                         "VirtualMachine", propertyNameList,
-                                        esxVI_Boolean_False,
                                         virtualMachine) < 0) {
         goto cleanup;
     }
@@ -2411,7 +2414,7 @@ esxVI_LookupDatastoreList(esxVI_Context *ctx, esxVI_String *propertyNameList,
      *        support */
     return esxVI_LookupObjectContentByType(ctx, ctx->hostSystem->_reference,
                                            "Datastore", propertyNameList,
-                                           esxVI_Boolean_True, datastoreList);
+                                           datastoreList);
 }
 
 
@@ -2590,8 +2593,7 @@ esxVI_LookupDatastoreHostMount(esxVI_Context *ctx,
 
     if (esxVI_String_AppendValueToList(&propertyNameList, "host") < 0 ||
         esxVI_LookupObjectContentByType(ctx, datastore, "Datastore",
-                                        propertyNameList, esxVI_Boolean_False,
-                                        &objectContent) < 0) {
+                                        propertyNameList, &objectContent) < 0) {
         goto cleanup;
     }
 
@@ -2656,7 +2658,6 @@ esxVI_LookupTaskInfoByTask(esxVI_Context *ctx,
 
     if (esxVI_String_AppendValueToList(&propertyNameList, "info") < 0 ||
         esxVI_LookupObjectContentByType(ctx, task, "Task", propertyNameList,
-                                        esxVI_Boolean_False,
                                         &objectContent) < 0) {
         goto cleanup;
     }
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index d5dc9d5..1431db2 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -161,8 +161,12 @@ struct _esxVI_Context {
     esxVI_Datacenter *datacenter;
     esxVI_ComputeResource *computeResource;
     esxVI_HostSystem *hostSystem;
-    esxVI_SelectionSpec *fullTraversalSpecList;
-    esxVI_SelectionSpec *fullTraversalSpecList2;
+    esxVI_SelectionSpec *selectSet_folderToChildEntity;
+    esxVI_SelectionSpec *selectSet_hostSystemToParent;
+    esxVI_SelectionSpec *selectSet_hostSystemToVm;
+    esxVI_SelectionSpec *selectSet_hostSystemToDatastore;
+    esxVI_SelectionSpec *selectSet_computeResourceToHost;
+    esxVI_SelectionSpec *selectSet_computeResourceToParentToParent;
 };
 
 int esxVI_Context_Alloc(esxVI_Context **ctx);
@@ -266,12 +270,11 @@ int esxVI_List_Deserialize(xmlNodePtr node, esxVI_List **list,
 
 int esxVI_Alloc(void **ptrptr, size_t size);
 
-int esxVI_BuildFullTraversalSpecItem
-      (esxVI_SelectionSpec **fullTraversalSpecList, const char *name,
+int esxVI_BuildSelectSet
+      (esxVI_SelectionSpec **selectSet, const char *name,
        const char *type, const char *path, const char *selectSetNames);
 
-int esxVI_BuildFullTraversalSpecList
-      (esxVI_SelectionSpec **fullTraversalSpecList);
+int esxVI_BuildSelectSetCollection(esxVI_Context *ctx);
 
 int esxVI_EnsureSession(esxVI_Context *ctx);
 
@@ -279,7 +282,6 @@ int esxVI_LookupObjectContentByType(esxVI_Context *ctx,
                                     esxVI_ManagedObjectReference *root,
                                     const char *type,
                                     esxVI_String *propertyNameList,
-                                    esxVI_Boolean recurse,
                                     esxVI_ObjectContent **objectContentList);
 
 int esxVI_GetManagedEntityStatus
-- 
1.7.0.4




More information about the libvir-list mailing list