Index: include/zbxmodules.h
===================================================================
--- include/zbxmodules.h	(revision 61401)
+++ include/zbxmodules.h	(revision 61924)
@@ -20,7 +20,11 @@
 #ifndef ZABBIX_ZBXMODULES_H
 #define ZABBIX_ZBXMODULES_H
 
-int	load_modules(const char *path, char **file_names, int timeout, int verbose);
-void	unload_modules();
+#include	"dbcache.h"
 
+int	zbx_load_modules(const char *path, char **file_names, int timeout, int verbose);
+void	zbx_unload_modules();
+
+void	zbx_sync_history_with_modules(zbx_dc_history_t history, int history_num);
+
 #endif
Index: include/dbcache.h
===================================================================
--- include/dbcache.h	(revision 61401)
+++ include/dbcache.h	(revision 61924)
@@ -24,6 +24,7 @@
 #include "comms.h"
 #include "sysinfo.h"
 #include "zbxalgo.h"
+#include "module.h"
 
 #define ZBX_SYNC_PARTIAL	0
 #define	ZBX_SYNC_FULL		1
@@ -585,4 +586,10 @@
 
 void	zbx_free_tag(zbx_tag_t *tag);
 
+typedef struct zbx_dc_history	*zbx_dc_history_t;
+
+int		zbx_next_history_index(zbx_dc_history_t history, int history_num, int *index);
+void		zbx_get_history_field(zbx_dc_history_t history, int index, zabbix_label_t label, zabbix_basic_t *res);
+zbx_uint64_t	zbx_get_history_type(zbx_dc_history_t history, int index);
+
 #endif
Index: include/module.h
===================================================================
--- include/module.h	(revision 61401)
+++ include/module.h	(revision 61924)
@@ -22,6 +22,66 @@
 
 #include "zbxtypes.h"
 
+/* Zabbix API */
+
+/* these definitions MUST stay the same unless we decide to release new API version */
+
+typedef unsigned char	zabbix_error_t;
+typedef unsigned char	zabbix_label_t;
+typedef zbx_uint64_t	zabbix_handle_t;
+
+/* convenience wrapper to access contents of buffers passed to */
+/* zabbix_get_object_member() and zabbix_get_vector_element () */
+/* WILL NOT WORK if Zabbix binary and module binary use different endianness */
+typedef union
+{
+	char		bytes[8];
+	zbx_uint64_t	as_uint64;
+	double		as_double;
+	char		*as_string;
+	zabbix_handle_t	as_object;
+	zabbix_handle_t	as_vector;
+}
+zabbix_basic_t;
+
+/* return codes */
+#define ZABBIX_SUCCESS		0
+#define ZABBIX_END_OF_VECTOR	1
+#define ZABBIX_INVALID_HANDLE	2
+#define ZABBIX_NOT_AN_OBJECT	3
+#define ZABBIX_NOT_A_VECTOR	4
+#define ZABBIX_NO_SUCH_MEMBER	5
+#define ZABBIX_INTERNAL_ERROR	6
+/* NB! don't forget to update zabbix_error_message() and ZBX_MAX_ERROR in modules.c when adding new error codes */
+
+/* object labels */
+#define ZABBIX_HISTORY_RECORD_ITEMID			1
+#define ZABBIX_HISTORY_RECORD_CLOCK			2
+#define ZABBIX_HISTORY_RECORD_NS			3
+#define ZABBIX_HISTORY_RECORD_VALUETYPE			4
+#define ZABBIX_HISTORY_RECORD_VALUE			5
+#define ZABBIX_HISTORY_RECORD_VALUELOG_VALUE		6
+#define ZABBIX_HISTORY_RECORD_VALUELOG_TIMESTAMP	7
+#define ZABBIX_HISTORY_RECORD_VALUELOG_SOURCE		8
+#define ZABBIX_HISTORY_RECORD_VALUELOG_LOGEVENTID	9
+#define ZABBIX_HISTORY_RECORD_VALUELOG_SEVERITY		10
+
+/* types */
+#define ZABBIX_TYPE_UINT64	1
+#define ZABBIX_TYPE_DOUBLE	2
+#define ZABBIX_TYPE_STRING	3
+#define ZABBIX_TYPE_OBJECT	4
+#define ZABBIX_TYPE_VECTOR	5
+
+unsigned char	zabbix_version(void);
+
+const char	*zabbix_error_message(zabbix_error_t error);
+
+zabbix_error_t	zabbix_get_object_member(zabbix_handle_t object, zabbix_label_t label, void *buffer);
+zabbix_error_t	zabbix_get_vector_element(zabbix_handle_t vector, void *buffer);
+
+/* module API */
+
 #define ZBX_MODULE_OK	0
 #define ZBX_MODULE_FAIL	-1
 
Index: src/zabbix_proxy/proxy.c
===================================================================
--- src/zabbix_proxy/proxy.c	(revision 61401)
+++ src/zabbix_proxy/proxy.c	(revision 61924)
@@ -239,6 +239,10 @@
 char	*CONFIG_TLS_PSK_IDENTITY	= NULL;
 char	*CONFIG_TLS_PSK_FILE		= NULL;
 
+extern int		(*next_history_index)(zbx_dc_history_t, int, int *);
+extern void		(*get_history_field)(zbx_dc_history_t, int, zabbix_label_t, zabbix_basic_t *);
+extern zbx_uint64_t	(*get_history_type)(zbx_dc_history_t, int);
+
 int	get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
 
 int	get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num)
@@ -883,7 +887,11 @@
 		exit(EXIT_FAILURE);
 	}
 #endif
-	if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
+	next_history_index = zbx_next_history_index;
+	get_history_field = zbx_get_history_field;
+	get_history_type = zbx_get_history_type;
+
+	if (FAIL == zbx_load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
 	{
 		zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
 		exit(EXIT_FAILURE);
@@ -1085,7 +1093,7 @@
 
 	free_selfmon_collector();
 
-	unload_modules();
+	zbx_unload_modules();
 
 	zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Proxy stopped. Zabbix %s (revision %s).",
 			ZABBIX_VERSION, ZABBIX_REVISION);
Index: src/zabbix_server/server.c
===================================================================
--- src/zabbix_server/server.c	(revision 61401)
+++ src/zabbix_server/server.c	(revision 61924)
@@ -238,6 +238,10 @@
 char	*CONFIG_TLS_PSK_FILE		= NULL;
 #endif
 
+extern int		(*next_history_index)(zbx_dc_history_t, int, int *);
+extern void		(*get_history_field)(zbx_dc_history_t, int, zabbix_label_t, zabbix_basic_t *);
+extern zbx_uint64_t	(*get_history_type)(zbx_dc_history_t, int);
+
 int	get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
 
 int	get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num)
@@ -850,7 +854,11 @@
 		exit(EXIT_FAILURE);
 	}
 #endif
-	if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
+	next_history_index = zbx_next_history_index;
+	get_history_field = zbx_get_history_field;
+	get_history_type = zbx_get_history_type;
+
+	if (FAIL == zbx_load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
 	{
 		zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
 		exit(EXIT_FAILURE);
@@ -1087,7 +1095,7 @@
 
 	zbx_uninitialize_events();
 
-	unload_modules();
+	zbx_unload_modules();
 
 	zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Server stopped. Zabbix %s (revision %s).",
 			ZABBIX_VERSION, ZABBIX_REVISION);
Index: src/libs/zbxmodules/modules.c
===================================================================
--- src/libs/zbxmodules/modules.c	(revision 61401)
+++ src/libs/zbxmodules/modules.c	(revision 61924)
@@ -30,23 +30,102 @@
 #define ZBX_MODULE_FUNC_ITEM_PROCESS	"zbx_module_item_process"
 #define ZBX_MODULE_FUNC_ITEM_TIMEOUT	"zbx_module_item_timeout"
 #define ZBX_MODULE_FUNC_UNINIT		"zbx_module_uninit"
+#define ZBX_MODULE_FUNC_HISTORY_WRITE	"zbx_module_history_write"
 
-static void	**modules = NULL;
+/* these function pointers will be initialized for server and proxy in runtime, agent does not need them */
+int		(*next_history_index)(zbx_dc_history_t, int, int *);
+void		(*get_history_field)(zbx_dc_history_t, int, zabbix_label_t, zabbix_basic_t *);
+zbx_uint64_t	(*get_history_type)(zbx_dc_history_t, int);
 
+typedef struct
+{
+	void		*lib;
+	char		*name;
+	zabbix_error_t	(*func_history_write)(zabbix_handle_t);
+}
+zbx_module_t;
+
+static zbx_module_t	*modules = NULL;
+
 /******************************************************************************
  *                                                                            *
+ * Comments: public API function, see documentation for more details          *
+ *                                                                            *
+ ******************************************************************************/
+unsigned char	zabbix_version(void)
+{
+	return ZABBIX_VERSION_MAJOR * 10 + ZABBIX_VERSION_MINOR;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Comments: public API function, see documentation for more details          *
+ *                                                                            *
+ ******************************************************************************/
+const char	*zabbix_error_message(zabbix_error_t error)
+{
+/* refers to the last error in error_messages */
+#define ZBX_MAX_ERROR	7
+
+	/* the order of messages MUST match the order of return code defines in module.h */
+	static const char * const	error_messages[ZBX_MAX_ERROR + 1] =
+	{
+		"call was successful",							/* 0 ZABBIX_SUCCESS */
+		"vector iteration reached its end",					/* 1 ZABBIX_END_OF_VECTOR */
+		"provided handle wasn't created properly or its lifetime has expired",	/* 2 ZABBIX_INVALID_HANDLE */
+		"provided handle is not an object handle",				/* 3 ZABBIX_NOT_AN_OBJECT */
+		"provided handle is not a vector handle",				/* 4 ZABBIX_NOT_A_VECTOR */
+		"object has no member associated with provided label",			/* 5 ZABBIX_NO_SUCH_MEMBER */
+		"internal error, please report to Zabbix developers",			/* 6 ZABBIX_INTERNAL_ERROR */
+		"unknown error"								/* 7 ZBX_MAX_ERROR */
+	};
+
+	if (ZABBIX_SUCCESS <= error && error < ZBX_MAX_ERROR)
+		return error_messages[error];
+
+	return error_messages[ZBX_MAX_ERROR];
+
+#undef ZBX_MAX_ERROR
+}
+
+#define ZBX_HANDLE_HISTORY			1
+#define ZBX_HANDLE_HISTORY_RECORD		2
+#define ZBX_HANDLE_HISTORY_RECORD_VALUELOG	3
+
+typedef struct
+{
+	int	type;	/* one of ZBX_HANDLE_* defines */
+	void	*data;	/* private handle data needed for implementation */
+}
+zbx_handle_t;
+
+static zbx_vector_ptr_t	handle_pool;
+
+typedef struct
+{
+	zbx_dc_history_t	history;
+	int			history_num;
+	int			index;
+}
+zbx_history_handle_data_t;
+
+/******************************************************************************
+ *                                                                            *
  * Function: register_module                                                  *
  *                                                                            *
  * Purpose: Add module to the list of loaded modules (dynamic libraries).     *
  *          It skips a module if it is already registered.                    *
  *                                                                            *
- * Parameters: module - library handler                                       *
+ * Parameters: lib                - library handle                            *
+ *             name               - library name                              *
+ *             func_history_write - library function which will be invoked    *
+ *                                  to sync historical data with module       *
  *                                                                            *
  * Return value: SUCCEED - if module is successfully registered               *
  *               FAIL - if module is already registered                       *
  *                                                                            *
  ******************************************************************************/
-static int	register_module(void *module)
+static int	register_module(void *lib, char *name, zabbix_error_t (*func_history_write)(zabbix_handle_t))
 {
 	const char	*__function_name = "register_module";
 
@@ -56,20 +135,23 @@
 
 	if (NULL == modules)
 	{
-		modules = zbx_malloc(modules, sizeof(void *));
-		modules[0] = NULL;
+		zbx_vector_ptr_create(&handle_pool);
+		modules = zbx_malloc(modules, sizeof(zbx_module_t));
+		modules[0].lib = NULL;
 	}
 
-	while (NULL != modules[i])
+	while (NULL != modules[i].lib)
 	{
-		if (module == modules[i])	/* a module is already registered */
+		if (lib == modules[i].lib)	/* a module is already registered */
 			goto out;
 		i++;
 	}
 
-	modules = zbx_realloc(modules, (i + 2) * sizeof(void *));
-	modules[i] = module;
-	modules[i + 1] = NULL;
+	modules = zbx_realloc(modules, (i + 2) * sizeof(zbx_module_t));
+	modules[i].lib = lib;
+	modules[i].name = zbx_strdup(NULL, name);
+	modules[i].func_history_write = func_history_write;
+	modules[i + 1].lib = NULL;
 
 	ret = SUCCEED;
 out:
@@ -94,7 +176,7 @@
  *               FAIL - loading of modules failed                             *
  *                                                                            *
  ******************************************************************************/
-int	load_modules(const char *path, char **file_names, int timeout, int verbose)
+int	zbx_load_modules(const char *path, char **file_names, int timeout, int verbose)
 {
 	const char	*__function_name = "load_modules";
 
@@ -104,10 +186,14 @@
 	int		(*func_init)(), (*func_version)();
 	ZBX_METRIC	*(*func_list)();
 	void		(*func_timeout)();
+	zabbix_error_t	(*func_history_write)(zabbix_handle_t);
 	int		i, ret = FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
+	if (8 != sizeof(zabbix_basic_t))	/* all basic types for Zabbix <-> module data transfer are 64 bit */
+		THIS_SHOULD_NEVER_HAPPEN;
+
 	for (file_name = file_names; NULL != *file_name; file_name++)
 	{
 		zbx_snprintf(full_name, sizeof(full_name), "%s/%s", path, *file_name);
@@ -171,8 +257,15 @@
 			continue;
 		}
 
-		if (SUCCEED == register_module(lib))
+		func_history_write = (zabbix_error_t (*)(zabbix_handle_t))dlsym(lib, ZBX_MODULE_FUNC_HISTORY_WRITE);
+		if (NULL == func_history_write)
 		{
+			zabbix_log(LOG_LEVEL_DEBUG, "cannot find \"" ZBX_MODULE_FUNC_HISTORY_WRITE "()\""
+					" function in module \"%s\": %s", *file_name, dlerror());
+		}
+
+		if (SUCCEED == register_module(lib, *file_name, func_history_write))
+		{
 			ZBX_METRIC	*metrics;
 
 			metrics = func_list();
@@ -213,6 +306,87 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: zbx_handle_alloc                                                 *
+ *                                                                            *
+ * Purpose: Creates a new handle of desired type in the handle pool, attaches *
+ *          provided private handle data to it and returns a public handle    *
+ *          identifier.                                                       *
+ *                                                                            *
+ ******************************************************************************/
+static zabbix_handle_t	zbx_handle_alloc(int type, void *data)
+{
+	zabbix_handle_t	handleid;
+	zbx_handle_t	*handle;
+
+	handleid = (zabbix_handle_t)handle_pool.values_num;
+	handle = zbx_malloc(NULL, sizeof(zbx_handle_t));
+	handle->type = type;
+	handle->data = data;
+	zbx_vector_ptr_append(&handle_pool, handle);
+
+	return handleid;
+}
+
+static void	zbx_handle_free(zbx_handle_t *handle)
+{
+	switch (handle->type)
+	{
+		case ZBX_HANDLE_HISTORY:
+		case ZBX_HANDLE_HISTORY_RECORD:
+		case ZBX_HANDLE_HISTORY_RECORD_VALUELOG:
+			zbx_free(handle->data);
+			break;
+		default:
+			THIS_SHOULD_NEVER_HAPPEN;
+	}
+
+	zbx_free(handle);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_sync_history_with_modules                                    *
+ *                                                                            *
+ * Purpose: Invoke zbx_module_history_write() from every loaded module which  *
+ *          exports such symbol                                               *
+ *                                                                            *
+ ******************************************************************************/
+void	zbx_sync_history_with_modules(zbx_dc_history_t history, int history_num)
+{
+	zbx_module_t	*module;
+
+	if (NULL == modules)
+		return;
+
+	for (module = modules; NULL != module->lib; module++)
+	{
+		if (NULL != module->func_history_write)
+		{
+			int				module_sync_start = time(NULL);
+			zbx_history_handle_data_t	*history_handle_data;
+
+			zabbix_log(LOG_LEVEL_DEBUG, "syncing history data with module %s...", module->name);
+
+			history_handle_data = zbx_malloc(NULL, sizeof(zbx_history_handle_data_t));
+			history_handle_data->history = history;
+			history_handle_data->history_num = history_num;
+			history_handle_data->index = 0;
+
+			module->func_history_write(zbx_handle_alloc(ZBX_HANDLE_HISTORY, history_handle_data));
+
+			/* handles which were used by module during zbx_module_history_write() call must be */
+			/* destroyed because their lifetime ended and they must not interfere with handles */
+			/* created in other module function calls */
+			zbx_vector_ptr_clear_ext(&handle_pool, (zbx_clean_func_t)zbx_handle_free);
+
+			zabbix_log(LOG_LEVEL_DEBUG, "syncing history data with module %s took %d seconds",
+					module->name, time(NULL) - module_sync_start);
+		}
+	}
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: unload_modules                                                   *
  *                                                                            *
  * Purpose: Unload already loaded loadable modules (dynamic libraries).       *
@@ -219,12 +393,12 @@
  *          It is called on process shutdown.                                 *
  *                                                                            *
  ******************************************************************************/
-void	unload_modules()
+void	zbx_unload_modules()
 {
 	const char	*__function_name = "unload_modules";
 
 	int		(*func_uninit)();
-	void		**module;
+	zbx_module_t	*module;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
@@ -232,14 +406,14 @@
 	if (NULL == modules)
 		goto out;
 
-	for (module = modules; NULL != *module; module++)
+	for (module = modules; NULL != module->lib; module++)
 	{
-		func_uninit = (int (*)(void))dlsym(*module, ZBX_MODULE_FUNC_UNINIT);
+		func_uninit = (int (*)(void))dlsym(module->lib, ZBX_MODULE_FUNC_UNINIT);
 		if (NULL == func_uninit)
 		{
 			zabbix_log(LOG_LEVEL_DEBUG, "cannot find \"" ZBX_MODULE_FUNC_UNINIT "()\" function: %s",
 					dlerror());
-			dlclose(*module);
+			dlclose(module->lib);
 			continue;
 		}
 
@@ -246,10 +420,146 @@
 		if (ZBX_MODULE_OK != func_uninit())
 			zabbix_log(LOG_LEVEL_WARNING, "uninitialization failed");
 
-		dlclose(*module);
+		dlclose(module->lib);
+		zbx_free(module->name);
 	}
 
+	zbx_vector_ptr_clear_ext(&handle_pool, (zbx_clean_func_t)zbx_handle_free);
+	zbx_vector_ptr_destroy(&handle_pool);
 	zbx_free(modules);
 out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
 }
+
+/******************************************************************************
+ *                                                                            *
+ * Comments: public API function, see documentation for more details          *
+ *                                                                            *
+ ******************************************************************************/
+zabbix_error_t	zabbix_get_object_member(zabbix_handle_t object, zabbix_label_t label, void *buffer)
+{
+	zabbix_basic_t	res;
+	zabbix_error_t	ret;
+
+	if (object < (zabbix_handle_t)handle_pool.values_num)
+	{
+		zbx_handle_t	*handle = (zbx_handle_t *)handle_pool.values[object];
+
+		if (ZBX_HANDLE_HISTORY_RECORD == handle->type)
+		{
+			zbx_history_handle_data_t	*record_data = (zbx_history_handle_data_t *)handle->data;
+
+			if (ZABBIX_HISTORY_RECORD_ITEMID == label || ZABBIX_HISTORY_RECORD_CLOCK == label ||
+					ZABBIX_HISTORY_RECORD_NS == label)
+			{
+				get_history_field(record_data->history, record_data->index, label, &res);
+				ret = ZABBIX_SUCCESS;
+			}
+			else if (ZABBIX_HISTORY_RECORD_VALUETYPE == label)
+			{
+				res.as_uint64 = get_history_type(record_data->history, record_data->index);
+				ret = ZABBIX_SUCCESS;
+			}
+			else if (ZABBIX_HISTORY_RECORD_VALUE == label)
+			{
+				zbx_uint64_t	type;
+
+				type = get_history_type(record_data->history, record_data->index);
+
+				if (ZABBIX_TYPE_UINT64 == type || ZABBIX_TYPE_DOUBLE == type ||
+						ZABBIX_TYPE_STRING == type)
+				{
+					get_history_field(record_data->history, record_data->index, label, &res);
+					ret = ZABBIX_SUCCESS;
+				}
+				else if (ZABBIX_TYPE_OBJECT == type)
+				{
+					zbx_history_handle_data_t	*log_data;
+
+					log_data = zbx_malloc(NULL, sizeof(zbx_history_handle_data_t));
+					log_data->history = record_data->history;
+					log_data->history_num = record_data->history_num;
+					log_data->index = record_data->index;
+					res.as_object = zbx_handle_alloc(ZBX_HANDLE_HISTORY_RECORD_VALUELOG, log_data);
+					ret = ZABBIX_SUCCESS;
+				}
+				else
+					ret = ZABBIX_INTERNAL_ERROR;
+			}
+			else
+				ret = ZABBIX_NO_SUCH_MEMBER;
+		}
+		else if (ZBX_HANDLE_HISTORY_RECORD_VALUELOG == handle->type)
+		{
+			zbx_history_handle_data_t	*log_data = (zbx_history_handle_data_t *)handle->data;
+
+			switch (label)
+			{
+				case ZABBIX_HISTORY_RECORD_VALUELOG_VALUE:
+				case ZABBIX_HISTORY_RECORD_VALUELOG_TIMESTAMP:
+				case ZABBIX_HISTORY_RECORD_VALUELOG_SOURCE:
+				case ZABBIX_HISTORY_RECORD_VALUELOG_LOGEVENTID:
+				case ZABBIX_HISTORY_RECORD_VALUELOG_SEVERITY:
+					get_history_field(log_data->history, log_data->index, label, &res);
+					ret = ZABBIX_SUCCESS;
+					break;
+				default:
+					ret = ZABBIX_NO_SUCH_MEMBER;
+			}
+		}
+		else
+			ret = ZABBIX_NOT_AN_OBJECT;
+	}
+	else
+		ret = ZABBIX_INVALID_HANDLE;
+
+	if (ZABBIX_SUCCESS == ret)
+		memcpy(buffer, &res, sizeof(zabbix_basic_t));	/* buffer may be unaligned */
+
+	return ret;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Comments: public API function, see documentation for more details          *
+ *                                                                            *
+ ******************************************************************************/
+zabbix_error_t	zabbix_get_vector_element(zabbix_handle_t vector, void *buffer)
+{
+	zabbix_basic_t	res;
+	zabbix_error_t	ret;
+
+	if (vector < (zabbix_handle_t)handle_pool.values_num)
+	{
+		zbx_handle_t	*handle = (zbx_handle_t *)handle_pool.values[vector];
+
+		if (ZBX_HANDLE_HISTORY == handle->type)
+		{
+			zbx_history_handle_data_t	*history_data = (zbx_history_handle_data_t *)handle->data;
+
+			if (SUCCEED == next_history_index(history_data->history, history_data->history_num,
+					&history_data->index))
+			{
+				zbx_history_handle_data_t	*history_record_data;
+
+				history_record_data = zbx_malloc(NULL, sizeof(zbx_history_handle_data_t));
+				history_record_data->history = history_data->history;
+				history_record_data->history_num = history_data->history_num;
+				history_record_data->index = history_data->index++;
+				res.as_object = zbx_handle_alloc(ZBX_HANDLE_HISTORY_RECORD, history_record_data);
+				ret = ZABBIX_SUCCESS;
+			}
+			else
+				ret = ZABBIX_END_OF_VECTOR;
+		}
+		else
+			ret = ZABBIX_NOT_A_VECTOR;
+	}
+	else
+		ret = ZABBIX_INVALID_HANDLE;
+
+	if (ZABBIX_SUCCESS == ret)
+		memcpy(buffer, &res, sizeof(zabbix_basic_t));	/* buffer may be unaligned */
+
+	return ret;
+}
Index: src/libs/zbxdbcache/dbcache.c
===================================================================
--- src/libs/zbxdbcache/dbcache.c	(revision 61401)
+++ src/libs/zbxdbcache/dbcache.c	(revision 61924)
@@ -31,6 +31,7 @@
 #include "memalloc.h"
 #include "zbxalgo.h"
 #include "valuecache.h"
+#include "zbxmodules.h"
 
 static zbx_mem_info_t	*hc_index_mem = NULL;
 static zbx_mem_info_t	*hc_mem = NULL;
@@ -87,7 +88,7 @@
 #define ZBX_DC_FLAG_LLD		0x04	/* low-level discovery value */
 #define ZBX_DC_FLAG_UNDEF	0x08	/* unsupported or undefined (delta calculation failed) value */
 
-typedef struct
+typedef struct zbx_dc_history
 {
 	zbx_uint64_t	itemid;
 	history_value_t	value_orig;	/* uninitialized if ZBX_DC_FLAG_NOVALUE is set */
@@ -2197,6 +2198,8 @@
 		*total_num += history_num;
 		candidate_num = history_items.values_num;
 
+		zbx_sync_history_with_modules(history, history_num);
+
 		now = time(NULL);
 
 		if (ZBX_SYNC_FULL == sync_type && now - sync_start >= 10)
@@ -3540,3 +3543,149 @@
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
 }
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_next_history_index                                           *
+ *                                                                            *
+ * Purpose: move index to the next position in history array skipping meta    *
+ *          information updates, notsupported items and low-level discovery   *
+ *                                                                            *
+ * Parameters: history     - [IN] array of history data                       *
+ *             history_num - [IN] number of history structures                *
+ *             index       - [IN/OUT] current position in history array       *
+ *                                                                            *
+ * Return value: SUCCEED - index was moved to the next position               *
+ *               FAIL    - there is no more history data to export            *
+ *                                                                            *
+ * Comments: internal helper function for implementation of public API        *
+ *           zabbix_get_vector_element() for ZBX_HANDLE_HISTORY type handles  *
+ *                                                                            *
+ ******************************************************************************/
+int	zbx_next_history_index(zbx_dc_history_t history, int history_num, int *index)
+{
+	ZBX_DC_HISTORY	*h = (ZBX_DC_HISTORY *)history;
+
+	for (; *index < history_num; (*index)++)
+	{
+		if (0 != (h[*index].flags & ZBX_DC_FLAG_NOVALUE))
+			continue;
+
+		if (0 != (h[*index].flags & ZBX_DC_FLAG_UNDEF))
+			continue;
+
+		if (0 != (h[*index].flags & ZBX_DC_FLAG_LLD))
+			continue;
+
+		return SUCCEED;
+	}
+
+	return FAIL;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_get_history_field                                            *
+ *                                                                            *
+ * Purpose: get the value of specified field of history array element         *
+ *                                                                            *
+ * Parameters: history     - [IN] array of history data                       *
+ *             index       - [IN] current position in history array           *
+ *             label       - [IN] requested field                             *
+ *             res         - [OUT] field value                                *
+ *                                                                            *
+ * Comments: internal helper function for implementation of public API        *
+ *           zabbix_get_object_member() for ZBX_HANDLE_HISTORY_RECORD and     *
+ *           ZBX_HANDLE_HISTORY_RECORD_VALUELOG type handles and their        *
+ *           respective labels (except ZABBIX_HISTORY_RECORD_VALUETYPE)       *
+ *                                                                            *
+ ******************************************************************************/
+void	zbx_get_history_field(zbx_dc_history_t history, int index, zabbix_label_t label, zabbix_basic_t *res)
+{
+	ZBX_DC_HISTORY	*h = (ZBX_DC_HISTORY *)history + index;
+
+	switch (label)
+	{
+		case ZABBIX_HISTORY_RECORD_ITEMID:
+			res->as_uint64 = h->itemid;
+			break;
+		case ZABBIX_HISTORY_RECORD_CLOCK:
+			res->as_uint64 = (zbx_uint64_t)h->ts.sec;
+			break;
+		case ZABBIX_HISTORY_RECORD_NS:
+			res->as_uint64 = (zbx_uint64_t)h->ts.ns;
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUE:
+			switch (h->value_type)
+			{
+				case ITEM_VALUE_TYPE_FLOAT:
+					res->as_double = h->value.dbl;
+					break;
+				case ITEM_VALUE_TYPE_UINT64:
+					res->as_uint64 = h->value.ui64;
+					break;
+				case ITEM_VALUE_TYPE_STR:
+				case ITEM_VALUE_TYPE_TEXT:
+					res->as_string = h->value_orig.str;
+					break;
+				default:
+					THIS_SHOULD_NEVER_HAPPEN;
+			}
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUELOG_VALUE:
+			res->as_string = h->value_orig.str;
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUELOG_TIMESTAMP:
+			res->as_uint64 = (zbx_uint64_t)h->timestamp;
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUELOG_SOURCE:
+			res->as_string = h->value.str;
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUELOG_LOGEVENTID:
+			res->as_uint64 = (zbx_uint64_t)h->logeventid;
+			break;
+		case ZABBIX_HISTORY_RECORD_VALUELOG_SEVERITY:
+			res->as_uint64 = (zbx_uint64_t)h->severity;
+			break;
+		default:
+			THIS_SHOULD_NEVER_HAPPEN;
+	}
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_get_history_type                                             *
+ *                                                                            *
+ * Purpose: get the type of history array element                             *
+ *                                                                            *
+ * Parameters: history     - [IN] array of history data                       *
+ *             index       - [IN] current position in history array           *
+ *                                                                            *
+ * Return value: one of ZABBIX_TYPE_* codes                                   *
+ *                                                                            *
+ * Comments: internal helper function for implementation of public API        *
+ *           zabbix_get_object_member() for ZBX_HANDLE_HISTORY_RECORD type    *
+ *           handles and their labels ZABBIX_HISTORY_RECORD_VALUE and         *
+ *           ZABBIX_HISTORY_RECORD_VALUETYPE                                  *
+ *                                                                            *
+ ******************************************************************************/
+zbx_uint64_t	zbx_get_history_type(zbx_dc_history_t history, int index)
+{
+	ZBX_DC_HISTORY	*h = (ZBX_DC_HISTORY *)history + index;
+
+	switch (h->value_type)
+	{
+		case ITEM_VALUE_TYPE_FLOAT:
+			return ZABBIX_TYPE_DOUBLE;
+		case ITEM_VALUE_TYPE_UINT64:
+			return ZABBIX_TYPE_UINT64;
+		case ITEM_VALUE_TYPE_STR:
+		case ITEM_VALUE_TYPE_TEXT:
+			return ZABBIX_TYPE_STRING;
+		case ITEM_VALUE_TYPE_LOG:
+			return ZABBIX_TYPE_OBJECT;
+		default:
+			THIS_SHOULD_NEVER_HAPPEN;
+			return (zbx_uint64_t)0;
+	}
+}
Index: src/zabbix_agent/zabbix_agentd.c
===================================================================
--- src/zabbix_agent/zabbix_agentd.c	(revision 61401)
+++ src/zabbix_agent/zabbix_agentd.c	(revision 61924)
@@ -897,7 +897,9 @@
 		exit(EXIT_FAILURE);
 	}
 #endif
-	if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
+#endif
+#ifndef _WINDOWS
+	if (FAIL == zbx_load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
 	{
 		zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
 		exit(EXIT_FAILURE);
@@ -1060,9 +1062,10 @@
 #ifdef _WINDOWS
 	free_perf_collector();
 	zbx_co_uninitialize();
-#else
-	unload_modules();
 #endif
+#ifndef _WINDOWS
+	zbx_unload_modules();
+#endif
 	zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent stopped. Zabbix %s (revision %s).",
 			ZABBIX_VERSION, ZABBIX_REVISION);
 
@@ -1156,7 +1159,7 @@
 			zbx_set_common_signal_handlers();
 #endif
 #ifndef _WINDOWS
-			if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 0))
+			if (FAIL == zbx_load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 0))
 			{
 				zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
 				exit(EXIT_FAILURE);
@@ -1173,7 +1176,7 @@
 			free_perf_collector();	/* cpu_collector must be freed before perf_collector is freed */
 #endif
 #ifndef _WINDOWS
-			unload_modules();
+			zbx_unload_modules();
 #endif
 			free_metrics();
 			alias_list_free();
