Index: src/zabbix_server/poller/checks_simple_vmware.c
===================================================================
--- src/zabbix_server/poller/checks_simple_vmware.c	(revision 62677)
+++ src/zabbix_server/poller/checks_simple_vmware.c	(working copy)
@@ -61,73 +61,56 @@
 	return ret;
 }
 
-static zbx_vmware_hv_t	*hv_get(zbx_vector_ptr_t *hvs, const char *uuid)
+static zbx_vmware_hv_t	*hv_get(zbx_hashset_t *hvs, const char *uuid)
 {
 	const char	*__function_name = "hv_get";
 
-	int		i;
-	zbx_vmware_hv_t	*hv;
+	zbx_vmware_hv_t	*hv, hv_local = {(char *)uuid};
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() uuid:'%s'", __function_name, uuid);
 
-	for (i = 0; i < hvs->values_num; i++)
-	{
-		hv = (zbx_vmware_hv_t *)hvs->values[i];
-
-		if (0 == strcmp(hv->uuid, uuid))
-			goto out;
-	}
+	hv = zbx_hashset_search(hvs, &hv_local);
 
-	hv = NULL;
-out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, hv);
 
 	return hv;
 }
 
-static zbx_vmware_vm_t	*vm_get(zbx_vector_ptr_t *vms, const char *uuid)
+static zbx_vmware_hv_t	*service_hv_get_by_vm_uuid(zbx_vmware_service_t *service, const char *uuid)
 {
-	const char	*__function_name = "vm_get";
+	const char	*__function_name = "service_hv_get_by_vm_uuid";
 
-	int		i;
-	zbx_vmware_vm_t	*vm;
+	zbx_vmware_vm_t		vm_local = {(char *)uuid};
+	zbx_vmware_vm_index_t	vmi_local = {&vm_local}, *vmi;
+	zbx_vmware_hv_t		*hv = NULL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() uuid:'%s'", __function_name, uuid);
 
-	for (i = 0; i < vms->values_num; i++)
-	{
-		vm = (zbx_vmware_vm_t *)vms->values[i];
+	if (NULL != (vmi = zbx_hashset_search(&service->data->vms_index, &vmi_local)))
+		hv = vmi->hv;
+	else
+		hv = NULL;
 
-		if (0 == strcmp(vm->uuid, uuid))
-			goto out;
-	}
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, hv);
 
-	vm = NULL;
-out:
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, vm);
+	return hv;
 
-	return vm;
 }
 
 static zbx_vmware_vm_t	*service_vm_get(zbx_vmware_service_t *service, const char *uuid)
 {
 	const char	*__function_name = "service_vm_get";
 
-	int		i;
-	zbx_vmware_vm_t	*vm;
+	zbx_vmware_vm_t		vm_local = {(char *)uuid}, *vm;
+	zbx_vmware_vm_index_t	vmi_local = {&vm_local}, *vmi;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() uuid:'%s'", __function_name, uuid);
 
-	for (i = 0; i < service->data->hvs.values_num; i++)
-	{
-		zbx_vmware_hv_t	*hv = (zbx_vmware_hv_t *)service->data->hvs.values[i];
-
-		if (NULL != (vm = vm_get(&hv->vms, uuid)))
-			goto out;
-	}
+	if (NULL != (vmi = zbx_hashset_search(&service->data->vms_index, &vmi_local)))
+		vm = vmi->vm;
+	else
+		vm = NULL;
 
-	vm = NULL;
-out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, vm);
 
 	return vm;
@@ -356,7 +339,7 @@
 
 /******************************************************************************
  *                                                                            *
- * Function: get_vcenter_vmstat                                               *
+ * Function: get_vcenter_vmprop                                               *
  *                                                                            *
  * Purpose: retrieves data from virtual machine details                       *
  *                                                                            *
@@ -369,17 +352,17 @@
  *             result    - [OUT] the request result                           *
  *                                                                            *
  ******************************************************************************/
-static int	get_vcenter_vmstat(AGENT_REQUEST *request, const char *username, const char *password,
-		const char *xpath, AGENT_RESULT *result)
+static int	get_vcenter_vmprop(AGENT_REQUEST *request, const char *username, const char *password,
+		int propid, AGENT_RESULT *result)
 {
-	const char		*__function_name = "get_vcenter_vmstat";
+	const char		*__function_name = "get_vcenter_vmprop";
 
 	zbx_vmware_service_t	*service;
 	zbx_vmware_vm_t		*vm = NULL;
 	char			*url, *uuid, *value;
 	int			ret = SYSINFO_RET_FAIL;
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s() xpath:'%s'", __function_name, xpath);
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() propid:%d", __function_name, propid);
 
 	if (2 != request->nparam)
 	{
@@ -407,13 +390,13 @@
 		goto unlock;
 	}
 
-	if (NULL == (value = zbx_xml_read_value(vm->details, xpath)))
+	if (NULL == (value = vm->props[propid]))
 	{
 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Value is not available."));
 		goto unlock;
 	}
 
-	SET_STR_RESULT(result, value);
+	SET_STR_RESULT(result, zbx_strdup(NULL, value));
 
 	ret = SYSINFO_RET_OK;
 unlock:
@@ -424,87 +407,32 @@
 	return ret;
 }
 
-#define ZBX_OPT_XPATH		0
-#define ZBX_OPT_VM_NUM		1
-#define ZBX_OPT_MEM_BALLOONED	2
-
-static int	hv_get_stat(zbx_vmware_hv_t *hv, int opt, const char *xpath, AGENT_RESULT *result)
-{
-	const char	*__function_name = "hv_get_stat";
-
-	char		*value;
-	zbx_uint64_t	value_uint64, value_uint64_sum;
-	int		i, ret = SYSINFO_RET_FAIL;
-
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
-
-	switch (opt)
-	{
-		case ZBX_OPT_XPATH:
-			zabbix_log(LOG_LEVEL_DEBUG, "%s() xpath:'%s'", __function_name, xpath);
-
-			if (NULL == (value = zbx_xml_read_value(hv->details, xpath)))
-				goto out;
-
-			SET_STR_RESULT(result, value);
-			break;
-		case ZBX_OPT_VM_NUM:
-			SET_UI64_RESULT(result, hv->vms.values_num);
-			break;
-		case ZBX_OPT_MEM_BALLOONED:
-			xpath = ZBX_XPATH_VM_QUICKSTATS("balloonedMemory");
-			value_uint64_sum = 0;
-
-			for (i = 0; i < hv->vms.values_num; i++)
-			{
-				zbx_vmware_vm_t	*vm = (zbx_vmware_vm_t *)hv->vms.values[i];
-
-				if (NULL == (value = zbx_xml_read_value(vm->details, xpath)))
-					continue;
-
-				if (SUCCEED == is_uint64(value, &value_uint64))
-					value_uint64_sum += value_uint64;
-
-				zbx_free(value);
-			}
-
-			SET_UI64_RESULT(result, value_uint64_sum);
-			break;
-	}
-
-	ret = SYSINFO_RET_OK;
-out:
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
-
-	return ret;
-}
-
 /******************************************************************************
  *                                                                            *
- * Function: get_vcenter_stat                                                 *
+ * Function: get_vcenter_hvprop                                               *
  *                                                                            *
- * Purpose: retrieves data from hypervisor details                            *
+ * Purpose: retrieves hypervisor property                                     *
  *                                                                            *
  * Parameters: request   - [IN] the original request. The first parameter is  *
  *                              vmware service URL and the second parameter   *
  *                              is hypervisor uuid.                           *
  *             username  - [IN] the vmware service user name                  *
  *             password  - [IN] the vmware service password                   *
- *             xpath     - [IN] the xpath describing data to retrieve         *
+ *             propid    - [IN] the property id                               *
  *             result    - [OUT] the request result                           *
  *                                                                            *
  ******************************************************************************/
-static int	get_vcenter_stat(AGENT_REQUEST *request, const char *username, const char *password,
-		int opt, const char *xpath, AGENT_RESULT *result)
+static int	get_vcenter_hvprop(AGENT_REQUEST *request, const char *username, const char *password, int propid,
+		AGENT_RESULT *result)
 {
-	const char		*__function_name = "get_vcenter_stat";
+	const char		*__function_name = "get_vcenter_hvprop";
 
 	zbx_vmware_service_t	*service;
-	const char		*uuid, *url;
+	const char		*uuid, *url, *value;
 	zbx_vmware_hv_t		*hv;
 	int			ret = SYSINFO_RET_FAIL;
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s() opt:%d", __function_name, opt);
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() propid:%d", __function_name, propid);
 
 	if (2 != request->nparam)
 	{
@@ -532,7 +460,14 @@
 		goto unlock;
 	}
 
-	ret = hv_get_stat(hv, opt, xpath, result);
+	if (NULL == (value = hv->props[propid]))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Value is not available."));
+		goto unlock;
+	}
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, value));
+	ret = SYSINFO_RET_OK;
 unlock:
 	zbx_vmware_unlock();
 out:
@@ -541,6 +476,7 @@
 	return ret;
 }
 
+
 int	check_vcenter_cluster_discovery(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result)
 {
@@ -934,9 +870,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_QUICKSTATS("overallCpuUsage"), result);
-
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE, result);
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * 1000000;
 
@@ -953,7 +887,10 @@
 	struct zbx_json		json_data;
 	char			*url, *name;
 	zbx_vmware_service_t	*service;
-	int			i, ret = SYSINFO_RET_FAIL;
+	int			ret = SYSINFO_RET_FAIL;
+	zbx_vmware_hv_t		*hv;
+	zbx_hashset_iter_t	iter;
+
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -973,12 +910,12 @@
 	zbx_json_init(&json_data, ZBX_JSON_STAT_BUF_LEN);
 	zbx_json_addarray(&json_data, ZBX_PROTO_TAG_DATA);
 
-	for (i = 0; i < service->data->hvs.values_num; i++)
+	zbx_hashset_iter_reset(&service->data->hvs, &iter);
+	while (NULL != (hv = zbx_hashset_iter_next(&iter)))
 	{
 		zbx_vmware_cluster_t	*cluster = NULL;
-		zbx_vmware_hv_t	*hv = (zbx_vmware_hv_t *)service->data->hvs.values[i];
 
-		if (NULL == (name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"))))
+		if (NULL == (name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
 			continue;
 
 		if (NULL != hv->clusterid)
@@ -991,8 +928,6 @@
 		zbx_json_addstring(&json_data, "{#CLUSTER.NAME}",
 				NULL != cluster ? cluster->name : "", ZBX_JSON_TYPE_STRING);
 		zbx_json_close(&json_data);
-
-		zbx_free(name);
 	}
 
 	zbx_json_close(&json_data);
@@ -1019,8 +954,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_CONFIG_PRODUCT("fullName"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_FULL_NAME, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1036,8 +970,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("numCpuCores"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1053,8 +986,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("cpuMhz"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_CPU_MHZ, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * 1000000;
@@ -1073,8 +1005,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("cpuModel"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_CPU_MODEL, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1090,8 +1021,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("numCpuThreads"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1107,7 +1037,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("memorySize"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1123,8 +1053,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("model"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_MODEL, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1140,8 +1069,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("uuid"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_UUID, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1157,8 +1085,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("vendor"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_VENDOR, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1170,15 +1097,62 @@
 {
 	const char	*__function_name = "check_vcenter_hv_memory_size_ballooned";
 
-	int		ret;
+	int			i, ret = SYSINFO_RET_FAIL;
+	zbx_vmware_service_t	*service;
+	const char		*uuid, *url;
+	zbx_vmware_hv_t		*hv;
+	zbx_uint64_t		value = 0;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_MEM_BALLOONED, NULL, result);
+	if (2 != request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+		goto out;
+	}
 
-	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
-		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
+	url = get_rparam(request, 0);
+	uuid = get_rparam(request, 1);
 
+	if ('\0' == *uuid)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		goto out;
+	}
+
+	zbx_vmware_lock();
+
+	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
+		goto unlock;
+
+	if (NULL == (hv = hv_get(&service->data->hvs, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown hypervisor uuid."));
+		goto unlock;
+	}
+
+	for (i = 0; i < hv->vms.values_num; i++)
+	{
+		zbx_uint64_t	mem;
+		const char	*value;
+		zbx_vmware_vm_t	*vm = (zbx_vmware_vm_t *)hv->vms.values[i];
+
+		if (NULL == (value = vm->props[ZBX_VMWARE_VMPROP_MEMORY_SIZE_BALLOONED]))
+			continue;
+
+		if (SUCCEED != is_uint64(value, &mem))
+			continue;
+
+		value += mem;
+	}
+
+	value *= ZBX_MEBIBYTE;
+	SET_UI64_RESULT(result, value);
+
+	ret = SYSINFO_RET_OK;
+unlock:
+	zbx_vmware_unlock();
+out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
 	return ret;
@@ -1193,8 +1167,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_QUICKSTATS("overallMemoryUsage"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_MEMORY_USED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1213,8 +1186,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_SENSOR_STATUS("VMware Rollup Health State"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_STATUS, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_STR_RESULT(result))
 	{
@@ -1246,8 +1218,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_QUICKSTATS("uptime"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_UPTIME, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1263,8 +1234,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_CONFIG_PRODUCT("version"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_VERSION, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1276,12 +1246,44 @@
 {
 	const char	*__function_name = "check_vcenter_hv_vm_num";
 
-	int		ret;
+	int			ret = SYSINFO_RET_FAIL;
+	zbx_vmware_service_t	*service;
+	const char		*uuid, *url;
+	zbx_vmware_hv_t		*hv;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_VM_NUM, NULL, result);
+	if (2 != request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+		goto out;
+	}
+
+	url = get_rparam(request, 0);
+	uuid = get_rparam(request, 1);
 
+	if ('\0' == *uuid)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		goto out;
+	}
+
+	zbx_vmware_lock();
+
+	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
+		goto unlock;
+
+	if (NULL == (hv = hv_get(&service->data->hvs, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown hypervisor uuid."));
+		goto unlock;
+	}
+
+	SET_UI64_RESULT(result, hv->vms.values_num);
+	ret = SYSINFO_RET_OK;
+unlock:
+	zbx_vmware_unlock();
+out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
 	return ret;
@@ -1647,7 +1649,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_CONFIG("numCpu"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_CPU_NUM, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1662,7 +1664,8 @@
 	char			*url, *uuid;
 	zbx_vmware_service_t	*service;
 	zbx_vmware_cluster_t	*cluster = NULL;
-	int			i, ret = SYSINFO_RET_FAIL;
+	int			ret = SYSINFO_RET_FAIL;
+	zbx_vmware_hv_t		*hv;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -1686,19 +1689,13 @@
 	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
 		goto unlock;
 
-	for (i = 0; i < service->data->hvs.values_num; i++)
+	if (NULL == (hv = service_hv_get_by_vm_uuid(service, uuid)))
 	{
-		zbx_vmware_hv_t	*hv = service->data->hvs.values[i];
-		zbx_vmware_vm_t		*vm;
-
-		if (NULL != (vm = vm_get(&hv->vms, uuid)))
-		{
-			if (NULL != hv->clusterid)
-				cluster = cluster_get(&service->data->clusters, hv->clusterid);
-
-			break;
-		}
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown virtual machine uuid."));
+		goto unlock;
 	}
+	if (NULL != hv->clusterid)
+		cluster = cluster_get(&service->data->clusters, hv->clusterid);
 
 	SET_STR_RESULT(result, zbx_strdup(NULL, NULL != cluster ? cluster->name : ""));
 
@@ -1720,7 +1717,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("overallCpuUsage"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_CPU_USAGE, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * 1000000;
@@ -1740,7 +1737,8 @@
 	zbx_vmware_service_t	*service;
 	zbx_vmware_hv_t		*hv;
 	zbx_vmware_vm_t		*vm;
-	int			i, k, ret = SYSINFO_RET_FAIL;
+	zbx_hashset_iter_t	iter;
+	int			i, ret = SYSINFO_RET_FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -1760,27 +1758,23 @@
 	zbx_json_init(&json_data, ZBX_JSON_STAT_BUF_LEN);
 	zbx_json_addarray(&json_data, ZBX_PROTO_TAG_DATA);
 
-	for (i = 0; i < service->data->hvs.values_num; i++)
+	zbx_hashset_iter_reset(&service->data->hvs, &iter);
+	while (NULL != (hv = zbx_hashset_iter_next(&iter)))
 	{
 		zbx_vmware_cluster_t	*cluster = NULL;
 
-		hv = (zbx_vmware_hv_t *)service->data->hvs.values[i];
-
 		if (NULL != hv->clusterid)
 			cluster = cluster_get(&service->data->clusters, hv->clusterid);
 
-		for (k = 0; k < hv->vms.values_num; k++)
+		for (i = 0; i < hv->vms.values_num; i++)
 		{
-			vm = (zbx_vmware_vm_t *)hv->vms.values[k];
+			vm = (zbx_vmware_vm_t *)hv->vms.values[i];
 
-			if (NULL == (vm_name = zbx_xml_read_value(vm->details, ZBX_XPATH_VM_CONFIG("name"))))
+			if (NULL == (vm_name = vm->props[ZBX_VMWARE_VMPROP_NAME]))
 				continue;
 
-			if (NULL == (hv_name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"))))
-			{
-				zbx_free(vm_name);
+			if (NULL == (hv_name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
 				continue;
-			}
 
 			zbx_json_addobject(&json_data, NULL);
 			zbx_json_addstring(&json_data, "{#VM.UUID}", vm->uuid, ZBX_JSON_TYPE_STRING);
@@ -1790,9 +1784,6 @@
 			zbx_json_addstring(&json_data, "{#CLUSTER.NAME}",
 					NULL != cluster ? cluster->name : "", ZBX_JSON_TYPE_STRING);
 			zbx_json_close(&json_data);
-
-			zbx_free(hv_name);
-			zbx_free(vm_name);
 		}
 	}
 
@@ -1819,7 +1810,7 @@
 	zbx_vmware_service_t	*service;
 	zbx_vmware_hv_t		*hv;
 	char			*url, *uuid, *name;
-	int			i, ret = SYSINFO_RET_FAIL;
+	int			ret = SYSINFO_RET_FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -1843,23 +1834,21 @@
 	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
 		goto unlock;
 
-	for (i = 0; i < service->data->hvs.values_num; i++)
-	{
-		hv = (zbx_vmware_hv_t *)service->data->hvs.values[i];
 
-		if (NULL != vm_get(&hv->vms, uuid))
-			break;
+	if (NULL == (hv = service_hv_get_by_vm_uuid(service, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown virtual machine uuid."));
+		goto unlock;
 	}
 
-	if (i != service->data->hvs.values_num)
+	if (NULL == (name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
 	{
-		name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"));
-
-		SET_STR_RESULT(result, name);
-		ret = SYSINFO_RET_OK;
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "No hypervisor name found."));
+		goto unlock;
 	}
-	else
-		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown virtual machine uuid."));
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, name));
+	ret = SYSINFO_RET_OK;
 unlock:
 	zbx_vmware_unlock();
 out:
@@ -1877,7 +1866,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_CONFIG("memorySizeMB"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1896,7 +1885,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("balloonedMemory"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_BALLOONED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1915,7 +1904,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("compressedMemory"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_COMPRESSED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1934,7 +1923,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("swappedMemory"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_SWAPPED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1953,7 +1942,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("guestMemoryUsage"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_GUEST, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1972,7 +1961,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("hostMemoryUsage"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_HOST, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1991,7 +1980,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("privateMemory"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_PRIVATE, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -2010,7 +1999,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("sharedMemory"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_MEMORY_SIZE_SHARED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -2029,7 +2018,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_RUNTIME("powerState"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_POWER_STATE, result);
 
 	if (SYSINFO_RET_OK == ret)
 		ret = vmware_set_powerstate_result(result);
@@ -2251,7 +2240,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_STORAGE("committed"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_STORAGE_COMMITED, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -2267,7 +2256,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_STORAGE("unshared"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_STORAGE_UNSHARED, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -2283,7 +2272,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_STORAGE("uncommitted"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_STORAGE_UNCOMMITTED, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -2299,7 +2288,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_vmstat(request, username, password, ZBX_XPATH_VM_QUICKSTATS("uptimeSeconds"), result);
+	ret = get_vcenter_vmprop(request, username, password, ZBX_VMWARE_VMPROP_UPTIME, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -2517,7 +2506,6 @@
 	zbx_vmware_service_t	*service;
 	zbx_vmware_vm_t		*vm = NULL;
 	char			*url, *uuid;
-	zbx_vector_str_t	disks;
 	int			i, ret = SYSINFO_RET_FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
@@ -2548,25 +2536,20 @@
 		goto unlock;
 	}
 
-	zbx_vector_str_create(&disks);
-
-	zbx_xml_read_values(vm->details, ZBX_XPATH_LN2("disk", "diskPath"), &disks);
-
 	zbx_json_init(&json_data, ZBX_JSON_STAT_BUF_LEN);
 	zbx_json_addarray(&json_data, ZBX_PROTO_TAG_DATA);
 
-	for (i = 0; i < disks.values_num; i++)
+	for (i = 0; i < vm->file_systems.values_num; i++)
 	{
+		zbx_vmware_fs_t	*fs = (zbx_vmware_fs_t *)vm->file_systems.values[i];
+
 		zbx_json_addobject(&json_data, NULL);
-		zbx_json_addstring(&json_data, "{#FSNAME}", disks.values[i], ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "{#FSNAME}", fs->path, ZBX_JSON_TYPE_STRING);
 		zbx_json_close(&json_data);
 	}
 
 	zbx_json_close(&json_data);
 
-	zbx_vector_str_clean(&disks);
-	zbx_vector_str_destroy(&disks);
-
 	SET_STR_RESULT(result, zbx_strdup(NULL, json_data.buffer));
 
 	zbx_json_free(&json_data);
@@ -2587,9 +2570,9 @@
 
 	zbx_vmware_service_t	*service;
 	zbx_vmware_vm_t		*vm;
-	char			*url, *uuid, *fsname, *mode, *value = NULL, xpath[MAX_STRING_LEN];
-	zbx_uint64_t		value_total, value_free;
-	int			ret = SYSINFO_RET_FAIL;
+	char			*url, *uuid, *fsname, *mode;
+	int			i, ret = SYSINFO_RET_FAIL;
+	zbx_vmware_fs_t		*fs = NULL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -2621,48 +2604,38 @@
 		goto unlock;
 	}
 
-	zbx_snprintf(xpath, sizeof(xpath),
-			ZBX_XPATH_LN2("disk", "diskPath") "[.='%s']/.." ZBX_XPATH_LN("capacity"), fsname);
-
-	if (NULL == (value = zbx_xml_read_value(vm->details, xpath)))
-		goto unlock;
-
-	zabbix_log(LOG_LEVEL_DEBUG, "%s() value:'%s'", __function_name, value);
-
-	if (SUCCEED != is_uint64(value, &value_total))
-		goto unlock;
-
-	zbx_free(value);
-
-	zbx_snprintf(xpath, sizeof(xpath),
-			ZBX_XPATH_LN2("disk", "diskPath") "[.='%s']/.." ZBX_XPATH_LN("freeSpace"), fsname);
+	for (i = 0; i < vm->file_systems.values_num; i++)
+	{
+		fs = (zbx_vmware_fs_t *)vm->file_systems.values[i];
 
-	if (NULL == (value = zbx_xml_read_value(vm->details, xpath)))
-		goto unlock;
+		if (0 == strcmp(fs->path, fsname))
+			break;
+	}
 
-	if (SUCCEED != is_uint64(value, &value_free))
+	if (NULL == fs)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown file system path."));
 		goto unlock;
+	}
 
 	ret = SYSINFO_RET_OK;
 
 	if (NULL == mode || '\0' == *mode || 0 == strcmp(mode, "total"))
-		SET_UI64_RESULT(result, value_total);
+		SET_UI64_RESULT(result, fs->capacity);
 	else if (0 == strcmp(mode, "free"))
-		SET_UI64_RESULT(result, value_free);
+		SET_UI64_RESULT(result, fs->free_space);
 	else if (0 == strcmp(mode, "used"))
-		SET_UI64_RESULT(result, value_total - value_free);
+		SET_UI64_RESULT(result, fs->capacity - fs->free_space);
 	else if (0 == strcmp(mode, "pfree"))
-		SET_DBL_RESULT(result, 0 != value_total ? (double)(100.0 * value_free) / value_total : 0);
+		SET_DBL_RESULT(result, 0 != fs->capacity ? (double)(100.0 * fs->free_space) / fs->capacity : 0);
 	else if (0 == strcmp(mode, "pused"))
-		SET_DBL_RESULT(result, 100.0 - (0 != value_total ? (double)(100.0 * value_free) / value_total : 0));
+		SET_DBL_RESULT(result, 100.0 - (0 != fs->capacity ? 100.0 * fs->free_space / fs->capacity : 0));
 	else
 	{
 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
 		ret = SYSINFO_RET_FAIL;
 	}
 unlock:
-	zbx_free(value);
-
 	zbx_vmware_unlock();
 out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
Index: src/zabbix_server/vmware/vmware.c
===================================================================
--- src/zabbix_server/vmware/vmware.c	(revision 62677)
+++ src/zabbix_server/vmware/vmware.c	(working copy)
@@ -114,6 +114,107 @@
 }
 zbx_vmware_counter_t;
 
+/* the vm/hv object property mapping */
+typedef struct
+{
+	int		propid;
+	const char	*xpath;
+}
+zbx_vmware_propmap_t;
+
+/* performance counter value for a specific instance */
+typedef struct
+{
+	zbx_uint64_t	counterid;
+	char		*instance;
+	char		*value;
+}
+zbx_vmware_perf_value_t;
+
+/* performance data for a performance collector entity */
+typedef struct
+{
+	/* entity type: HostSystem or VirtualMachine */
+	char			*type;
+
+	/* entity id */
+	char			*id;
+
+	/* the performance counter values (see zbx_vmware_perfvalue_t) */
+	zbx_vector_ptr_t	values;
+}
+zbx_vmware_perf_data_t;
+
+static char	*hv_propmap[] = {
+	ZBX_XPATH_HV_QUICKSTATS("overallCpuUsage"),			/* ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE */
+	ZBX_XPATH_HV_CONFIG_PRODUCT("fullName"),			/* ZBX_VMWARE_HVPROP_FULL_NAME */
+	ZBX_XPATH_HV_HARDWARE("numCpuCores"),				/* ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES */
+	ZBX_XPATH_HV_HARDWARE("cpuMhz"),				/* ZBX_VMWARE_HVPROP_HW_CPU_MHZ */
+	ZBX_XPATH_HV_HARDWARE("cpuModel"),				/* ZBX_VMWARE_HVPROP_HW_CPU_MODEL */
+	ZBX_XPATH_HV_HARDWARE("numCpuThreads"), 			/* ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS */
+	ZBX_XPATH_HV_HARDWARE("memorySize"), 				/* ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE */
+	ZBX_XPATH_HV_HARDWARE("model"), 				/* ZBX_VMWARE_HVPROP_HW_MODEL */
+	ZBX_XPATH_HV_HARDWARE("uuid"), 					/* ZBX_VMWARE_HVPROP_HW_UUID */
+	ZBX_XPATH_HV_HARDWARE("vendor"), 				/* ZBX_VMWARE_HVPROP_HW_VENDOR */
+	ZBX_XPATH_HV_QUICKSTATS("overallMemoryUsage"),			/* ZBX_VMWARE_HVPROP_MEMORY_USED */
+	ZBX_XPATH_HV_SENSOR_STATUS("VMware Rollup Health State"),	/* ZBX_VMWARE_HVPROP_STATUS */
+	ZBX_XPATH_HV_QUICKSTATS("uptime"),				/* ZBX_VMWARE_HVPROP_UPTIME */
+	ZBX_XPATH_HV_CONFIG_PRODUCT("version"),				/* ZBX_VMWARE_HVPROP_VERSION */
+	ZBX_XPATH_HV_CONFIG("name")					/* ZBX_VMWARE_HVPROP_NAME */
+};
+
+
+static char	*vm_propmap[] = {
+	ZBX_XPATH_VM_CONFIG("numCpu"),					/* ZBX_VMWARE_VMPROP_CPU_NUM */
+	ZBX_XPATH_VM_QUICKSTATS("overallCpuUsage"),			/* ZBX_VMWARE_VMPROP_CPU_USAGE */
+	ZBX_XPATH_VM_CONFIG("name"),					/* ZBX_VMWARE_VMPROP_NAME */
+	ZBX_XPATH_VM_CONFIG("memorySizeMB"),				/* ZBX_VMWARE_VMPROP_MEMORY_SIZE */
+	ZBX_XPATH_VM_QUICKSTATS("balloonedMemory"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_BALLOONED */
+	ZBX_XPATH_VM_QUICKSTATS("compressedMemory"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_COMPRESSED */
+	ZBX_XPATH_VM_QUICKSTATS("swappedMemory"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_SWAPPED */
+	ZBX_XPATH_VM_QUICKSTATS("guestMemoryUsage"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_GUEST */
+	ZBX_XPATH_VM_QUICKSTATS("hostMemoryUsage"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_HOST */
+	ZBX_XPATH_VM_QUICKSTATS("privateMemory"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_PRIVATE */
+	ZBX_XPATH_VM_QUICKSTATS("sharedMemory"),			/* ZBX_VMWARE_VMPROP_MEMORY_SIZE_SHARED */
+	ZBX_XPATH_VM_RUNTIME("powerState"),				/* ZBX_VMWARE_VMPROP_POWER_STATE */
+	ZBX_XPATH_VM_STORAGE("committed"),				/* ZBX_VMWARE_VMPROP_STORAGE_COMMITED */
+	ZBX_XPATH_VM_STORAGE("unshared"),				/* ZBX_VMWARE_VMPROP_STORAGE_UNSHARED */
+	ZBX_XPATH_VM_STORAGE("uncommitted"),				/* ZBX_VMWARE_VMPROP_STORAGE_UNCOMMITTED */
+	ZBX_XPATH_VM_QUICKSTATS("uptimeSeconds")			/* ZBX_VMWARE_VMPROP_UPTIME */
+};
+
+/* hypervisor hashset support */
+zbx_hash_t	vmware_hv_hash(const void *data)
+{
+	zbx_vmware_hv_t	*hv = (zbx_vmware_hv_t *)data;
+
+	return ZBX_DEFAULT_STRING_HASH_ALGO(hv->uuid, strlen(hv->uuid), ZBX_DEFAULT_HASH_SEED);
+}
+
+int	vmware_hv_compare(const void *d1, const void *d2)
+{
+	zbx_vmware_hv_t	*hv1 = (zbx_vmware_hv_t *)d1;
+	zbx_vmware_hv_t	*hv2 = (zbx_vmware_hv_t *)d2;
+
+	return strcmp(hv1->uuid, hv2->uuid);
+}
+
+/* virtual machine index support */
+zbx_hash_t	vmware_vm_hash(const void *data)
+{
+	zbx_vmware_vm_index_t	*vmi = (zbx_vmware_vm_index_t *)data;
+
+	return ZBX_DEFAULT_STRING_HASH_ALGO(vmi->vm->uuid, strlen(vmi->vm->uuid), ZBX_DEFAULT_HASH_SEED);
+}
+
+int	vmware_vm_compare(const void *d1, const void *d2)
+{
+	zbx_vmware_vm_index_t	*vmi1 = (zbx_vmware_vm_index_t *)d1;
+	zbx_vmware_vm_index_t	*vmi2 = (zbx_vmware_vm_index_t *)d2;
+
+	return strcmp(vmi1->vm->uuid, vmi2->vm->uuid);
+}
+
 /*
  * SOAP support
  */
@@ -232,6 +333,96 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_free_perfvalue                                            *
+ *                                                                            *
+ * Purpose: frees perfvalue data structure                                    *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_free_perfvalue(zbx_vmware_perf_value_t *value)
+{
+	zbx_free(value->instance);
+	zbx_free(value->value);
+	zbx_free(value);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: vmware_free_perfdata                                             *
+ *                                                                            *
+ * Purpose: frees perfdata data structure                                     *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_free_perfdata(zbx_vmware_perf_data_t *data)
+{
+	zbx_free(data->id);
+	zbx_free(data->type);
+	zbx_vector_ptr_clean(&data->values, (zbx_mem_free_func_t)vmware_free_perfvalue);
+	zbx_vector_ptr_destroy(&data->values);
+
+	zbx_free(data);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: xml_read_props                                                   *
+ *                                                                            *
+ * Purpose: reads the vmware object properties by their xpaths from xml data  *
+ *                                                                            *
+ * Parameters: xml       - [IN] the xml data                                  *
+ *             propmap   - [IN] the xpaths of the properties to read          *
+ *             props_num - [IN] the number of properties to read              *
+ *                                                                            *
+ * Return value: an array of property values                                  *
+ *                                                                            *
+ * Comments: The array with property values must be freed by the caller.      *
+ *                                                                            *
+ ******************************************************************************/
+static char	**xml_read_props(const char *xml, char **propmap, int props_num)
+{
+	xmlDoc		*doc;
+	xmlXPathContext	*xpathCtx;
+	xmlXPathObject	*xpathObj;
+	xmlNodeSetPtr	nodeset;
+	xmlChar		*val;
+	char		**props;
+	int		i;
+
+	if (NULL == (doc = xmlReadMemory(xml, strlen(xml), ZBX_VM_NONAME_XML, NULL, 0)))
+		return NULL;
+
+	props = (char **)zbx_malloc(NULL, sizeof(char *) * props_num);
+	memset(props, 0, sizeof(char *) * props_num);
+
+	for (i = 0; i < props_num; i++)
+	{
+		xpathCtx = xmlXPathNewContext(doc);
+
+		if (NULL != (xpathObj = xmlXPathEvalExpression((const xmlChar *)propmap[i], xpathCtx)))
+		{
+			if (0 == xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+			{
+				nodeset = xpathObj->nodesetval;
+
+				if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1)))
+				{
+					props[i] = zbx_strdup(NULL, (char *)val);
+					xmlFree(val);
+				}
+			}
+
+			xmlXPathFreeObject(xpathObj);
+		}
+
+		xmlXPathFreeContext(xpathCtx);
+	}
+
+	xmlFreeDoc(doc);
+
+	return props;
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_shared_strdup                                             *
  *                                                                            *
  * Purpose: duplicates the specified string into shared memory                *
@@ -377,6 +568,32 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_props_shared_free                                         *
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store properties list         *
+ *                                                                            *
+ * Parameters: props     - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_props_shared_free(char **props, int props_num)
+{
+	int	i;
+
+	if (NULL == props)
+		return;
+
+	for (i = 0; i < props_num; i++)
+	{
+		if (NULL != props[i])
+			__vm_mem_free_func(props[i]);
+	}
+
+	__vm_mem_free_func(props);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_dev_shared_free                                           *
  *                                                                            *
  * Purpose: frees shared resources allocated to store vm device data          *
@@ -397,6 +614,23 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_fs_shared_free                                            *
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store file system object      *
+ *                                                                            *
+ * Parameters: dev   - [IN] the vm device                                     *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_fs_shared_free(zbx_vmware_fs_t *fs)
+{
+	if (NULL != fs->path)
+		__vm_mem_free_func(fs->path);
+
+	__vm_mem_free_func(fs);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_vm_shared_free                                            *
  *                                                                            *
  * Purpose: frees shared resources allocated to store virtual machine         *
@@ -409,28 +643,30 @@
 	zbx_vector_ptr_clean(&vm->devs, (zbx_mem_free_func_t)vmware_dev_shared_free);
 	zbx_vector_ptr_destroy(&vm->devs);
 
+	zbx_vector_ptr_clean(&vm->file_systems, (zbx_mem_free_func_t)vmware_fs_shared_free);
+	zbx_vector_ptr_destroy(&vm->file_systems);
+
 	if (NULL != vm->uuid)
 		__vm_mem_free_func(vm->uuid);
 
 	if (NULL != vm->id)
 		__vm_mem_free_func(vm->id);
 
-	if (NULL != vm->details)
-		__vm_mem_free_func(vm->details);
+	vmware_props_shared_free(vm->props, ZBX_VMWARE_VMPROPS_NUM);
 
 	__vm_mem_free_func(vm);
 }
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_hv_shared_free                                            *
+ * Function: vmware_hv_shared_clean                                           *
  *                                                                            *
  * Purpose: frees shared resources allocated to store vmware hypervisor       *
  *                                                                            *
  * Parameters: hv   - [IN] the vmware hypervisor                              *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_hv_shared_free(zbx_vmware_hv_t *hv)
+static void	vmware_hv_shared_clean(zbx_vmware_hv_t *hv)
 {
 	zbx_vector_ptr_clean(&hv->datastores, (zbx_mem_free_func_t)vmware_datastore_shared_free);
 	zbx_vector_ptr_destroy(&hv->datastores);
@@ -444,13 +680,10 @@
 	if (NULL != hv->id)
 		__vm_mem_free_func(hv->id);
 
-	if (NULL != hv->details)
-		__vm_mem_free_func(hv->details);
-
 	if (NULL != hv->clusterid)
 		__vm_mem_free_func(hv->clusterid);
 
-	__vm_mem_free_func(hv);
+	vmware_props_shared_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
 }
 
 /******************************************************************************
@@ -489,8 +722,16 @@
 {
 	if (NULL != data)
 	{
-		zbx_vector_ptr_clean(&data->hvs, (zbx_mem_free_func_t)vmware_hv_shared_free);
-		zbx_vector_ptr_destroy(&data->hvs);
+		zbx_hashset_iter_t	iter;
+		zbx_vmware_hv_t		*hv;
+
+		zbx_hashset_iter_reset(&data->hvs, &iter);
+		while (NULL != (hv = zbx_hashset_iter_next(&iter)))
+			vmware_hv_shared_clean(hv);
+
+		zbx_hashset_destroy(&data->hvs);
+
+		zbx_hashset_destroy(&data->vms_index);
 
 		zbx_vector_ptr_clean(&data->clusters, (zbx_mem_free_func_t)vmware_cluster_shared_free);
 		zbx_vector_ptr_destroy(&data->clusters);
@@ -653,6 +894,55 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_fs_shared_dup                                             *
+ *                                                                            *
+ * Purpose: copies vmware virtual machine file system object into shared      *
+ *          memory                                                            *
+ *                                                                            *
+ * Parameters: src   - [IN] the vmware device object                          *
+ *                                                                            *
+ * Return value: a duplicated vmware device object                            *
+ *                                                                            *
+ ******************************************************************************/
+static zbx_vmware_fs_t	*vmware_fs_shared_dup(const zbx_vmware_fs_t *src)
+{
+	zbx_vmware_fs_t	*fs;
+
+	fs = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_fs_t));
+	fs->path = vmware_shared_strdup(src->path);
+	fs->capacity = src->capacity;
+	fs->free_space = src->free_space;
+
+	return fs;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: vmware_props_shared_dup                                          *
+ *                                                                            *
+ * Purpose: copies object properties list into shared memory                  *
+ *                                                                            *
+ * Parameters: src       - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ * Return value: a duplicated object properties list                          *
+ *                                                                            *
+ ******************************************************************************/
+static char	**vmware_props_shared_dup(char ** const src, int props_num)
+{
+	char	**props;
+	int	i;
+
+	props = __vm_mem_malloc_func(NULL, sizeof(char *) * props_num);
+
+	for (i = 0; i < props_num; i++)
+		props[i] = vmware_shared_strdup(src[i]);
+
+	return props;
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_vm_shared_dup                                             *
  *                                                                            *
  * Purpose: copies vmware virtual machine object into shared memory           *
@@ -670,20 +960,24 @@
 	vm = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_vm_t));
 
 	VMWARE_VECTOR_CREATE(&vm->devs, ptr);
+	VMWARE_VECTOR_CREATE(&vm->file_systems, ptr);
 
 	vm->uuid = vmware_shared_strdup(src->uuid);
 	vm->id = vmware_shared_strdup(src->id);
-	vm->details = vmware_shared_strdup(src->details);
+	vm->props = vmware_props_shared_dup(src->props, ZBX_VMWARE_VMPROPS_NUM);
 
 	for (i = 0; i < src->devs.values_num; i++)
 		zbx_vector_ptr_append(&vm->devs, vmware_dev_shared_dup(src->devs.values[i]));
 
+	for (i = 0; i < src->file_systems.values_num; i++)
+		zbx_vector_ptr_append(&vm->file_systems, vmware_fs_shared_dup(src->file_systems.values[i]));
+
 	return vm;
 }
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_hv_shared_dup                                             *
+ * Function: vmware_hv_shared_copy                                            *
  *                                                                            *
  * Purpose: copies vmware hypervisor object into shared memory                *
  *                                                                            *
@@ -692,28 +986,24 @@
  * Return value: a duplicated vmware hypervisor object                        *
  *                                                                            *
  ******************************************************************************/
-static zbx_vmware_hv_t	*vmware_hv_shared_dup(const zbx_vmware_hv_t *src)
+static	void	vmware_hv_shared_copy(zbx_vmware_hv_t *dst, const zbx_vmware_hv_t *src)
 {
-	zbx_vmware_hv_t	*hv;
-	int		i;
+	int	i;
 
-	hv = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_hv_t));
+	VMWARE_VECTOR_CREATE(&dst->datastores, ptr);
+	VMWARE_VECTOR_CREATE(&dst->vms, ptr);
 
-	VMWARE_VECTOR_CREATE(&hv->datastores, ptr);
-	VMWARE_VECTOR_CREATE(&hv->vms, ptr);
+	dst->uuid = vmware_shared_strdup(src->uuid);
+	dst->id = vmware_shared_strdup(src->id);
+	dst->clusterid = vmware_shared_strdup(src->clusterid);
 
-	hv->uuid = vmware_shared_strdup(src->uuid);
-	hv->id = vmware_shared_strdup(src->id);
-	hv->details = vmware_shared_strdup(src->details);
-	hv->clusterid = vmware_shared_strdup(src->clusterid);
+	dst->props = vmware_props_shared_dup(src->props, ZBX_VMWARE_HVPROPS_NUM);
 
 	for (i = 0; i < src->datastores.values_num; i++)
-		zbx_vector_ptr_append(&hv->datastores, vmware_datastore_shared_dup(src->datastores.values[i]));
+		zbx_vector_ptr_append(&dst->datastores, vmware_datastore_shared_dup(src->datastores.values[i]));
 
 	for (i = 0; i < src->vms.values_num; i++)
-		zbx_vector_ptr_append(&hv->vms, vmware_vm_shared_dup(src->vms.values[i]));
-
-	return hv;
+		zbx_vector_ptr_append(&dst->vms, vmware_vm_shared_dup(src->vms.values[i]));
 }
 
 /******************************************************************************
@@ -727,24 +1017,42 @@
  * Return value: a duplicated vmware data object                              *
  *                                                                            *
  ******************************************************************************/
-static zbx_vmware_data_t	*vmware_data_shared_dup(const zbx_vmware_data_t *src)
+static zbx_vmware_data_t	*vmware_data_shared_dup(zbx_vmware_data_t *src)
 {
 	zbx_vmware_data_t	*data;
 	int			i;
+	zbx_hashset_iter_t	iter;
+	zbx_vmware_hv_t		*hv, hv_local;
 
 	data = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_data_t));
 
-	VMWARE_VECTOR_CREATE(&data->hvs, ptr);
+	zbx_hashset_create_ext(&data->hvs, 1, vmware_hv_hash, vmware_hv_compare, NULL, __vm_mem_malloc_func,
+			__vm_mem_realloc_func, __vm_mem_free_func);
 	VMWARE_VECTOR_CREATE(&data->clusters, ptr);
 
+	zbx_hashset_create_ext(&data->vms_index, 100, vmware_vm_hash, vmware_vm_compare, NULL, __vm_mem_malloc_func,
+			__vm_mem_realloc_func, __vm_mem_free_func);
+
 	data->events = vmware_shared_strdup(src->events);
 	data->error =  vmware_shared_strdup(src->error);
 
 	for (i = 0; i < src->clusters.values_num; i++)
 		zbx_vector_ptr_append(&data->clusters, vmware_cluster_shared_dup(src->clusters.values[i]));
 
-	for (i = 0; i < src->hvs.values_num; i++)
-		zbx_vector_ptr_append(&data->hvs, vmware_hv_shared_dup(src->hvs.values[i]));
+	zbx_hashset_iter_reset(&src->hvs, &iter);
+	while (NULL != (hv = zbx_hashset_iter_next(&iter)))
+	{
+
+		vmware_hv_shared_copy(&hv_local, hv);
+		hv = zbx_hashset_insert(&data->hvs, &hv_local, sizeof(hv_local));
+
+		for (i = 0; i < hv->vms.values_num; i++)
+		{
+			zbx_vmware_vm_index_t	vmi_local = {(zbx_vmware_vm_t *)hv->vms.values[i], hv};
+
+			zbx_hashset_insert(&data->vms_index, &vmi_local, sizeof(vmi_local));
+		}
+	}
 
 	return data;
 }
@@ -767,9 +1075,32 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_props_free                                                *
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store properties list         *
+ *                                                                            *
+ * Parameters: props     - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_props_free(char **props, int props_num)
+{
+	int	i;
+
+	if (NULL == props)
+		return;
+
+	for (i = 0; i < props_num; i++)
+		zbx_free(props[i]);
+
+	zbx_free(props);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_dev_free                                                  *
  *                                                                            *
- * Purpose: frees resources allocated to store vm device data                 *
+ * Purpose: frees resources allocated to store vm device object               *
  *                                                                            *
  * Parameters: dev   - [IN] the vm device                                     *
  *                                                                            *
@@ -783,6 +1114,21 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_fs_free                                                   *
+ *                                                                            *
+ * Purpose: frees resources allocated to store vm file system object          *
+ *                                                                            *
+ * Parameters: fs    - [IN] the file system                                   *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_fs_free(zbx_vmware_fs_t *fs)
+{
+	zbx_free(fs->path);
+	zbx_free(fs);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_vm_free                                                   *
  *                                                                            *
  * Purpose: frees resources allocated to store virtual machine                *
@@ -795,22 +1141,25 @@
 	zbx_vector_ptr_clean(&vm->devs, (zbx_mem_free_func_t)vmware_dev_free);
 	zbx_vector_ptr_destroy(&vm->devs);
 
+	zbx_vector_ptr_clean(&vm->file_systems, (zbx_mem_free_func_t)vmware_fs_free);
+	zbx_vector_ptr_destroy(&vm->file_systems);
+
 	zbx_free(vm->uuid);
 	zbx_free(vm->id);
-	zbx_free(vm->details);
+	vmware_props_free(vm->props, ZBX_VMWARE_VMPROPS_NUM);
 	zbx_free(vm);
 }
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_hv_free                                                   *
+ * Function: vmware_hv_clean                                                  *
  *                                                                            *
  * Purpose: frees resources allocated to store vmware hypervisor              *
  *                                                                            *
  * Parameters: hv   - [IN] the vmware hypervisor                              *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_hv_free(zbx_vmware_hv_t *hv)
+static void	vmware_hv_clean(zbx_vmware_hv_t *hv)
 {
 	zbx_vector_ptr_clean(&hv->datastores, (zbx_mem_free_func_t)vmware_datastore_free);
 	zbx_vector_ptr_destroy(&hv->datastores);
@@ -820,9 +1169,9 @@
 
 	zbx_free(hv->uuid);
 	zbx_free(hv->id);
-	zbx_free(hv->details);
 	zbx_free(hv->clusterid);
-	zbx_free(hv);
+
+	vmware_props_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
 }
 
 /******************************************************************************
@@ -853,8 +1202,14 @@
  ******************************************************************************/
 static void	vmware_data_free(zbx_vmware_data_t *data)
 {
-	zbx_vector_ptr_clean(&data->hvs, (zbx_mem_free_func_t)vmware_hv_free);
-	zbx_vector_ptr_destroy(&data->hvs);
+	zbx_hashset_iter_t	iter;
+	zbx_vmware_hv_t		*hv;
+
+	zbx_hashset_iter_reset(&data->hvs, &iter);
+	while (NULL != (hv = zbx_hashset_iter_next(&iter)))
+		vmware_hv_clean(hv);
+
+	zbx_hashset_destroy(&data->hvs);
 
 	zbx_vector_ptr_clean(&data->clusters, (zbx_mem_free_func_t)vmware_cluster_free);
 	zbx_vector_ptr_destroy(&data->clusters);
@@ -1286,19 +1641,20 @@
 
 /******************************************************************************
  *                                                                            *
- * Function: wmware_vm_get_nic_devices                                        *
+ * Function: vmware_vm_get_nic_devices                                        *
  *                                                                            *
  * Purpose: gets virtual machine network interface devices                    *
  *                                                                            *
- * Parameters: vm     - [IN] the virtual machine                              *
+ * Parameters: vm      - [OUT] the virtual machine                            *
+ *             details - [IN] a xml string containing virtual machine data    *
  *                                                                            *
  * Comments: The network interface devices are taken from vm device list      *
  *           filtered by macAddress key.                                      *
  *                                                                            *
  ******************************************************************************/
-static void	wmware_vm_get_nic_devices(zbx_vmware_vm_t *vm)
+static void	vmware_vm_get_nic_devices(zbx_vmware_vm_t *vm, const char *details)
 {
-	const char	*__function_name = "wmware_vm_get_nic_devices";
+	const char	*__function_name = "vmware_vm_get_nic_devices";
 	xmlDoc		*doc;
 	xmlXPathContext	*xpathCtx;
 	xmlXPathObject	*xpathObj;
@@ -1307,7 +1663,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	if (NULL == (doc = xmlReadMemory(vm->details, strlen(vm->details), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
+	if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
 		goto out;
 
 	xpathCtx = xmlXPathNewContext(doc);
@@ -1333,14 +1689,12 @@
 
 		dev = zbx_malloc(NULL, sizeof(zbx_vmware_dev_t));
 		dev->type =  ZBX_VMWARE_DEV_TYPE_NIC;
-		dev->instance = zbx_strdup(NULL, key);
+		dev->instance = key;
 		dev->label = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
 				"*[local-name()='deviceInfo']/*[local-name()='label']");
 
 		zbx_vector_ptr_append(&vm->devs, dev);
 		nics++;
-
-		zbx_free(key);
 	}
 clean:
 	if (NULL != xpathObj)
@@ -1354,16 +1708,17 @@
 
 /******************************************************************************
  *                                                                            *
- * Function: wmware_vm_get_disk_devices                                       *
+ * Function: vmware_vm_get_disk_devices                                       *
  *                                                                            *
  * Purpose: gets virtual machine virtual disk devices                         *
  *                                                                            *
- * Parameters: vm     - [IN] the virtual machine                              *
+ * Parameters: vm      - [OUT] the virtual machine                            *
+ *             details - [IN] a xml string containing virtual machine data    *
  *                                                                            *
  ******************************************************************************/
-static void	wmware_vm_get_disk_devices(zbx_vmware_vm_t *vm)
+static void	vmware_vm_get_disk_devices(zbx_vmware_vm_t *vm, const char *details)
 {
-	const char	*__function_name = "wmware_vm_get_disk_devices";
+	const char	*__function_name = "vmware_vm_get_disk_devices";
 	xmlDoc		*doc;
 	xmlXPathContext	*xpathCtx;
 	xmlXPathObject	*xpathObj;
@@ -1373,7 +1728,7 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	if (NULL == (doc = xmlReadMemory(vm->details, strlen(vm->details), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
+	if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
 		goto out;
 
 	xpathCtx = xmlXPathNewContext(doc);
@@ -1474,6 +1829,80 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_vm_get_file_systems                                       *
+ *                                                                            *
+ * Purpose: gets virtual machine network interface devices                    *
+ *                                                                            *
+ * Parameters: vm      - [OUT] the virtual machine                            *
+ *             details - [IN] a xml string containing virtual machine data    *
+ *                                                                            *
+ * Comments: The network interface devices are taken from vm device list      *
+ *           filtered by macAddress key.                                      *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_vm_get_file_systems(zbx_vmware_vm_t *vm, const char *details)
+{
+	const char	*__function_name = "vmware_vm_get_file_systems";
+	xmlDoc		*doc;
+	xmlXPathContext	*xpathCtx;
+	xmlXPathObject	*xpathObj;
+	xmlNodeSetPtr	nodeset;
+	int		i;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
+
+	if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, 0)))
+		goto out;
+
+	xpathCtx = xmlXPathNewContext(doc);
+
+	if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)ZBX_XPATH_VM_GUESTDISKS(), xpathCtx)))
+		goto clean;
+
+	if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+		goto clean;
+
+	nodeset = xpathObj->nodesetval;
+
+	for (i = 0; i < nodeset->nodeNr; i++)
+	{
+		zbx_vmware_fs_t	*fs;
+		char		*value;
+
+		if (NULL == (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='diskPath']")))
+			continue;
+
+		fs = zbx_malloc(NULL, sizeof(zbx_vmware_fs_t));
+		memset(fs, 0, sizeof(zbx_vmware_fs_t));
+
+		fs->path = value;
+
+		if (NULL != (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='capacity']")))
+		{
+			ZBX_STR2UINT64(fs->capacity, value);
+			zbx_free(value);
+		}
+
+		if (NULL != (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='freeSpace']")))
+		{
+			ZBX_STR2UINT64(fs->free_space, value);
+			zbx_free(value);
+		}
+
+		zbx_vector_ptr_append(&vm->file_systems, fs);
+	}
+clean:
+	if (NULL != xpathObj)
+		xmlXPathFreeObject(xpathObj);
+
+	xmlXPathFreeContext(xpathCtx);
+	xmlFreeDoc(doc);
+out:
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() found:%d", __function_name, vm->file_systems.values_num);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_service_get_vm_data                                       *
  *                                                                            *
  * Purpose: gets the virtual machine data                                     *
@@ -1502,7 +1931,7 @@
 					"<ns0:pathSet>config.uuid</ns0:pathSet>"	\
 					"<ns0:pathSet>config.instanceUuid</ns0:pathSet>"\
 					"<ns0:pathSet>summary</ns0:pathSet>"		\
-					"<ns0:pathSet>guest</ns0:pathSet>"		\
+					"<ns0:pathSet>guest.disk</ns0:pathSet>"		\
 				"</ns0:propSet>"					\
 				"<ns0:objectSet>"					\
 					"<ns0:obj type=\"VirtualMachine\">%s</ns0:obj>"	\
@@ -1569,7 +1998,7 @@
 	const char	*__function_name = "vmware_service_create_vm";
 
 	zbx_vmware_vm_t	*vm;
-	char		*value;
+	char		*value, *details = NULL;
 	const char	*uuid_xpath[3] = {NULL, ZBX_XPATH_VM_UUID(), ZBX_XPATH_VM_INSTANCE_UUID()};
 	int		ret = FAIL;
 
@@ -1579,21 +2008,27 @@
 	memset(vm, 0, sizeof(zbx_vmware_vm_t));
 
 	zbx_vector_ptr_create(&vm->devs);
+	zbx_vector_ptr_create(&vm->file_systems);
 
-	if (SUCCEED != vmware_service_get_vm_data(service, easyhandle, id, &vm->details, error))
+	if (SUCCEED != vmware_service_get_vm_data(service, easyhandle, id, &details, error))
 		goto out;
 
-	if (NULL == (value = zbx_xml_read_value(vm->details, uuid_xpath[service->type])))
+	if (NULL == (value = zbx_xml_read_value(details, uuid_xpath[service->type])))
 		goto out;
 
 	vm->uuid = value;
 	vm->id = zbx_strdup(NULL, id);
 
-	wmware_vm_get_nic_devices(vm);
-	wmware_vm_get_disk_devices(vm);
+	vm->props = xml_read_props(details, vm_propmap, ZBX_VMWARE_VMPROPS_NUM);
+
+	vmware_vm_get_nic_devices(vm, details);
+	vmware_vm_get_disk_devices(vm, details);
+	vmware_vm_get_file_systems(vm, details);
 
 	ret = SUCCEED;
 out:
+	zbx_free(details);
+
 	if (SUCCEED != ret)
 	{
 		vmware_vm_free(vm);
@@ -1769,31 +2204,30 @@
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_service_create_hv                                         *
+ * Function: vmware_service_init_hv                                           *
  *                                                                            *
- * Purpose: create vmware hypervisor object                                   *
+ * Purpose: initialize vmware hypervisor object                               *
  *                                                                            *
  * Parameters: service      - [IN] the vmware service                         *
  *             easyhandle   - [IN] the CURL handle                            *
  *             id           - [IN] the vmware hypervisor id                   *
+ *             hv           - [OUT] the hypervisor object (must be allocated) *
  *             error        - [OUT] the error message in the case of failure  *
  *                                                                            *
- * Return value: The created vmware hypervisor object or NULL if an error was *
- *               detected.                                                    *
+ * Return value: SUCCEED - the hypervisor object was initialized successfully *
+ *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static zbx_vmware_hv_t	*vmware_service_create_hv(zbx_vmware_service_t *service, CURL *easyhandle,
-		const char *id, char **error)
+static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandle, const char *id,
+		zbx_vmware_hv_t *hv, char **error)
 {
-	const char		*__function_name = "vmware_service_create_hv";
-	zbx_vmware_hv_t		*hv;
-	char			*value;
+	const char		*__function_name = "vmware_service_init_hv";
+	char			*value, *details = NULL;
 	zbx_vector_str_t	datastores, vms;
 	int			i, ret = FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() hvid:'%s'", __function_name, id);
 
-	hv = zbx_malloc(NULL, sizeof(zbx_vmware_hv_t));
 	memset(hv, 0, sizeof(zbx_vmware_hv_t));
 
 	zbx_vector_ptr_create(&hv->datastores);
@@ -1802,21 +2236,21 @@
 	zbx_vector_str_create(&datastores);
 	zbx_vector_str_create(&vms);
 
-	if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, &hv->details, error))
+	if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, &details, error))
 		goto out;
 
-	if (NULL == (value = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_HARDWARE("uuid"))))
+	hv->props = xml_read_props(details, hv_propmap, ZBX_VMWARE_HVPROPS_NUM);
+
+	if (NULL == hv->props[ZBX_VMWARE_HVPROP_HW_UUID])
 		goto out;
 
-	hv->uuid = value;
+	hv->uuid = zbx_strdup(NULL, hv->props[ZBX_VMWARE_HVPROP_HW_UUID]);
 	hv->id = zbx_strdup(NULL, id);
 
-	if (NULL != (value = zbx_xml_read_value(hv->details, "//*[@type='ClusterComputeResource']")))
-	{
+	if (NULL != (value = zbx_xml_read_value(details, "//*[@type='ClusterComputeResource']")))
 		hv->clusterid = value;
-	}
 
-	zbx_xml_read_values(hv->details, ZBX_XPATH_HV_DATASTORES(), &datastores);
+	zbx_xml_read_values(details, ZBX_XPATH_HV_DATASTORES(), &datastores);
 
 	for (i = 0; i < datastores.values_num; i++)
 	{
@@ -1826,7 +2260,7 @@
 			zbx_vector_ptr_append(&hv->datastores, datastore);
 	}
 
-	zbx_xml_read_values(hv->details, ZBX_XPATH_HV_VMS(), &vms);
+	zbx_xml_read_values(details, ZBX_XPATH_HV_VMS(), &vms);
 
 	for (i = 0; i < vms.values_num; i++)
 	{
@@ -1838,6 +2272,8 @@
 
 	ret = SUCCEED;
 out:
+	zbx_free(details);
+
 	zbx_vector_str_clean(&vms);
 	zbx_vector_str_destroy(&vms);
 
@@ -1845,14 +2281,11 @@
 	zbx_vector_str_destroy(&datastores);
 
 	if (SUCCEED != ret)
-	{
-		vmware_hv_free(hv);
-		hv = NULL;
-	}
+		vmware_hv_clean(hv);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
 
-	return hv;
+	return ret;
 }
 
 /******************************************************************************
@@ -2741,7 +3174,7 @@
 {
 	const char			*__function_name = "vmware_service_update_perf_entities";
 
-	int				now, i, j;
+	int				now, i;
 	zbx_vmware_perf_entity_t	*entity;
 	zbx_vmware_hv_t			*hv;
 	zbx_vmware_vm_t			*vm;
@@ -2766,14 +3199,14 @@
 	now = time(NULL);
 
 	/* update current performance entities */
-	for (i = 0; i < service->data->hvs.values_num; i++)
+	zbx_hashset_iter_reset(&service->data->hvs, &iter);
+	while (NULL != (hv = zbx_hashset_iter_next(&iter)))
 	{
-		hv = service->data->hvs.values[i];
 		vmware_service_add_perf_entity(service, "HostSystem", hv->id, hv_perfcounters, now);
 
-		for (j = 0; j < hv->vms.values_num; j++)
+		for (i = 0; i < hv->vms.values_num; i++)
 		{
-			vm = hv->vms.values[j];
+			vm = hv->vms.values[i];
 			vmware_service_add_perf_entity(service, "VirtualMachine", vm->id, vm_perfcounters, now);
 		}
 	}
@@ -2816,7 +3249,7 @@
 	data = zbx_malloc(NULL, sizeof(zbx_vmware_data_t));
 	memset(data, 0, sizeof(zbx_vmware_data_t));
 
-	zbx_vector_ptr_create(&data->hvs);
+	zbx_hashset_create(&data->hvs, 1, vmware_hv_hash, vmware_hv_compare);
 	zbx_vector_ptr_create(&data->clusters);
 
 	zbx_vector_str_create(&hvs);
@@ -2850,10 +3283,10 @@
 
 	for (i = 0; i < hvs.values_num; i++)
 	{
-		zbx_vmware_hv_t	*hv;
+		zbx_vmware_hv_t	hv_local;
 
-		if (NULL != (hv = vmware_service_create_hv(service, easyhandle, hvs.values[i], &data->error)))
-			zbx_vector_ptr_append(&data->hvs, hv);
+		if (SUCCEED == vmware_service_init_hv(service, easyhandle, hvs.values[i], &hv_local, &data->error))
+			zbx_hashset_insert(&data->hvs, &hv_local, sizeof(hv_local));
 	}
 
 	if (SUCCEED != vmware_service_get_event_data(service, easyhandle, &data->events, &data->error))
@@ -2898,18 +3331,18 @@
  *                                                                            *
  * Purpose: updates vmware performance statistics data                        *
  *                                                                            *
- * Parameters: service - [IN] the vmware service                              *
- *             type    - [IN] the performance entity type (HostSystem,        *
- *                            (VirtualMachine...)                             *
- *             id      - [IN] the performance entity id                       *
- *             doc     - [IN] the XML document containing performance counter *
- *                            values for all entities                         *
- *             node    - [IN] the XML node containing performance counter     *
+ * Parameters: pervalues - [OUT] the performance counter values               *
+ *             doc       - [IN] the XML document containing performance       *
+ *                              counter values for all entities               *
+ *             node      - [IN] the XML node containing performance counter   *
  *                            values for the specified entity                 *
  *                                                                            *
+ * Return value: SUCCEED - the performance entity data was parsed             *
+ *               FAIL    - the perofmance entity data did not contain valid   *
+ *                         values                                             *
+ *                                                                            *
  ******************************************************************************/
-static void	vmware_service_process_perf_entity_data(zbx_vmware_service_t *service, const char *type, const char *id,
-		xmlDoc *doc, xmlNode *node)
+static int	vmware_service_process_perf_entity_data(zbx_vector_ptr_t *pervalues, xmlDoc *doc, xmlNode *node)
 {
 	const char			*__function_name = "vmware_service_process_perf_entity_data";
 
@@ -2917,12 +3350,10 @@
 	xmlXPathObject			*xpathObj;
 	xmlNodeSetPtr			nodeset;
 	char				*instance, *counter, *value;
-	int				i, index, values = 0, valid_data = 0;
-	zbx_vmware_perf_entity_t	*entity;
-	zbx_uint64_t			counterid;
-	zbx_vmware_perf_counter_t	*perfcounter;
+	int				i, values = 0, ret = FAIL;
+	zbx_vmware_perf_value_t		*perfvalue;
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s", __function_name, type, id);
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
 	xpathCtx = xmlXPathNewContext(doc);
 	xpathCtx->node = node;
@@ -2933,9 +3364,6 @@
 	if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
 		goto out;
 
-	if (NULL == (entity = zbx_vmware_service_get_perf_entity(service, type, id)))
-		goto out;
-
 	nodeset = xpathObj->nodesetval;
 
 	for (i = 0; i < nodeset->nodeNr; i++)
@@ -2948,23 +3376,19 @@
 
 		if (NULL != value && NULL != counter)
 		{
-			ZBX_STR2UINT64(counterid, counter);
+			perfvalue = zbx_malloc(NULL, sizeof(zbx_vmware_perf_value_t));
 
-			if (FAIL != (index = zbx_vector_ptr_bsearch(&entity->counters, &counterid,
-					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
-			{
-				zbx_ptr_pair_t	perfvalue;
-				perfcounter = (zbx_vmware_perf_counter_t *)entity->counters.values[index];
+			ZBX_STR2UINT64(perfvalue->counterid, counter);
+			perfvalue->instance = (NULL != instance ? instance : zbx_strdup(NULL, ""));
+			perfvalue->value = value;
 
-				perfvalue.first = vmware_shared_strdup(NULL != instance ? instance : "");
-				perfvalue.second = vmware_shared_strdup(value);
+			zbx_vector_ptr_append(pervalues, perfvalue);
 
-				zbx_vector_ptr_pair_append_ptr(&perfcounter->values, &perfvalue);
-				values++;
+			if (FAIL == ret && 0 != strcmp(value, "-1"))
+				ret = SUCCEED;
 
-				if (0 == valid_data && 0 != strcmp(value, "-1"))
-					valid_data = 1;
-			}
+			instance = NULL;
+			value = NULL;
 		}
 
 		zbx_free(counter);
@@ -2972,15 +3396,6 @@
 		zbx_free(value);
 	}
 
-	/* No valid data found - all metrics have -1 value. In this case clear the counter values. */
-	if (0 == valid_data)
-	{
-		for (i = 0; i < entity->counters.values_num; i++)
-		{
-			perfcounter = (zbx_vmware_perf_counter_t *)entity->counters.values[i];
-			vmware_vector_ptr_pair_shared_clean(&perfcounter->values);
-		}
-	}
 out:
 	if (NULL != xpathObj)
 		xmlXPathFreeObject(xpathObj);
@@ -2988,6 +3403,8 @@
 	xmlXPathFreeContext(xpathCtx);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() values:%d", __function_name, values);
+
+	return ret;
 }
 
 /******************************************************************************
@@ -2996,11 +3413,11 @@
  *                                                                            *
  * Purpose: updates vmware performance statistics data                        *
  *                                                                            *
- * Parameters: service - [IN] the vmware service                              *
- *             data    - [IN] the performance data                            *
+ * Parameters: perfdata - [OUT] performance entity data                       *
+ *             data     - [IN] the performance data                           *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_service_parse_perf_data(zbx_vmware_service_t *service, const char *data)
+static void	vmware_service_parse_perf_data(zbx_vector_ptr_t *perfdata, const char *xml)
 {
 	const char		*__function_name = "vmware_service_parse_perf_data";
 
@@ -3009,11 +3426,10 @@
 	xmlXPathObject		*xpathObj;
 	xmlNodeSetPtr		nodeset;
 	int			i;
-	char			*id, *type;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	if (NULL == (doc = xmlReadMemory(data, strlen(data), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
+	if (NULL == (doc = xmlReadMemory(xml, strlen(xml), ZBX_VM_NONAME_XML, NULL, XML_PARSE_HUGE)))
 		goto out;
 
 	xpathCtx = xmlXPathNewContext(doc);
@@ -3028,14 +3444,22 @@
 
 	for (i = 0; i < nodeset->nodeNr; i++)
 	{
-		id = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']");
-		type = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']/@type");
+		zbx_vmware_perf_data_t 	*data;
+		int			ret = FAIL;
 
-		if (NULL != type && NULL != id)
-			vmware_service_process_perf_entity_data(service, type, id, doc, nodeset->nodeTab[i]);
+		data = zbx_malloc(NULL, sizeof(zbx_vmware_perf_data_t));
 
-		zbx_free(type);
-		zbx_free(id);
+		data->id = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']");
+		data->type = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']/@type");
+		zbx_vector_ptr_create(&data->values);
+
+		if (NULL != data->type && NULL != data->id)
+			ret = vmware_service_process_perf_entity_data(&data->values, doc, nodeset->nodeTab[i]);
+
+		if (SUCCEED == ret)
+			zbx_vector_ptr_append(perfdata, data);
+		else
+			vmware_free_perfdata(data);
 	}
 clean:
 	if (NULL != xpathObj)
@@ -3049,6 +3473,58 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_service_parse_perf_data                                   *
+ *                                                                            *
+ * Purpose: updates vmware performance statistics data                        *
+ *                                                                            *
+ * Parameters: service - [IN] the vmware service                              *
+ *             data    - [IN] the performance data                            *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_service_copy_perf_data(zbx_vmware_service_t *service, zbx_vector_ptr_t *perfdata)
+{
+	const char			*__function_name = "vmware_service_copy_perf_data";
+
+	int				i, j, index;
+	zbx_vmware_perf_data_t		*data;
+	zbx_vmware_perf_value_t		*value;
+	zbx_vmware_perf_entity_t	*entity;
+	zbx_vmware_perf_counter_t	*perfcounter;
+	zbx_ptr_pair_t			perfvalue;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
+
+	for (i = 0; i < perfdata->values_num; i++)
+	{
+		data = (zbx_vmware_perf_data_t *)perfdata->values[i];
+
+		if (NULL == (entity = zbx_vmware_service_get_perf_entity(service, data->type, data->id)))
+			continue;
+
+		for (j = 0; j < data->values.values_num; j++)
+		{
+			value = (zbx_vmware_perf_value_t *)data->values.values[j];
+
+			if (FAIL == (index = zbx_vector_ptr_bsearch(&entity->counters, &value->counterid,
+					ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
+			{
+				continue;
+			}
+
+			perfcounter = (zbx_vmware_perf_counter_t *)entity->counters.values[index];
+
+			perfvalue.first = vmware_shared_strdup(value->instance);
+			perfvalue.second = vmware_shared_strdup(value->value);
+
+			zbx_vector_ptr_pair_append_ptr(&perfcounter->values, &perfvalue);
+		}
+	}
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_service_update_perf                                       *
  *                                                                            *
  * Purpose: updates vmware statistics data                                    *
@@ -3062,13 +3538,14 @@
 
 	CURL				*easyhandle = NULL;
 	struct curl_slist		*headers = NULL;
-	int				err, opt, i, j;
+	int				err, opt, i, j, ret = FAIL;
 	char				*error = NULL, *tmp = NULL;
 	size_t				tmp_alloc = 0, tmp_offset = 0;
 	zbx_vector_ptr_t		entities;
 	zbx_vmware_perf_entity_t	*entity, *local_entity;
 	zbx_vmware_perf_counter_t	*counter;
 	zbx_hashset_iter_t		iter;
+	zbx_vector_ptr_t		perfdata;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() %s@%s", __function_name, service->username, service->url);
 
@@ -3189,7 +3666,15 @@
 
 	page.offset = 0;
 
-	if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
+	if (CURLE_OK == (err = curl_easy_perform(easyhandle)))
+	{
+		/* parse performance data into local memory */
+		zbx_vector_ptr_create(&perfdata);
+		vmware_service_parse_perf_data(&perfdata, page.data);
+
+		ret = SUCCEED;
+	}
+	else
 		error = zbx_strdup(error, curl_easy_strerror(err));
 clean:
 	zbx_free(tmp);
@@ -3197,9 +3682,10 @@
 	curl_slist_free_all(headers);
 	curl_easy_cleanup(easyhandle);
 out:
+
 	zbx_vmware_lock();
 
-	if (NULL != error)
+	if (FAIL == ret)
 	{
 		zabbix_log(LOG_LEVEL_WARNING, "cannot update performance statistics of vmware service \"%s\": %s",
 				service->url, error);
@@ -3207,8 +3693,9 @@
 	}
 	else
 	{
+		/* clean old performance data and copy the new data into shared memory */
 		vmware_entities_shared_clean_stats(&service->entities);
-		vmware_service_parse_perf_data(service, page.data);
+		vmware_service_copy_perf_data(service, &perfdata);
 	}
 
 	service->state &= ~(ZBX_VMWARE_STATE_UPDATING_PERF);
@@ -3216,6 +3703,14 @@
 
 	zbx_vmware_unlock();
 
+	if (FAIL != ret)
+	{
+		/* free performance data in local memory */
+		zbx_vector_ptr_clean(&perfdata, (zbx_mem_free_func_t)vmware_free_perfdata);
+		zbx_vector_ptr_destroy(&perfdata);
+	}
+
+
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): processed " ZBX_FS_SIZE_T " bytes of data", __function_name,
 			(zbx_fs_size_t)page.offset);
 }
Index: src/zabbix_server/vmware/vmware.h
===================================================================
--- src/zabbix_server/vmware/vmware.h	(revision 62677)
+++ src/zabbix_server/vmware/vmware.h	(working copy)
@@ -93,13 +93,23 @@
 }
 zbx_vmware_dev_t;
 
+/* file system data */
+typedef struct
+{
+	char		*path;
+	zbx_uint64_t	capacity;
+	zbx_uint64_t	free_space;
+}
+zbx_vmware_fs_t;
+
 /* the vmware virtual machine data */
 typedef struct
 {
 	char			*uuid;
 	char			*id;
-	char			*details;
+	char			**props;
 	zbx_vector_ptr_t	devs;
+	zbx_vector_ptr_t	file_systems;
 }
 zbx_vmware_vm_t;
 
@@ -108,13 +118,21 @@
 {
 	char			*uuid;
 	char			*id;
-	char			*details;
 	char			*clusterid;
+	char			**props;
 	zbx_vector_ptr_t	datastores;
 	zbx_vector_ptr_t	vms;
 }
 zbx_vmware_hv_t;
 
+/* index virtual machines by uuids */
+typedef struct
+{
+	zbx_vmware_vm_t	*vm;
+	zbx_vmware_hv_t	*hv;
+}
+zbx_vmware_vm_index_t;
+
 /* the vmware cluster data */
 typedef struct
 {
@@ -130,7 +148,8 @@
 	char	*error;
 	char	*events;
 
-	zbx_vector_ptr_t	hvs;
+	zbx_hashset_t		hvs;
+	zbx_hashset_t		vms_index;
 	zbx_vector_ptr_t	clusters;
 }
 zbx_vmware_data_t;
@@ -163,7 +182,7 @@
 	/* list of entities to monitor with performance counters */
 	zbx_hashset_t		entities;
 
-	/* The service data object that is swapped with a new one during service update */
+	/* the service data object that is swapped with a new one during service update */
 	zbx_vmware_data_t	*data;
 }
 zbx_vmware_service_t;
@@ -225,6 +244,10 @@
 	"/*/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='config.hardware']]"	\
 		"/*[local-name()='val']/*[local-name()='" property "']"
 
+#define ZBX_XPATH_VM_GUESTDISKS()									\
+	"/*/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='guest.disk']]"		\
+	"/*/*[local-name()='GuestDiskInfo']"
+
 #define ZBX_XPATH_VM_UUID()										\
 	"/*/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='config.uuid']]"		\
 		"/*[local-name()='val']"
@@ -257,7 +280,6 @@
 		"[*[local-name()='name'][text()='" sensor "']]"						\
 		"/*[local-name()='healthState']/*[local-name()='key']"
 
-
 #define ZBX_XPATH_VMWARE_ABOUT(property)								\
 	"/*/*/*/*/*[local-name()='about']/*[local-name()='" property "']"
 
@@ -270,6 +292,45 @@
 char	*zbx_xml_read_node_value(xmlDoc *doc, xmlNode *node, const char *xpath);
 int	zbx_xml_read_values(const char *data, const char *xpath, zbx_vector_str_t *values);
 
+/* hypervisor properties */
+#define ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE		0
+#define ZBX_VMWARE_HVPROP_FULL_NAME			1
+#define ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES		2
+#define ZBX_VMWARE_HVPROP_HW_CPU_MHZ			3
+#define ZBX_VMWARE_HVPROP_HW_CPU_MODEL			4
+#define ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS		5
+#define ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE		6
+#define ZBX_VMWARE_HVPROP_HW_MODEL			7
+#define ZBX_VMWARE_HVPROP_HW_UUID			8
+#define ZBX_VMWARE_HVPROP_HW_VENDOR			9
+#define ZBX_VMWARE_HVPROP_MEMORY_USED			10
+#define ZBX_VMWARE_HVPROP_STATUS			11
+#define ZBX_VMWARE_HVPROP_UPTIME			12
+#define ZBX_VMWARE_HVPROP_VERSION			13
+#define ZBX_VMWARE_HVPROP_NAME				14
+
+#define ZBX_VMWARE_HVPROPS_NUM				15
+
+/* virtual machine properties */
+#define ZBX_VMWARE_VMPROP_CPU_NUM			0
+#define ZBX_VMWARE_VMPROP_CPU_USAGE			1
+#define ZBX_VMWARE_VMPROP_NAME				2
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE			3
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_BALLOONED		4
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_COMPRESSED	5
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_SWAPPED		6
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_GUEST	7
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_HOST	8
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_PRIVATE		9
+#define ZBX_VMWARE_VMPROP_MEMORY_SIZE_SHARED		10
+#define ZBX_VMWARE_VMPROP_POWER_STATE			11
+#define ZBX_VMWARE_VMPROP_STORAGE_COMMITED		12
+#define ZBX_VMWARE_VMPROP_STORAGE_UNSHARED		13
+#define ZBX_VMWARE_VMPROP_STORAGE_UNCOMMITTED		14
+#define ZBX_VMWARE_VMPROP_UPTIME			15
+
+#define ZBX_VMWARE_VMPROPS_NUM				16
+
 #endif	/* defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL) */
 
 #endif	/* ZABBIX_VMWARE_H */
Index: .
===================================================================
--- .	(revision 62677)
+++ .	(working copy)

Property changes on: .
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /branches/dev/ZBXNEXT-3106:r57944-57946,57959,57964,58021,58054,58082
