Mercurial > hg > release > heapstats-1.1
view agent/src/util.hpp @ 26:8008ab68f482
Bug 1852: HeapStats 1.1 agent can't output WARM messages correctly when _GNU_SOURCE is enabled.
reviewed-by: yasuenag
author | KUBOTA Yuji <kubota.yuji@gmail.com> |
---|---|
date | Sun, 22 Jun 2014 19:46:01 +0900 |
parents | 6086194b2867 |
children | eafa619db958 |
line wrap: on
line source
/*! * \file util.hpp * \brief This file is utilities. * Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef UTIL_HPP #define UTIL_HPP #include <sys/time.h> #include <jni.h> #include <jvmti.h> #include <pthread.h> #include <stddef.h> #include <sys/types.h> #include <iostream> /* STDOUT/ERR helper macro. */ /*! * \brief Standard output macro. */ #define STDOUT std::cout /*! * \brief Standard error output macro. */ #define STDERR std::cerr /*! * \brief Output newline code macro. */ #define NEWLINE std::endl /*! * \brief Standard ouput width adjustment macro. */ #define STDOUT_WIDTH_ADJ(x) std::cout.width((x)) /*! * \brief Standard output force output macro. */ #define FLUSH_STDOUT std::cout.flush() /*! * \brief Standard error output force output macro. */ #define FLUSH_STDERR std::cerr.flush() /*! * \brief Critical message header macro. */ #define PRINT_CRIT_MSG_HEADER \ if (arg.LogLevel >= CRIT) STDERR << "heapstats CRIT: " /*! * \brief Critical message macro. */ #define PRINT_CRIT_MSG(msg) \ PRINT_CRIT_MSG_HEADER << (msg) << NEWLINE /* Warning message. */ /*! * \brief Warning message header macro. */ #define PRINT_WARN_MSG_HEADER \ if (arg.LogLevel >= WARN) STDERR << "heapstats WARN: " /*! * \brief Warning message macro. */ #define PRINT_WARN_MSG(msg) \ PRINT_WARN_MSG_HEADER << (msg) << NEWLINE /*! * \brief Warning message macro for file open failed. */ #define PRINT_FAIL_OPENFILE_MSG(filename, errnum) \ PRINT_WARN_MSG_HEADER << "Counldn't open a file." \ << " file:\"" << (filename) << "\"" \ << " cause:\"" << strerror((errnum)) << "\"" << NEWLINE /*! * \brief Warning message macro for file create failed. */ #define PRINT_FAIL_CREATEFILE_MSG(filename, errnum) \ PRINT_WARN_MSG_HEADER << "Counldn't create a file." \ << " file:\"" << (filename) << "\"" \ << " cause:\"" << strerror((errnum)) << "\"" << NEWLINE /*! * \brief Warning message macro for file output is failed. */ #define PRINT_FAIL_WRITE_MSG(filename, errnum) \ PRINT_WARN_MSG_HEADER << "Failed to outputting to file." \ << " file:\"" << (filename) << "\"" \ << " cause:\"" << strerror((errnum)) << "\"" \ << NEWLINE /*! * \brief Warning message and errno macro. */ #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE /* XSI-compliant version of strerror_r() */ #define PRINT_WARN_MSG_AND_ERRNO(msg, errnum) \ char error_string[1024]; \ strerror_r(errnum, error_string, 1024); \ PRINT_WARN_MSG_HEADER << (msg) \ << " cause:\"" << error_string << "\"" << NEWLINE #else /* GNU-specific version of strerror_r() */ #define PRINT_WARN_MSG_AND_ERRNO(msg, errnum) \ char error_string[1024]; \ PRINT_WARN_MSG_HEADER << (msg) \ << " cause:\"" << strerror_r(errnum, error_string, 1024) << "\"" << NEWLINE #endif /* Info message. */ /*! * \brief Info message header force macro. */ #define PRINT_INFO_MSG_HEADER_NOIF \ STDOUT << "heapstats INFO: " /*! * \brief Info message header macro. */ #define PRINT_INFO_MSG_HEADER \ if (arg.LogLevel >= INFO) PRINT_INFO_MSG_HEADER_NOIF /*! * \brief Info message macro. */ #define PRINT_INFO_MSG(msg) \ PRINT_INFO_MSG_HEADER << (msg) << NEWLINE /* Debug message. */ /*! * \brief Debug message header force macro. */ #define PRINT_DEBUG_MSG_HEADER_NOIF \ STDOUT << "heapstats DEBUG: " /*! * \brief Debug message header macro. */ #define PRINT_DEBUG_MSG_HEADER \ if (arg.LogLevel >= DEBUG) PRINT_DEBUG_MSG_HEADER_NOIF /*! * \brief Debug message macro. */ #define PRINT_DEBUG_MSG(msg) \ PRINT_DEBUG_MSG_HEADER << (msg) << NEWLINE /* Branch prediction. */ /*! * \brief Positive branch prediction. */ #define likely(x) __builtin_expect(!!(x), 1) /*! * \brief Negative branch prediction. */ #define unlikely(x) __builtin_expect(!!(x), 0) /* Critical section helper macro for pthread mutex. */ /*! * \brief Enter critical pthread section macro. */ #define ENTER_PTHREAD_SECTION(monitor) \ if (unlikely(pthread_mutex_lock((monitor)) != 0)) { \ PRINT_WARN_MSG("Entering mutex failed!"); \ } else { /*! * \brief Exit critical pthread section macro. */ #define EXIT_PTHREAD_SECTION(monitor) \ if (unlikely(pthread_mutex_unlock((monitor)) != 0)) { \ PRINT_WARN_MSG("Exiting mutex failed!"); \ } \ } /*! * \brief Calculate align macro. * from hotspot/src/share/vm/utilities/globalDefinitions.hpp */ #define ALIGN_SIZE_UP(size, alignment) \ (((size) + ((alignment) - 1)) & ~((alignment) - 1)) #ifdef __LP64__ /*! * \brief Format string for jlong.<br /> * At "LP64" java environment, jlong is defined as "long int". */ #define JLONG_FORMAT_STR "%ld" #else /*! * \brief Format string for jlong.<br /> * At most java environment, jlong is defined as "long long int". */ #define JLONG_FORMAT_STR "%lld" #endif #ifdef DEBUG /*! * \brief This macro for statement only debug. */ #define DEBUG_ONLY(statement) statement /*! * \brief This macro for statement only release. */ #define RELEASE_ONLY(statement) #else /*! * \brief This macro for statement only debug. */ #define DEBUG_ONLY(statement) /*! * \brief This macro for statement only release. */ #define RELEASE_ONLY(statement) statement #endif /*! * \brief Debug macro. */ #define STATEMENT_BY_MODE(debug_state, release_state) \ DEBUG_ONLY(debug_state) RELEASE_ONLY(release_state) /* Typedef. */ /*! * \brief Causes of function invoking. */ typedef enum{ GC = 1, /*!< Invoke by Garbage Collection. */ DataDumpRequest = 2, /*!< Invoke by user dump request. */ Interval = 3, /*!< Invoke by timer interval. */ Signal = 4, /*!< Invoke by user's signal. */ AnotherSignal = 5, /*!< Invoke by user's another signal. */ ResourceExhausted = 6, /*!< Invoke by JVM resource exhausted. */ ThreadExhausted = 7, /*!< Invoke by thread exhausted. */ OccurredDeadlock = 8 /*!< Invoke by occured deadlock. */ } TInvokeCause; /*! * \brief Ranking Order.<br> * This order affects heap alert. */ typedef enum{ DELTA, /*!< Ranking is sorted by delta from before snapshot. */ USAGE /*!< Ranking is sorted by heap using size. */ } TRankOrder; /*! * \brief Logging Level. */ typedef enum{ CRIT = 1, /*!< Level for FATAL error log. This's displayed by all means. */ WARN = 2, /*!< Level for runnable error log. e.g. Heap-Alert */ INFO = 3, /*!< Level for normal info log. e.g. Heap-Ranking */ DEBUG = 4 /*!< Level for debug info log. */ } TLogLevel; /*! * \brief HeapStats configure setting structure. */ typedef struct{ bool attach; /*!< Flag of agent attach enable. */ char *FileName; /*!< Output snapshot file name. */ char *heapLogFile; /*!< Output common log file name. */ char *archiveFile; /*!< Output archive log file name. */ bool reduceSnapShot; /*!< Is reduced snapshot. */ bool triggerOnFullGC; /*!< Make snapshot is triggered by full-GC. */ bool triggerOnDump; /*!< Make snapshot is triggered by dump request. */ bool triggerOnLogError; /*!< Logging on JVM error(Resoure exhausted). */ bool triggerOnLogSignal; /*!< Logging on received signal. */ bool triggerOnLogLock; /*!< Logging on occurred deadlock. */ int RankLevel; /*!< Count of show ranking. */ TLogLevel LogLevel; /*!< Output log level. */ TRankOrder order; /*!< Order of ranking. */ int AlertPercentage; /*!< Percentage of trigger alert in heap. */ jlong AlertThreshold; /*!< Size of trigger alert in heap. */ int HeapAlertPercentage; /*!< Alert percentage of javaHeapAlert. */ jlong HeapAlertThreshold;/*!< Trigger usage for javaHeapAlert. */ jlong MetaspaceThreshold;/*!< Trigger usage for javaMetaspaceAlert. */ jlong TimerInterval; /*!< Interval of periodic snapshot. */ jlong LogInterval; /*!< Interval of periodic logging. */ bool firstCollect; /*!< Logging on JVM error only first time. */ bool isFirstCollected; /*!< Flag of already logged on JVM error. */ char* logSignalNormal; /*!< Name of signal logging about process. */ char* logSignalAll; /*!< Name of signal logging about environment. */ char* reloadSignal; /*!< Name of signal reload configuration file. */ bool snmpSend; /*!< Flag of SNMP trap send enable. */ char* snmpTarget; /*!< SNMP trap send target. */ char* snmpComName; /*!< SNMP trap community name. */ char* logDir; /*!< Path of working directory for log archive. */ char* archiveCommand; /*!< Command was execute to making log archive. */ bool killOnError; /*!< Abort JVM on resoure exhausted or deadlock. */ } TArguments; /*! * \brief Java thread information structure. */ typedef struct{ char *name; /*!< Name of java thread. */ bool isDaemon; /*!< Flag of thread is daemon thread. */ int priority; /*!< Priority of thread in java. */ char *state; /*!< String about thread state. */ } TJavaThreadInfo; /*! * \brief Java method information structure in stack frame. */ typedef struct{ char *methodName; /*!< Name of class method. */ char *className; /*!< Name of class is declaring method. */ bool isNative; /*!< Flag of method is native. */ char *sourceFile; /*!< Name of file name is declaring class. */ int lineNumber; /*!< Line number of method's executing position in file. */ } TJavaStackMethodInfo; /* Extern variables. */ /*! * \brief Agent attach mode flag. * Value is true, if agent is attached by on-demand-attach. * Value is false, if agent is attached by command line. */ extern bool isOnDemandAttached; /*! * \brief HeapStats configurations. */ extern TArguments arg; /* CPU instruction set flag. */ /*! * \brief SSE2 instruction usable flag. */ extern bool usableSSE2; /*! * \brief SSE3 instruction usable flag. */ extern bool usableSSE3; /*! * \brief SSSE3 instruction usable flag. */ extern bool usableSSSE3; /*! * \brief SSE4.1 instruction usable flag. */ extern bool usableSSE4_1; /*! * \brief SSE4.2 instruction usable flag. */ extern bool usableSSE4_2; /*! * \brief Intel AVX instruction usable flag. */ extern bool usableAVX; /*! * \brief Page size got from sysconf. */ extern long systemPageSize; /*! * \brief Interval of check signal by signal watch timer.(msec) */ const unsigned int SIG_WATCHER_INTERVAL = 0; /* Export functions. */ /*! * \brief JVMTI error detector. * \param jvmti [in] JVMTI envrionment object. * \param error [in] JVMTI error code. * \return Param "error" is error code?(true/false) */ bool isError(jvmtiEnv *jvmti, jvmtiError error); /*! * \brief Set config to default. */ void initSetting(void); /*! * \brief Free config memory. * \param targetArg [in,out] Deallocate target settings. */ void freeSetting(TArguments *targetArg); /*! * \brief Inherited config from old config. * \param newArg [in,out] New argument settings. * \param oldArg [in,out] Old argument settings. */ void inheritedSetting(TArguments *newArg, TArguments *oldArg); /*! * \brief Load configuration from file. * \param filename [in] Read configuration file path. */ void loadConfiguration(const char *filename); /*! * \brief Print setting information. */ void printSetting(void); /*! * \brief Get system information. * \param env [in] JNI envrionment. * \param key [in] System property key. * \return String of system property. */ char *GetSystemProperty(JNIEnv *env, const char *key); /*! * \brief Get ClassUnload event index. * \param jvmti [in] JVMTI envrionment object. * \return ClassUnload event index. * \sa hotspot/src/share/vm/prims/jvmtiExport.cpp<br> * hotspot/src/share/vm/prims/jvmtiEventController.cpp<br> * hotspot/src/share/vm/prims/jvmti.xml<br> * in JDK. */ jint GetClassUnloadingExtEventIndex(jvmtiEnv *jvmti); /*! * \brief Verify CPU instruction set. */ void verifyInstructSet(void); /*! * \brief Replace old string in new string on string. * \param str [in] Process target string. * \param oldStr [in] Targer of replacing. * \param newStr [in] A string will replace existing string. * \return String invoked replace.<br>Don't forget deallocate. */ char *strReplase(char const* str, char const* oldStr, char const* newStr); /*! * \brief Get now date and time. * \return Mili-second elapsed time from 1970/1/1 0:00:00. */ jlong getNowTimeSec(void); /*! * \brief Check signal is supported by JVM. * \param sigName [in] Name of signal. * \return Signal is supported, if value is true. * Otherwise, value is false. * \sa Please see below JDK source about JVM supported signal.<br> * hotspot/src/os/linux/vm/jvm_linux.cpp */ bool isSupportSignal(char const* sigName); /*! * \brief A little sleep. * \param sec [in] Second of sleep range. * \param nsec [in] Nano second of sleep range. */ void littleSleep(const long int sec, const long int nsec); /*! * \brief Get thread information. * \param jvmti [in] JVMTI environment object. * \param env [in] JNI environment object. * \param thread [in] Thread object in java. * \param info [out] Record stored thread information. */ void getThreadDetailInfo(jvmtiEnv *jvmti, JNIEnv* env, jthread thread, TJavaThreadInfo *info); /*! * \brief Get method information in designed stack frame. * \param jvmti [in] JVMTI environment object. * \param env [in] JNI environment object. * \param frame [in] method stack frame. * \param info [out] Record stored method information in stack frame. */ void getMethodFrameInfo(jvmtiEnv *jvmti, JNIEnv* env, jvmtiFrameInfo frame, TJavaStackMethodInfo *info); /*! * \brief Wait spin lock. * \param aLock [in] Target integer lock. */ inline void spinLockWait(volatile int *aLock) { asm volatile( "1:" "xorl %%eax, %%eax;" "pause;" "lock cmpxchgl %1, (%0);" "jnz 1b;" : "+r" (aLock) : "r" (1) : "cc", "memory", "%eax"); }; /*! * \brief Release spin lock. * \param aLock [in] Target integer lock. */ inline void spinLockRelease(volatile int *aLock) { asm volatile( "xorl %%eax, %%eax;" "lock xchgl %%eax, (%0);" : "+r" (aLock) : : "cc", "memory", "%eax"); }; /*! * \brief Handling Java Exception if exists. * \param env [in] JNI environment object. */ inline void handlePendingException(JNIEnv *env) { /* If exists execption in java. */ if (env->ExceptionOccurred() != NULL) { /* Clear execption in java. */ env->ExceptionDescribe(); env->ExceptionClear(); } }; /*! * \brief Add to address. * \param addr [in] Target address. * \param inc [in] Incremental integer value. * \return The address added increment value. */ inline void *incAddress(void *addr, off_t inc) { return (void*)((ptrdiff_t)addr + inc); }; /* Classes. */ /*! * \brief Hasher class for std::tr1::unordered_map. * This template class will be used when key is numeric type. * (int, pointer, etc) */ template<typename T> class TNumericalHasher { public: /*! * \brief Get hash value from designated value. * This function always return convert to integer only. * \param val [in] Hash source data. * \return Hash value. */ size_t operator()(const T &val) const { return (size_t)val; }; }; #endif