changeset 153:894e7948189c

Bug 2794: Remove dependency on net-snmp-libs. Reviewed-by: ykubota GitHub: https://github.com/HeapStats/heapstats/pull/21
author Yasumasa Suenaga <yasuenag@gmail.com>
date Tue, 15 Mar 2016 12:48:16 +0900
parents ce583e804b7a
children 96e06914c625
files ChangeLog Makefile.in agent/Makefile.in agent/attacher/Makefile.in agent/heapstats.conf.in agent/src/Makefile.in agent/src/heapstats-engines/Makefile.am agent/src/heapstats-engines/Makefile.in agent/src/heapstats-engines/classContainer.cpp agent/src/heapstats-engines/configuration.cpp agent/src/heapstats-engines/configuration.hpp agent/src/heapstats-engines/libmain.cpp agent/src/heapstats-engines/trapSender.cpp agent/src/heapstats-engines/trapSender.hpp agent/src/heapstats-engines/util.hpp agent/src/iotracer/Makefile.in agent/test/deadlock/heapstats.conf agent/test/thread-recording/heapstats.conf configure configure.ac mbean/Makefile.in mbean/native/Makefile.in specs/heapstats.spec
diffstat 23 files changed, 288 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Mar 10 19:14:45 2016 +0900
+++ b/ChangeLog	Tue Mar 15 12:48:16 2016 +0900
@@ -1,3 +1,11 @@
+2016-03-15  Yasumasa Suenaga <yasuenag@gmail.com>
+
+	* Bug 2794: Remove dependency on net-snmp-libs.
+
+2016-03-04 Shinji Takao  <takao.shinji@lab.ntt.co.jp>
+
+	* Bug 2796: Change default value: snmp_send to false.
+
 2016-03-05  Yasumasa Suenaga <yasuenag@gmail.com>
 
 	* Bug 2870: JVM crash when oneway option is changed through JMX.
--- a/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -242,6 +242,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -250,7 +251,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/agent/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -217,6 +217,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -225,7 +226,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/agent/attacher/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/attacher/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -158,6 +158,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -166,7 +167,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/agent/heapstats.conf.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/heapstats.conf.in	Tue Mar 15 12:48:16 2016 +0900
@@ -59,6 +59,8 @@
 snmp_send=false
 snmp_target=localhost
 snmp_comname=public
+# You can check library path with `net-snmp-config --netsnmp-libs`
+snmp_libpath=@LIBNETSNMP_PATH@
 
 logdir=./tmp
 archive_command=/usr/bin/zip %archivefile% -jr %logdir%
--- a/agent/src/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -263,6 +263,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -271,7 +272,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/agent/src/heapstats-engines/Makefile.am	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/Makefile.am	Tue Mar 15 12:48:16 2016 +0900
@@ -19,7 +19,7 @@
                   -Wno-strict-aliasing -fPIC @VMSTRUCTS_CXX_FLAGS@           \
                   @VMSTRUCTS_CXX_FLAGS@ -DDEFAULT_CONF_DIR=\"$(sysconfdir)\"
 
-BASE_LD_FLAGS   = -shared @NET_SNMP_LIB_FLAGS@
+BASE_LD_FLAGS   = -shared
 
 BASE_CCAS_FLAGS = @CCASFLAGS@
 
--- a/agent/src/heapstats-engines/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -579,6 +579,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -587,7 +588,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
@@ -670,7 +670,7 @@
                   -Wno-strict-aliasing -fPIC @VMSTRUCTS_CXX_FLAGS@           \
                   @VMSTRUCTS_CXX_FLAGS@ -DDEFAULT_CONF_DIR=\"$(sysconfdir)\"
 
-BASE_LD_FLAGS = -shared @NET_SNMP_LIB_FLAGS@
+BASE_LD_FLAGS = -shared
 BASE_CCAS_FLAGS = @CCASFLAGS@
 ACLOCAL_AMFLAGS = -I ../m4
 @ARM_TRUE@libheapstats_engine_none_2_0_so_SOURCES = $(BASE_SOURCE) \
--- a/agent/src/heapstats-engines/classContainer.cpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/classContainer.cpp	Tue Mar 15 12:48:16 2016 +0900
@@ -125,8 +125,12 @@
     }
 
     /* Create trap sender. */
-    pSender = new TTrapSender(SNMP_VERSION_2c, conf->SnmpTarget()->get(),
-                              conf->SnmpComName()->get(), 162);
+    if (conf->SnmpSend()->get()) {
+      pSender = new TTrapSender(SNMP_VERSION_2c, conf->SnmpTarget()->get(),
+                                conf->SnmpComName()->get(), 162);
+    } else {
+      pSender = NULL;
+    }
 
     /* Create unloaded class information queue. */
     unloadedList = new TClassInfoQueue();
--- a/agent/src/heapstats-engines/configuration.cpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/configuration.cpp	Tue Mar 15 12:48:16 2016 +0900
@@ -137,6 +137,9 @@
     snmpComName =
         new TStringConfig(this, "snmp_comname", (char *)"public",
                           &setSnmpComName, (TStringConfig::TFinalizer) & free);
+    snmpLibPath =
+        new TStringConfig(this, "snmp_libpath", (char *)LIBNETSNMP_PATH,
+                          &setSnmpLibPath, (TStringConfig::TFinalizer) & free);
     logDir = new TStringConfig(this, "logdir", (char *)"./tmp",
                                &ReadStringValue,
                                (TStringConfig::TFinalizer) & free);
@@ -178,6 +181,7 @@
     snmpSend = new TBooleanConfig(*src->snmpSend);
     snmpTarget = new TStringConfig(*src->snmpTarget);
     snmpComName = new TStringConfig(*src->snmpComName);
+    snmpLibPath = new TStringConfig(*src->snmpLibPath);
     logDir = new TStringConfig(*src->logDir);
     archiveCommand = new TStringConfig(*src->archiveCommand);
     killOnError = new TBooleanConfig(*src->killOnError);
@@ -215,6 +219,7 @@
   configs.push_back(snmpSend);
   configs.push_back(snmpTarget);
   configs.push_back(snmpComName);
+  configs.push_back(snmpLibPath);
   configs.push_back(logDir);
   configs.push_back(archiveCommand);
   configs.push_back(killOnError);
@@ -542,6 +547,7 @@
                        snmpSend->get() ? "true" : "false");
   logger->printInfoMsg("SNMP target = %s", snmpTarget->get());
   logger->printInfoMsg("SNMP community = %s", snmpComName->get());
+  logger->printInfoMsg("NET-SNMP client library path = %s", snmpLibPath->get());
 
   /* Output temporary log directory path. */
   logger->printInfoMsg("Temporary log directory = %s", logDir->get());
@@ -643,6 +649,11 @@
 
   /* SNMP check */
   if (snmpSend->get()) {
+    if (snmpLibPath->get() == NULL) {
+      logger->printWarnMsg("snmp_libpath must be set when snmp_send is set.");
+      result = false;
+    }
+
     if ((snmpTarget->get() == NULL) || (strlen(snmpTarget->get()) == 0)) {
       logger->printWarnMsg("snmp_target have to be set when snmp_send is set");
       result = false;
--- a/agent/src/heapstats-engines/configuration.hpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/configuration.hpp	Tue Mar 15 12:48:16 2016 +0900
@@ -291,6 +291,9 @@
   /*!< SNMP trap community name. */
   TStringConfig *snmpComName;
 
+  /*!< NET-SNMP client library path. */
+  TStringConfig *snmpLibPath;
+
   /*!< Path of working directory for log archive. */
   TStringConfig *logDir;
 
@@ -443,6 +446,7 @@
   TBooleanConfig *SnmpSend() { return snmpSend; }
   TStringConfig *SnmpTarget() { return snmpTarget; }
   TStringConfig *SnmpComName() { return snmpComName; }
+  TStringConfig *SnmpLibPath() { return snmpLibPath; }
   TStringConfig *LogDir() { return logDir; }
   TStringConfig *ArchiveCommand() { return archiveCommand; }
   TBooleanConfig *KillOnError() { return killOnError; }
@@ -526,6 +530,16 @@
       *dest = (strcmp(val, "(NULL)") == 0) ? strdup("") : strdup(val);
     }
   }
+
+  static void setSnmpLibPath(TConfiguration *inst, char *val, char **dest) {
+    if (inst->isLoaded &&
+        ((val != NULL) && (*dest != NULL) && (strcmp(val, *dest) != 0))) {
+      throw "Cannot set snmp_libpath";
+    } else {
+      inst->ReadStringValue(inst, val, dest);
+    }
+  }
+
 };
 
 #endif  // CONFIGURATION_HPP
--- a/agent/src/heapstats-engines/libmain.cpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/libmain.cpp	Tue Mar 15 12:48:16 2016 +0900
@@ -599,11 +599,9 @@
 
   logger->flush();
 
-  /* Get now date and set time as agent init-time. */
-  struct timeval tv;
-  gettimeofday(&tv, NULL);
-  TTrapSender::initializeTime =
-      (jlong)tv.tv_sec * 100 + (jlong)tv.tv_usec / 10000;
+  if (conf->SnmpSend()->get() && !TTrapSender::initialize()) {
+    return SNMP_SETUP_FAILED;
+  }
 
   /* Create thread instances that controlled snapshot trigger. */
   try {
@@ -680,6 +678,9 @@
   /* Free allocated configuration file path string. */
   free(loadConfigPath);
   loadConfigPath = NULL;
+
+  /* Cleanup TTrapSender. */
+  TTrapSender::finalize();
 }
 
 /*!
--- a/agent/src/heapstats-engines/trapSender.cpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/trapSender.cpp	Tue Mar 15 12:48:16 2016 +0900
@@ -24,6 +24,7 @@
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
 #include <pthread.h>
+#include <dlfcn.h>
 
 #include "globals.hpp"
 #include "util.hpp"
@@ -49,6 +50,50 @@
 pthread_mutex_t TTrapSender::senderMutex =
                                 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
 
+/*!
+ * \brief Flags whether libnetsnmp.so is loaded.
+ */
+bool TTrapSender::is_netsnmp_loaded = false;
+
+/*!
+ * \brief Library handle of libnetsnmp.so .
+ */
+void * TTrapSender::libnetsnmp_handle = NULL;
+
+/*!
+ * \brief Functions in NET-SNMP client library.
+ */
+TNetSNMPFunctions TTrapSender::netSnmpFuncs;
+
+
+/*!
+ * \brief TTrapSender initialization.
+ * \return true if succeeded.
+ */
+bool TTrapSender::initialize(void) {
+  /* Get now date and set time as agent init-time. */
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  TTrapSender::initializeTime =
+      (jlong)tv.tv_sec * 100 + (jlong)tv.tv_usec / 10000;
+
+  /* Load functions from libnetsnmp */
+  if (!getProcAddressFromNetSNMPLib()) {
+    return false;
+  }
+
+  return true;
+}
+
+/*!
+ * \brief TTrapSender global finalization.
+ */
+void TTrapSender::finalize(void) {
+  /* Unload library */
+  if (libnetsnmp_handle != NULL) {
+    dlclose(libnetsnmp_handle);
+  }
+}
 
 /*!
  * \brief TrapSender constructor.
@@ -61,7 +106,8 @@
   /* Lock to use in multi-thread. */
   ENTER_PTHREAD_SECTION(&senderMutex) {
     /* Disable NETSNMP logging. */
-    netsnmp_register_loghandler(NETSNMP_LOGHANDLER_NONE, LOG_EMERG);
+    netSnmpFuncs.netsnmp_register_loghandler(
+                               NETSNMP_LOGHANDLER_NONE, LOG_EMERG);
 
     /* If snmp target is illegal. */
     if (pPeer == NULL) {
@@ -70,7 +116,7 @@
     } else {
       /* Initialize session. */
       memset(&session, 0, sizeof(netsnmp_session));
-      snmp_sess_init(&session);
+      netSnmpFuncs.snmp_sess_init(&session);
       session.version = snmp;
       session.peername = strdup(pPeer);
       session.remote_port = port;
@@ -78,7 +124,7 @@
       session.community_len = (pCommName != NULL) ? strlen(pCommName) : 0;
 
       /* Make a PDU */
-      pPdu = snmp_pdu_create(SNMP_MSG_TRAP2);
+      pPdu = netSnmpFuncs.snmp_pdu_create(SNMP_MSG_TRAP2);
     }
   }
   /* Unlock to use in multi-thread. */
@@ -96,10 +142,10 @@
 
     /* Free SNMP pdu. */
     if (pPdu != NULL) {
-      snmp_free_pdu(pPdu);
+      netSnmpFuncs.snmp_free_pdu(pPdu);
     }
     /* Close and free SNMP session. */
-    snmp_close(&session);
+    netSnmpFuncs.snmp_close(&session);
   }
   /* Unlock to use in multi-thread. */
   EXIT_PTHREAD_SECTION(&senderMutex)
@@ -171,7 +217,7 @@
   }
 
   /* Append variable. */
-  int error = snmp_add_var(pPdu, id, len, type, pStr);
+  int error = netSnmpFuncs.snmp_add_var(pPdu, id, len, type, pStr);
 
   /* Failure append variables. */
   if (error) {
@@ -208,15 +254,17 @@
 
   /* Open session. */
 #ifdef HAVE_NETSNMP_TRANSPORT_OPEN_CLIENT
-  netsnmp_session *sess = snmp_add(
-        &session, netsnmp_transport_open_client("snmptrap", session.peername),
-        NULL, NULL);
+  netsnmp_session *sess = netSnmpFuncs.snmp_add(
+        &session, netSnmpFuncs.netsnmp_transport_open_client(
+                                        "snmptrap", session.peername),
+                                                                  NULL, NULL);
 #else
   char target[256];
   snprintf(target, sizeof(target), "%s:%d", session.peername,
              session.remote_port);
-  netsnmp_session *sess = snmp_add(
-        &session, netsnmp_tdomain_transport(target, 0, "udp"), NULL, NULL);
+  netsnmp_session *sess = netSnmpFuncs.snmp_add(
+        &session, netSnmpFuncs.netsnmp_tdomain_transport(target, 0, "udp"),
+                                                                  NULL, NULL);
 #endif
 
   /* If failure open session. */
@@ -231,15 +279,15 @@
   }
 
   /* Send trap. */
-  int success = snmp_send(sess, pPdu);
+  int success = netSnmpFuncs.snmp_send(sess, pPdu);
 
   /* Clean up after send trap. */
-  snmp_close(sess);
+  netSnmpFuncs.snmp_close(sess);
 
   /* If failure send trap. */
   if (!success) {
     /* Free PDU. */
-    snmp_free_pdu(pPdu);
+    netSnmpFuncs.snmp_free_pdu(pPdu);
     logger->printWarnMsg("Send SNMP trap failed!");
   }
 
@@ -272,6 +320,54 @@
   strSet.clear();
 
   /* Make a PDU. */
-  pPdu = snmp_pdu_create(SNMP_MSG_TRAP2);
+  pPdu = netSnmpFuncs.snmp_pdu_create(SNMP_MSG_TRAP2);
 }
 
+/*!
+ * \brief Get function address from libnetsnmp.
+ * \return true if succeeded.
+ */
+bool TTrapSender::getProcAddressFromNetSNMPLib(void) {
+  libnetsnmp_handle = dlopen(conf->SnmpLibPath()->get(), RTLD_NOW);
+
+  if (libnetsnmp_handle == NULL) {
+    logger->printCritMsg("Could not load libnetsnmp: %s", dlerror());
+    return false;
+  }
+
+  netSnmpFuncs.netsnmp_register_loghandler =
+                   (Tnetsnmp_register_loghandler)dlsym(
+                             libnetsnmp_handle, "netsnmp_register_loghandler");
+  netSnmpFuncs.snmp_sess_init = (Tsnmp_sess_init)dlsym(
+                                           libnetsnmp_handle, "snmp_sess_init");
+  netSnmpFuncs.snmp_pdu_create = (Tsnmp_pdu_create)dlsym(
+                                          libnetsnmp_handle, "snmp_pdu_create");
+  netSnmpFuncs.snmp_free_pdu = (Tsnmp_free_pdu)dlsym(
+                                            libnetsnmp_handle, "snmp_free_pdu");
+  netSnmpFuncs.snmp_close = (Tsnmp_close)dlsym(libnetsnmp_handle, "snmp_close");
+  netSnmpFuncs.snmp_add_var = (Tsnmp_add_var)dlsym(
+                                             libnetsnmp_handle, "snmp_add_var");
+  netSnmpFuncs.snmp_add = (Tsnmp_add)dlsym(libnetsnmp_handle, "snmp_add");
+  netSnmpFuncs.netsnmp_transport_open_client =
+                    (Tnetsnmp_transport_open_client)dlsym(
+                            libnetsnmp_handle, "netsnmp_transport_open_client");
+  netSnmpFuncs.netsnmp_tdomain_transport = (Tnetsnmp_tdomain_transport)dlsym(
+                                libnetsnmp_handle, "netsnmp_tdomain_transport");
+  netSnmpFuncs.snmp_send = (Tsnmp_send)dlsym(libnetsnmp_handle, "snmp_send");
+
+  if ((netSnmpFuncs.netsnmp_register_loghandler == NULL) ||
+      (netSnmpFuncs.snmp_sess_init == NULL) ||
+      (netSnmpFuncs.snmp_pdu_create == NULL) ||
+      (netSnmpFuncs.snmp_free_pdu == NULL) ||
+      (netSnmpFuncs.snmp_close == NULL) ||
+      (netSnmpFuncs.snmp_add_var == NULL) ||
+      (netSnmpFuncs.snmp_add == NULL) ||
+      (netSnmpFuncs.netsnmp_transport_open_client == NULL) ||
+      (netSnmpFuncs.snmp_send == NULL)) {
+    logger->printCritMsg("Could not load function(s) from libnetsnmp");
+    return false;
+  }
+
+  return true;
+}
+
--- a/agent/src/heapstats-engines/trapSender.hpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/trapSender.hpp	Tue Mar 15 12:48:16 2016 +0900
@@ -149,6 +149,45 @@
  */
 #define OID_METASPACEALERT OID_PEN ".6.0"
 
+/* Function type definition for NET-SNMP client library. */
+typedef netsnmp_log_handler *(*Tnetsnmp_register_loghandler)(int type, int pri);
+typedef void (*Tsnmp_sess_init)(netsnmp_session *);
+typedef netsnmp_pdu *(*Tsnmp_pdu_create)(int type);
+typedef void (*Tsnmp_free_pdu)(netsnmp_pdu *pdu);
+typedef int (*Tsnmp_close)(netsnmp_session *);
+typedef int (*Tsnmp_add_var)(netsnmp_pdu *, const oid *, size_t,
+                                                    char, const char *);
+typedef netsnmp_session *(*Tsnmp_add)(netsnmp_session *,
+                                      struct netsnmp_transport_s *,
+                                      int (*fpre_parse) (netsnmp_session *,
+                                                   struct netsnmp_transport_s
+                                                   *, void *, int),
+                                      int (*fpost_parse) (netsnmp_session *,
+                                                          netsnmp_pdu *, int));
+typedef netsnmp_transport *(*Tnetsnmp_transport_open_client)
+                                     (const char* application, const char* str);
+typedef netsnmp_transport *(*Tnetsnmp_tdomain_transport)(const char *str,
+                                                    int local,
+                                                    const char *default_domain);
+typedef int (*Tsnmp_send)(netsnmp_session *, netsnmp_pdu *);
+
+/*!
+ * \brief Structure for functions in NET-SNMP client library.
+ */
+typedef struct {
+  Tnetsnmp_register_loghandler   netsnmp_register_loghandler;
+  Tsnmp_sess_init                snmp_sess_init;
+  Tsnmp_pdu_create               snmp_pdu_create;
+  Tsnmp_free_pdu                 snmp_free_pdu;
+  Tsnmp_close                    snmp_close;
+  Tsnmp_add_var                  snmp_add_var;
+  Tsnmp_add                      snmp_add;
+  Tnetsnmp_transport_open_client netsnmp_transport_open_client;
+  Tnetsnmp_tdomain_transport     netsnmp_tdomain_transport;
+  Tsnmp_send                     snmp_send;
+} TNetSNMPFunctions;
+
+
 /*!
  * \brief This class is send trap to SNMP Manager.
  */
@@ -173,6 +212,17 @@
   static pthread_mutex_t senderMutex;
 
   /*!
+   * \brief TTrapSender initialization.
+   * \return true if succeeded.
+   */
+  static bool initialize(void);
+
+  /*!
+   * \brief TTrapSender global finalization.
+   */
+  static void finalize(void);
+
+  /*!
    * \brief TrapSender constructor.
    * \param snmp      [in] SNMP version.
    * \param pPeer     [in] Target of SNMP trap.
@@ -238,6 +288,19 @@
 
  private:
   /*!
+   * \brief Flags whether libnetsnmp.so is loaded.
+   */
+  static bool is_netsnmp_loaded;
+  /*!
+   * \brief Library handle of libnetsnmp.so .
+   */
+  static void *libnetsnmp_handle;
+  /*!
+   * \brief Functions in NET-SNMP client library.
+   */
+  static TNetSNMPFunctions netSnmpFuncs;
+
+  /*!
    * \brief SNMP session information.
    */
   netsnmp_session session;
@@ -250,6 +313,13 @@
    * \brief Allocated string set for PDU.
    */
   std::set<char *> strSet;
+
+  /*!
+   * \brief Get function address from libnetsnmp.
+   * \return true if succeeded.
+   */
+  static bool getProcAddressFromNetSNMPLib(void);
+
 };
 
 #endif  //_TRAP_SENDER_H
--- a/agent/src/heapstats-engines/util.hpp	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/heapstats-engines/util.hpp	Tue Mar 15 12:48:16 2016 +0900
@@ -156,6 +156,10 @@
  * \brief Configuration is not valid.
  */
 #define INVALID_CONFIGURATION 0x07
+/*!
+ * \brief SNMP setup failed.
+ */
+#define SNMP_SETUP_FAILED 0x08
 
 /*!
  * \brief This macro is notification catch signal to signal watcher thread.
--- a/agent/src/iotracer/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/src/iotracer/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -157,6 +157,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -165,7 +166,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/agent/test/deadlock/heapstats.conf	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/test/deadlock/heapstats.conf	Tue Mar 15 12:48:16 2016 +0900
@@ -1,14 +1,18 @@
-# heapstats_agent 1.1.1
-# heapstats_agent 1.1.1 configuration file.
+# heapstats_agent 2.0.0
+# heapstats_agent 2.0.0 configuration file.
 attach=true
 
 # Output file setting
 file=heapstats_snapshot.dat
 heaplogfile=heapstats_log.csv
 archivefile=heapstats_analyze.zip
+logfile=
 loglevel=INFO
 reduce_snapshot=true
 
+# SnapShot type
+collect_reftree=true
+
 # Trigger snapshot setting
 trigger_on_fullgc=true
 trigger_on_dump=true
@@ -45,10 +49,18 @@
 logsignal_all=SIGUSR2
 signal_reload=SIGHUP
 
+# Thread recording
+thread_record_enable=false
+thread_record_buffer_size=100  # Set buffer size in MB.
+thread_record_filename=heapstats-thread-records.htr
+thread_record_iotracer=/usr/local/etc/iotracer/IoTrace.class
+
 # Snmp setting
 snmp_send=true
 snmp_target=localhost
 snmp_comname=public
+# You can check library path with `net-snmp-config --netsnmp-libs`
+snmp_libpath=/usr/lib64/libnetsnmp.so
 
 logdir=./tmp
 archive_command=/usr/bin/zip %archivefile% -jr %logdir%
--- a/agent/test/thread-recording/heapstats.conf	Thu Mar 10 19:14:45 2016 +0900
+++ b/agent/test/thread-recording/heapstats.conf	Tue Mar 15 12:48:16 2016 +0900
@@ -1,14 +1,18 @@
-# heapstats_agent 1.1.1
-# heapstats_agent 1.1.1 configuration file.
+# heapstats_agent 2.0.0
+# heapstats_agent 2.0.0 configuration file.
 attach=true
 
 # Output file setting
 file=heapstats_snapshot.dat
 heaplogfile=heapstats_log.csv
 archivefile=heapstats_analyze.zip
+logfile=
 loglevel=INFO
 reduce_snapshot=true
 
+# SnapShot type
+collect_reftree=true
+
 # Trigger snapshot setting
 trigger_on_fullgc=true
 trigger_on_dump=true
@@ -55,6 +59,8 @@
 snmp_send=true
 snmp_target=localhost
 snmp_comname=public
+# You can check library path with `net-snmp-config --netsnmp-libs`
+snmp_libpath=/usr/lib64/libnetsnmp.so
 
 logdir=./tmp
 archive_command=/usr/bin/zip %archivefile% -jr %logdir%
--- a/configure	Thu Mar 10 19:14:45 2016 +0900
+++ b/configure	Tue Mar 15 12:48:16 2016 +0900
@@ -635,7 +635,7 @@
 SSE3_TRUE
 SSE2_FALSE
 SSE2_TRUE
-NET_SNMP_LIB_FLAGS
+LIBNETSNMP_PATH
 NET_SNMP_CFG_PATH
 VMSTRUCTS_CXX_FLAGS
 JDK_DIR
@@ -5600,47 +5600,6 @@
   as_fn_error $? "BFD library was not found." "$LINENO" 5
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnetsnmp" >&5
-$as_echo_n "checking for main in -lnetsnmp... " >&6; }
-if ${ac_cv_lib_netsnmp_main+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnetsnmp  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-int
-main ()
-{
-return main ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_netsnmp_main=yes
-else
-  ac_cv_lib_netsnmp_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmp_main" >&5
-$as_echo "$ac_cv_lib_netsnmp_main" >&6; }
-if test "x$ac_cv_lib_netsnmp_main" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNETSNMP 1
-_ACEOF
-
-  LIBS="-lnetsnmp $LIBS"
-
-else
-  as_fn_error $? "net-snmp library was not found." "$LINENO" 5
-fi
-
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -7891,32 +7850,6 @@
 fi
 done
 
-for ac_func in netsnmp_transport_open_client
-do :
-  ac_fn_c_check_func "$LINENO" "netsnmp_transport_open_client" "ac_cv_func_netsnmp_transport_open_client"
-if test "x$ac_cv_func_netsnmp_transport_open_client" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETSNMP_TRANSPORT_OPEN_CLIENT 1
-_ACEOF
-
-else
-  for ac_func in netsnmp_tdomain_transport
-do :
-  ac_fn_c_check_func "$LINENO" "netsnmp_tdomain_transport" "ac_cv_func_netsnmp_tdomain_transport"
-if test "x$ac_cv_func_netsnmp_tdomain_transport" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NETSNMP_TDOMAIN_TRANSPORT 1
-_ACEOF
-
-else
-  as_fn_error $? "Function was not found in net-snmp library." "$LINENO" 5
-fi
-done
-
-
-fi
-done
-
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -8288,9 +8221,8 @@
 
 # end VMStructs ----------------------------------------------------------------
 
-# get Net-SNMP-Config ----------------------------------------------------------
-
-for ac_prog in net-snmp-config-x86_64 net-snmp-config
+# get default NET-SNMP client library path  ------------------------------------
+for ac_prog in net-snmp-config
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -8305,8 +8237,7 @@
   ;;
   *)
   as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_dummy="/bin:/sbin/:/usr/bin"
-for as_dir in $as_dummy
+for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
@@ -8335,16 +8266,20 @@
 
   test -n "$NET_SNMP_CFG_PATH" && break
 done
-test -n "$NET_SNMP_CFG_PATH" || NET_SNMP_CFG_PATH="net-snmp-config"
-
-
-NET_SNMP_LIB_FLAGS=`$NET_SNMP_CFG_PATH --agent-libs 2>$DEVNULL`
+test -n "$NET_SNMP_CFG_PATH" || NET_SNMP_CFG_PATH="/bin:/sbin/:/usr/bin"
+
+LIBNETSNMP_PATH=`$NET_SNMP_CFG_PATH --netsnmp-libs | sed -e 's|^-L\(.\+\) -l\(.\+\)$|\1/lib\2.so|'`
+
 if test $? -ne 0 ; then
-  as_fn_error $? "Could not get LDFLAGS from net-snmp-cfg." "$LINENO" 5
-fi
-
-
-# end Net-SNMP-Config ----------------------------------------------------------
+  as_fn_error $? "Could not get path to libnetsnmp.so ." "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define LIBNETSNMP_PATH "$LIBNETSNMP_PATH"
+_ACEOF
+
+# end default NET-SNMP client library path  ------------------------------------
 
 # CPU optimization (x86 only) --------------------------------------------------
 if test x"$PROCESSOR_TYPE" = "xx86"; then
--- a/configure.ac	Thu Mar 10 19:14:45 2016 +0900
+++ b/configure.ac	Tue Mar 15 12:48:16 2016 +0900
@@ -54,8 +54,6 @@
 AC_CHECK_LIB([iberty], [main], [], [])
 AC_CHECK_LIB([bfd], [main], [],
   [AC_MSG_ERROR([BFD library was not found.])])
-AC_CHECK_LIB([netsnmp], [main], [],
-  [AC_MSG_ERROR([net-snmp library was not found.])])
 AC_CACHE_SAVE
 
 # Checks for common header files.
@@ -139,10 +137,6 @@
   madvise posix_fadvise munmap \
   gnu_get_libc_version gnu_get_libc_release ], [], \
   [AC_MSG_ERROR([Function was not found that need to test feature.])])
-AC_CHECK_FUNCS([netsnmp_transport_open_client],
-  [], [AC_CHECK_FUNCS([netsnmp_tdomain_transport], [],
-    [AC_MSG_ERROR([Function was not found in net-snmp library.])])
-  ])
 AC_CACHE_SAVE
 
 # set test macro state
@@ -300,18 +294,17 @@
 
 # end VMStructs ----------------------------------------------------------------
 
-# get Net-SNMP-Config ----------------------------------------------------------
-
-AC_PATH_PROGS([NET_SNMP_CFG_PATH], [net-snmp-config-x86_64 net-snmp-config], [net-snmp-config], 
-  [/bin:/sbin/:/usr/bin])
+# get default NET-SNMP client library path  ------------------------------------
+AC_PATH_PROGS([NET_SNMP_CFG_PATH], [net-snmp-config], [/bin:/sbin/:/usr/bin])
+LIBNETSNMP_PATH=`$NET_SNMP_CFG_PATH --netsnmp-libs | sed -e 's|^-L\(.\+\) -l\(.\+\)$|\1/lib\2.so|'`
 
-NET_SNMP_LIB_FLAGS=`$NET_SNMP_CFG_PATH --agent-libs 2>$DEVNULL`
 if test $? -ne 0 ; then
-  AC_MSG_ERROR([Could not get LDFLAGS from net-snmp-cfg.])
+  AC_MSG_ERROR([Could not get path to libnetsnmp.so .])
 fi
-AC_SUBST([NET_SNMP_LIB_FLAGS])
 
-# end Net-SNMP-Config ----------------------------------------------------------
+AC_SUBST([LIBNETSNMP_PATH])
+AC_DEFINE_UNQUOTED([LIBNETSNMP_PATH], "$LIBNETSNMP_PATH")
+# end default NET-SNMP client library path  ------------------------------------
 
 # CPU optimization (x86 only) --------------------------------------------------
 if test x"$PROCESSOR_TYPE" = "xx86"; then
--- a/mbean/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/mbean/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -217,6 +217,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -225,7 +226,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/mbean/native/Makefile.in	Thu Mar 10 19:14:45 2016 +0900
+++ b/mbean/native/Makefile.in	Tue Mar 15 12:48:16 2016 +0900
@@ -205,6 +205,7 @@
 JAVA_PATH = @JAVA_PATH@
 JDK_DIR = @JDK_DIR@
 LDFLAGS = @LDFLAGS@
+LIBNETSNMP_PATH = @LIBNETSNMP_PATH@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LTLIBOBJS = @LTLIBOBJS@
@@ -213,7 +214,6 @@
 MKDIR_P = @MKDIR_P@
 MVN = @MVN@
 NET_SNMP_CFG_PATH = @NET_SNMP_CFG_PATH@
-NET_SNMP_LIB_FLAGS = @NET_SNMP_LIB_FLAGS@
 NM = @NM@
 OBJEXT = @OBJEXT@
 PACKAGE = @PACKAGE@
--- a/specs/heapstats.spec	Thu Mar 10 19:14:45 2016 +0900
+++ b/specs/heapstats.spec	Tue Mar 15 12:48:16 2016 +0900
@@ -14,7 +14,6 @@
 
 # Requires for running
 Requires: pcre >= 6
-Requires: net-snmp-libs >= 5.3
 
 # Requires for building
 BuildRequires: pcre-devel >= 6