--- zabbix-4.0.0alpha9/src/zabbix_proxy/proxy.c.orig	2018-07-23 21:05:43.000000000 +0900
+++ zabbix-4.0.0alpha9/src/zabbix_proxy/proxy.c	2018-08-13 09:40:06.590709273 +0900
@@ -1028,6 +1028,14 @@ int	MAIN_ZABBIX_ENTRY(int flags)
 	DCsync_configuration(ZBX_DBSYNC_INIT);
 	DBclose();
 
+	/* create Trapper Cache for data without nano seconds information */
+	if (SUCCEED != trapper_cache_init(&error))
+	{
+		zabbix_log(LOG_LEVEL_CRIT, "cannot initialize Trapper cache: %s", error);
+		zbx_free(error);
+		exit(EXIT_FAILURE);
+	}
+
 	if (0 != CONFIG_IPMIPOLLER_FORKS)
 		CONFIG_IPMIMANAGER_FORKS = 1;
 
@@ -1165,6 +1173,9 @@ void	zbx_on_exit(void)
 #ifdef HAVE_PTHREAD_PROCESS_SHARED
 	zbx_locks_disable();
 #endif
+
+	trapper_cache_destroy();
+
 	free_metrics();
 #ifdef HAVE_OPENIPMI
 	zbx_ipc_service_free_env();
--- zabbix-4.0.0alpha9/src/libs/zbxdbhigh/proxy.c.orig	2018-08-10 10:04:23.889069478 +0900
+++ zabbix-4.0.0alpha9/src/libs/zbxdbhigh/proxy.c	2018-08-13 09:22:59.333754733 +0900
@@ -24,15 +24,46 @@
 #include "zbxserver.h"
 #include "zbxtasks.h"
 
+#include "mutexs.h"
+
 #include "proxy.h"
 #include "dbcache.h"
 #include "discovery.h"
+#include "memalloc.h"
 #include "zbxalgo.h"
 #include "preproc.h"
 #include "../zbxcrypto/tls_tcp_active.h"
 
 extern char	*CONFIG_SERVER;
 
+static zbx_mem_info_t	*tc_mem = NULL;
+
+#define NS_NULL	-1
+/* Trapper Cache Size is 1MB */
+#define CONFIG_TRAPPER_CACHE_SIZE	(1<<20)
+
+#define ZBX_TC_INIT_SIZE	256
+
+typedef struct
+{
+	zbx_hashset_t	ns_non_exist;
+}
+trapper_cache_t;
+
+static trapper_cache_t	*trapper_cache;
+
+static zbx_mutex_t	trapper_cache_lock;
+
+ZBX_MEM_FUNC_IMPL(__tc, tc_mem)
+
+typedef struct
+{
+	zbx_uint64_t	itemid;
+	unsigned char	value_type;
+	zbx_timespec_t	ts;
+}
+trapper_cache_record_t;
+
 /* the space reserved in json buffer to hold at least one record plus service data */
 #define ZBX_DATA_JSON_RESERVED		(HISTORY_TEXT_VALUE_LEN * 4 + ZBX_KIBIBYTE * 4)
 
@@ -2368,6 +2399,8 @@ void	calc_timestamp(const char *line, in
  ******************************************************************************/
 static int	process_history_data_value(DC_ITEM *item, zbx_agent_value_t *value)
 {
+	trapper_cache_record_t *tc_r;
+
 	if (ITEM_STATUS_ACTIVE != item->status)
 		return FAIL;
 
@@ -2389,6 +2422,105 @@ static int	process_history_data_value(DC
 		}
 	}
 
+	if (NS_NULL == value->ts.ns)
+	{
+		zbx_mutex_lock(trapper_cache_lock);
+
+		tc_r = (trapper_cache_record_t *)zbx_hashset_search(&trapper_cache->ns_non_exist, &(item->itemid));
+
+		if (NULL == tc_r)
+		{
+			char	*tbl[] = {"", "_str", "_log", "uint", "_text"};
+			DB_RESULT	result;
+			DB_ROW	row;
+			trapper_cache_record_t	tc_record_new;
+
+			tc_record_new.itemid = item->itemid;
+			tc_record_new.value_type = item->value_type;
+
+			result = DBselect("select clock,ns from history%s where itemid="
+				ZBX_FS_UI64 " order by clock desc,ns desc limit 1",
+				tbl[item->value_type], item->itemid);
+			if (NULL == (row = DBfetch(result)))
+			{
+				tc_record_new.ts.sec = value->ts.sec;
+				tc_record_new.ts.ns = value->ts.ns = 0;
+			}
+			else
+			{
+				zbx_timespec_t ts;
+
+				ts.sec = atoi(row[0]);
+				if (SUCCEED == DBis_null(row[2]))
+					ts.ns = 0;
+				else
+					ts.ns = atoi(row[1]);
+
+				if (ts.sec < value->ts.sec)
+				{
+					value->ts.ns = 0;
+					tc_record_new.ts = value->ts;
+				}
+				else if (ts.sec == value->ts.sec)
+				{
+					value->ts.ns = ts.ns + 1;
+					if (1000000000 == value->ts.ns)
+					{
+						value->ts.ns = 0;
+						(value->ts.sec)++;
+					}
+					tc_record_new.ts = value->ts;
+				}
+				else
+				{
+					zabbix_log(LOG_LEVEL_WARNING, "History data is newer than gotton one, so does not adjust. "
+						"itemid=%ld, exist: sec=%ld, gotton: sec=%ld",
+						item->itemid, ts.sec, value->ts.sec);
+					ts.ns++;
+					if (1000000000 == ts.ns)
+					{
+						ts.ns = 0;
+						ts.sec++;
+					}
+					tc_record_new.ts = value->ts = ts;
+				}
+			}
+			zbx_hashset_insert(&trapper_cache->ns_non_exist, &tc_record_new, sizeof(trapper_cache_record_t));
+        		DBfree_result(result);
+		}
+		else
+		{
+			if (tc_r->ts.sec < value->ts.sec)
+			{
+				tc_r->ts.sec = value->ts.sec;
+				tc_r->ts.ns = value->ts.ns = 0;
+			}
+			else if (tc_r->ts.sec == value->ts.sec)
+			{
+				value->ts.ns = ++(tc_r->ts.ns);
+				if (1000000000 == value->ts.ns)
+				{
+					tc_r->ts.ns = value->ts.ns = 0;
+					tc_r->ts.sec = ++(value->ts.sec);
+				}
+			}
+			else
+			{
+				zabbix_log(LOG_LEVEL_WARNING, "History data is newer than gotton one, so does not adjust. "
+					"itemid=%ld, exist: sec=%ld, gotton: sec=%ld",
+					item->itemid, tc_r->ts.sec, value->ts.sec);
+				(tc_r->ts.ns)++;
+				if (1000000000 == tc_r->ts.ns)
+				{
+					tc_r->ts.ns = 0;
+					(tc_r->ts.sec)++;
+				}
+				value->ts = tc_r->ts;
+			}
+		}
+		zbx_mutex_unlock(trapper_cache_lock);
+	}
+
 	if (ITEM_STATE_NOTSUPPORTED == value->state ||
 			(NULL != value->value && 0 == strcmp(value->value, ZBX_NOTSUPPORTED)))
 	{
@@ -2618,6 +2750,7 @@ static int	parse_history_data_row_value(
 		}
 		else
 		{
+#if 0
 			/* ensure unique value timestamp (clock, ns) if only clock is available */
 
 			av->ts.sec += unique_shift->sec;
@@ -2628,6 +2761,8 @@ static int	parse_history_data_row_value(
 				unique_shift->sec++;
 				unique_shift->ns = 0;
 			}
+#endif
+			av->ts.ns = NS_NULL;
 		}
 	}
 	else
@@ -3935,3 +4070,47 @@ void	zbx_update_proxy_data(DC_PROXY *pro
 
 	zbx_db_flush_proxy_lastaccess();
 }
+
+int     trapper_cache_init(char **error)
+{
+	const char	*__function_name = "trapper_cache_init";
+
+	int		ret = FAIL;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
+
+	if (SUCCEED != zbx_mutex_create(&trapper_cache_lock, ZBX_MUTEX_TRAPPER, error))
+                goto out;
+
+	if (SUCCEED != (ret = zbx_mem_create(&tc_mem, CONFIG_TRAPPER_CACHE_SIZE, "trapper cache",
+			"TrapperCacheSize", 0, error)))
+        {
+                goto out;
+        }
+
+	trapper_cache = (trapper_cache_t *)__tc_mem_malloc_func(NULL, sizeof(trapper_cache_t));
+        memset(trapper_cache, 0, sizeof(trapper_cache_t));
+
+	zbx_hashset_create_ext(&trapper_cache->ns_non_exist, ZBX_TC_INIT_SIZE,
+			ZBX_DEFAULT_UINT64_HASH_FUNC, ZBX_DEFAULT_UINT64_COMPARE_FUNC, NULL,
+			__tc_mem_malloc_func, __tc_mem_realloc_func, __tc_mem_free_func);
+
+	ret = SUCCEED;
+out:
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
+
+	return ret;
+}
+
+void    trapper_cache_destroy(void)
+{
+	const char      *__function_name = "trapper_cache_destroy";
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
+
+	zbx_hashset_destroy(&trapper_cache->ns_non_exist);
+	trapper_cache = NULL;
+	zbx_mutex_destroy(&trapper_cache_lock);
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
+}
--- zabbix-4.0.0alpha9/src/zabbix_server/server.c.orig	2018-08-10 09:39:44.721493701 +0900
+++ zabbix-4.0.0alpha9/src/zabbix_server/server.c	2018-08-13 09:39:45.908709866 +0900
@@ -26,6 +26,7 @@
 #include "cfg.h"
 #include "pid.h"
 #include "db.h"
+#include "proxy.h"
 #include "dbcache.h"
 #include "zbxdbupgrade.h"
 #include "log.h"
@@ -1056,6 +1057,14 @@ int	MAIN_ZABBIX_ENTRY(int flags)
 
 	DBclose();
 
+	/* create Trapper Cache for data without nano seconds information */
+	if (SUCCEED != trapper_cache_init(&error))
+	{
+		zabbix_log(LOG_LEVEL_CRIT, "cannot initialize Trapper cache: %s", error);
+		zbx_free(error);
+		exit(EXIT_FAILURE);
+	}
+
 	zbx_vc_enable();
 
 	if (0 != CONFIG_IPMIPOLLER_FORKS)
@@ -1220,6 +1229,9 @@ void	zbx_on_exit(void)
 #ifdef HAVE_PTHREAD_PROCESS_SHARED
 	zbx_locks_disable();
 #endif
+
+	trapper_cache_destroy();
+
 	free_metrics();
 	zbx_ipc_service_free_env();
 
--- zabbix-4.0.0alpha9/include/mutexs.h.orig	2018-07-23 21:05:43.000000000 +0900
+++ zabbix-4.0.0alpha9/include/mutexs.h	2018-08-10 09:40:12.820490330 +0900
@@ -44,6 +44,7 @@ typedef enum
 	ZBX_MUTEX_SQLITE3,
 	ZBX_MUTEX_PROCSTAT,
 	ZBX_MUTEX_PROXY_HISTORY,
+	ZBX_MUTEX_TRAPPER,
 	ZBX_MUTEX_COUNT
 }
 zbx_mutex_name_t;
--- zabbix-4.0.0alpha9/include/proxy.h.orig	2018-08-10 16:04:31.802569471 +0900
+++ zabbix-4.0.0alpha9/include/proxy.h	2018-08-10 16:09:26.491557548 +0900
@@ -71,4 +71,7 @@ int	process_agent_history_data(zbx_socke
 int	process_sender_history_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts, char **info);
 int	process_proxy_data(const DC_PROXY *proxy, struct zbx_json_parse *jp, zbx_timespec_t *ts, char **error);
 
+int	trapper_cache_init(char **error);
+void	trapper_cache_destroy(void);
+
 #endif
