From a8226e04466ebc60e834ec72105b52483befecb3 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sat, 15 Dec 2018 05:26:17 +0800 Subject: [PATCH 01/21] add file rotation --- .gitignore | 6 ++ src/main/cpp/agent.cpp | 4 + src/main/cpp/globals.h | 8 ++ src/main/cpp/log_writer.cpp | 161 +++++++++++++++++++++++------------- src/main/cpp/log_writer.h | 43 ++++++---- src/main/cpp/profiler.cpp | 2 +- 6 files changed, 149 insertions(+), 75 deletions(-) diff --git a/.gitignore b/.gitignore index 8f36ee7c2..c9ce332fb 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,9 @@ Testing .settings /bin/ + +.project +.cproject + +src/main/cpp/CMakeLists.txt +src/main/cpp/cmake-build-debug/ diff --git a/src/main/cpp/agent.cpp b/src/main/cpp/agent.cpp index 47b45b92b..4a3bef896 100644 --- a/src/main/cpp/agent.cpp +++ b/src/main/cpp/agent.cpp @@ -281,6 +281,10 @@ static void parseArguments(char *options, ConfigurationOptions &configuration) { configuration.samplingIntervalMax = atoi(value); } else if (strstr(key, "interval") == key) { configuration.samplingIntervalMin = configuration.samplingIntervalMax = atoi(value); + } else if (strstr(key, "rotateNum") == key) { + configuration.rotateNum = atoi(value); + } else if (strstr(key, "rotateSizeMB") == key) { + configuration.rotateSizeMB = atoi(value); } else if (strstr(key, "logPath") == key) { configuration.logFilePath.assign(value, STR_SIZE(value, next)); } else if (strstr(key, "start") == key) { diff --git a/src/main/cpp/globals.h b/src/main/cpp/globals.h index f83f2c232..513663fd8 100755 --- a/src/main/cpp/globals.h +++ b/src/main/cpp/globals.h @@ -25,6 +25,8 @@ void setProfiler(Profiler *p); const int DEFAULT_SAMPLING_INTERVAL = 1; const int DEFAULT_MAX_FRAMES_TO_CAPTURE = 128; const int MAX_FRAMES_TO_CAPTURE = 2048; +const int DEFAULT_ROTATE_SIZE_MB = 5; +const int DEFAULT_ROTATE_NUM = 5; #if defined(STATIC_ALLOCATION_ALLOCA) #define STATIC_ARRAY(NAME, TYPE, SIZE, MAXSZ) TYPE *NAME = (TYPE*)alloca((SIZE) * sizeof(TYPE)) @@ -41,6 +43,8 @@ char *safe_copy_string(const char *value, const char *next); struct ConfigurationOptions { /** Interval in microseconds */ int samplingIntervalMin, samplingIntervalMax; + /** RotateSize in MB */ + int rotateNum, rotateSizeMB; std::string logFilePath; std::string host; std::string port; @@ -50,6 +54,8 @@ struct ConfigurationOptions { ConfigurationOptions() : samplingIntervalMin(DEFAULT_SAMPLING_INTERVAL), samplingIntervalMax(DEFAULT_SAMPLING_INTERVAL), + rotateNum(DEFAULT_ROTATE_NUM), + rotateSizeMB(DEFAULT_ROTATE_SIZE_MB), logFilePath(""), host(""), port(""), @@ -60,6 +66,8 @@ struct ConfigurationOptions { ConfigurationOptions(const ConfigurationOptions &config) : samplingIntervalMin(config.samplingIntervalMin), samplingIntervalMax(config.samplingIntervalMax), + rotateNum(config.rotateNum), + rotateSizeMB(config.rotateSizeMB), logFilePath(config.logFilePath), host(config.host), port(config.port), diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 489e16153..9f31ef9c4 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -1,6 +1,10 @@ +#include "log_writer.h" + +#include #include -#include "log_writer.h" +#include "concurrent_map.h" +#include "globals.h" using std::copy; @@ -12,8 +16,13 @@ bool isLittleEndian() { static bool IS_LITTLE_ENDIAN = isLittleEndian(); -LogWriter::LogWriter(std::string &fileName, jvmtiEnv *jvmti) : - file(fileName, std::ofstream::out | std::ofstream::binary), output_(this->file), +LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti) : + fileName(fileName), + file(fileName, std::ofstream::out | std::ofstream::binary), + rotateNum(rotateNum), + rotateSize(rotateSizeMB * 1024 * 1024), + size(0), + output_(this->file), frameInfoFoo(NULL), jvmti_(jvmti) { if (output_.fail()) { // The JVM will still continue to run though; could call abort() to terminate the JVM abnormally. @@ -27,15 +36,16 @@ LogWriter::LogWriter(ostream &output, GetFrameInformation frameLookup, jvmtiEnv } template -void LogWriter::writeValue(const T &value) { +void LogWriter::writeValue(ofstream& fout, const T &value) { if (IS_LITTLE_ENDIAN) { const char *data = reinterpret_cast(&value); for (int i = sizeof(value) - 1; i >= 0; i--) { - output_.put(data[i]); + fout.put(data[i]); } } else { - output_.write(reinterpret_cast(&value), sizeof(value)); + fout.write(reinterpret_cast(&value), sizeof(value)); } + size += sizeof(value); } static jint bci2line(jint bci, jvmtiLineNumberEntry *table, jint entry_count) { @@ -102,7 +112,8 @@ void LogWriter::record(const JVMPI_CallTrace &trace, ThreadBucketPtr info) { } void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info) { - recordTraceStart(trace.num_frames, (map::HashType)trace.env_id, ts, info); + ofstream& fout = getOut(); + recordTraceStart(fout, trace.num_frames, (map::HashType)trace.env_id, ts, info); for (int i = 0; i < trace.num_frames; i++) { JVMPI_CallFrame frame = trace.frames[i]; @@ -121,7 +132,7 @@ void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadB } } -void LogWriter::inspectMethod(const method_id methodId, const JVMPI_CallFrame &frame) { +void LogWriter::inspectMethod(ofstream& fout, const method_id methodId, const JVMPI_CallFrame &frame) { if (knownMethods.count(methodId) > 0) { return; } @@ -135,7 +146,7 @@ void LogWriter::inspectMethod(const method_id methodId, const JVMPI_CallFrame &f } } -void LogWriter::inspectThread(map::HashType &threadId, ThreadBucketPtr& info) { +void LogWriter::inspectThread(ofstream& fout, map::HashType &threadId, ThreadBucketPtr& info) { std::string threadName; if (info.defined()) { @@ -149,80 +160,89 @@ void LogWriter::inspectThread(map::HashType &threadId, ThreadBucketPtr& info) { knownThreads.insert(threadId); - output_.put(THREAD_META); - writeValue(threadId); - writeWithSize(threadName.c_str()); - output_.flush(); + fout.put(THREAD_META); + size++; + writeValue(fout, threadId); + writeWithSize(fout, threadName.c_str()); + fout.flush(); } -void LogWriter::recordTraceStart(const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { map::HashType threadId = -envHash; inspectThread(threadId, info); - output_.put(TRACE_START); - writeValue(numFrames); - writeValue(threadId); - output_.flush(); + fout.put(TRACE_START); + size++; + writeValue(fout, numFrames); + writeValue(fout, threadId); + fout.flush(); } -void LogWriter::recordTraceStart(const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { map::HashType threadId = -envHash; // mark unrecognized threads with negative id's - inspectThread(threadId, info); - - output_.put(TRACE_WITH_TIME); - writeValue(numFrames); - writeValue(threadId); - writeValue((int64_t)ts.tv_sec); - writeValue((int64_t)ts.tv_nsec); - output_.flush(); + inspectThread(fout, threadId, info); + + fout.put(TRACE_WITH_TIME); + size++; + writeValue(fout, numFrames); + writeValue(fout, threadId); + writeValue(fout, (int64_t)ts.tv_sec); + writeValue(fout, (int64_t)ts.tv_nsec); + fout.flush(); } -void LogWriter::recordFrame(const jint bci, const jint lineNumber, const method_id methodId) { - output_.put(FRAME_FULL); - writeValue(bci); - writeValue(lineNumber); - writeValue(methodId); - output_.flush(); +void LogWriter::recordFrame(ofstream& fout, const jint bci, const jint lineNumber, const method_id methodId) { + fout.put(FRAME_FULL); + size++; + writeValue(fout, bci); + writeValue(fout, lineNumber); + writeValue(fout, methodId); + fout.flush(); } // kept for old format tests -void LogWriter::recordFrame(const jint bci, const method_id methodId) { - output_.put(FRAME_BCI_ONLY); - writeValue(bci); - writeValue(methodId); - output_.flush(); +void LogWriter::recordFrame(ofstream& fout, const jint bci, const method_id methodId) { + fout.put(FRAME_BCI_ONLY); + size++; + writeValue(fout, bci); + writeValue(fout, methodId); + fout.flush(); } -void LogWriter::writeWithSize(const char *value) { +void LogWriter::writeWithSize(ofstream& fout, const char *value) { jint size = (jint) strlen(value); - writeValue(size); - output_.write(value, size); + writeValue(fout, size); + fout.write(value, size); } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *methodName) { - output_.put(NEW_METHOD); - writeValue(methodId); - writeWithSize(fileName); - writeWithSize(className); - writeWithSize(methodName); - output_.flush(); + ofstream& fout = getOut(); + fout.put(NEW_METHOD); + size++; + writeValue(fout, methodId); + writeWithSize(fout, fileName); + writeWithSize(fout, className); + writeWithSize(fout, methodName); + fout.flush(); } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *genericClassName, const char *methodName, const char *methodSignature, const char *genericMethodSignature) { - output_.put(NEW_METHOD_SIGNATURE); - writeValue(methodId); - writeWithSize(fileName); - writeWithSize(className); - writeWithSize(genericClassName ? genericClassName : ""); - writeWithSize(methodName); - writeWithSize(methodSignature); - writeWithSize(genericMethodSignature ? genericMethodSignature : ""); - output_.flush(); + ofstream& fout = getOut(); + fout.put(NEW_METHOD_SIGNATURE); + size++; + writeValue(fout, methodId); + writeWithSize(fout, fileName); + writeWithSize(fout, className); + writeWithSize(fout, genericClassName ? genericClassName : ""); + writeWithSize(fout, methodName); + writeWithSize(fout, methodSignature); + writeWithSize(fout, genericMethodSignature ? genericMethodSignature : ""); + fout.flush(); } bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { @@ -281,4 +301,31 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { ); return true; -} \ No newline at end of file +} + +ofstream& LogWriter::getOut() { + if (size >= rotateSize) { + // rotate + file.close(); + size = 0; + for (int i = rotateNum; i > 0; --i) { + // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 + char buff[1024]; + if (i > 1) { + snprintf(buff, sizeof(buff), "%s.%d", fileName, i - 1); + } else { + snprintf(buff, sizeof(buff), "%s", fileName); + } + + char buff_target[1024]; + snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName, i); + + std::remove(buff_target); + std::rename(buff, buff_target); + } + // recreate log + file = std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + } else { + return file; + } +} diff --git a/src/main/cpp/log_writer.h b/src/main/cpp/log_writer.h index a3edf4c53..316ba1445 100644 --- a/src/main/cpp/log_writer.h +++ b/src/main/cpp/log_writer.h @@ -51,24 +51,14 @@ const jint ERR_NO_LINE_FOUND= -101; class LogWriter : public QueueListener, public MethodListener { public: - explicit LogWriter(std::string &fileName, jvmtiEnv *jvmti); + explicit LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti); - explicit LogWriter(ostream &output, GetFrameInformation frameLookup, jvmtiEnv *jvmti); + explicit LogWriter(ofstream &output, GetFrameInformation frameLookup, jvmtiEnv *jvmti); virtual void record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info = ThreadBucketPtr(nullptr)); void record(const JVMPI_CallTrace &trace, ThreadBucketPtr info = ThreadBucketPtr(nullptr)); - void recordTraceStart(const jint numFrames, map::HashType envHash, ThreadBucketPtr& info); - - void recordTraceStart(const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info); - - // method are unique pointers, use a long to standardise - // between 32 and 64 bits - void recordFrame(const jint bci, const jint lineNumber, method_id methodId); - - void recordFrame(const jint bci, method_id methodId); - bool lookupFrameInformation(const JVMPI_CallFrame &frame); virtual void recordNewMethod(method_id methodId, const char *file_name, @@ -79,8 +69,13 @@ class LogWriter : public QueueListener, public MethodListener { const char *methodName, const char *methodSignature, const char *genericMethodSignature); private: + std::string fileName; + int rotateSize; + int rotateNum; + int size; + ofstream file; - ostream& output_; + ofstream& output_; GetFrameInformation frameInfoFoo; jvmtiEnv *const jvmti_; @@ -90,13 +85,27 @@ class LogWriter : public QueueListener, public MethodListener { unordered_set knownThreads; template - void writeValue(const T &value); + void writeValue(ofstream& fout, const T &value); + + void writeWithSize(ofstream& fout, const char *value); + + void inspectMethod(ofstream& fout, const method_id methodId, const JVMPI_CallFrame &frame); + + void inspectThread(ofstream& fout, map::HashType &threadId, ThreadBucketPtr& info); + + + void recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info); + + void recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info); + + // method are unique pointers, use a long to standardise + // between 32 and 64 bits + void recordFrame(ofstream& fout, const jint bci, const jint lineNumber, method_id methodId); - void writeWithSize(const char *value); + void recordFrame(ofstream& fout, const jint bci, method_id methodId); - void inspectMethod(const method_id methodId, const JVMPI_CallFrame &frame); - void inspectThread(map::HashType &threadId, ThreadBucketPtr& info); + ofstream& getOut(); jint getLineNo(jint bci, jmethodID methodId); diff --git a/src/main/cpp/profiler.cpp b/src/main/cpp/profiler.cpp index 383afa993..41dc4f5a4 100755 --- a/src/main/cpp/profiler.cpp +++ b/src/main/cpp/profiler.cpp @@ -159,7 +159,7 @@ void Profiler::configure() { } else { configuration_.logFilePath = liveConfiguration.logFilePath; } - writer = std::unique_ptr(new LogWriter(liveConfiguration.logFilePath, jvmti_)); + writer = std::unique_ptr(new LogWriter(liveConfiguration.logFilePath, liveConfiguration.rotateNum, liveConfiguration.rotateSizeMB, jvmti_)); } needsUpdate = needsUpdate || From e695503fbf949c89976ad64d596d406435196cf9 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sat, 15 Dec 2018 09:05:13 +0800 Subject: [PATCH 02/21] fix cotr --- src/main/cpp/log_writer.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 9f31ef9c4..d6116cb79 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -30,8 +30,13 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm } } -LogWriter::LogWriter(ostream &output, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : - file(), output_(output), frameInfoFoo(frameLookup), jvmti_(jvmti) { +LogWriter::LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : + file(), + output_(output), + rotateNum(rotateNum), + rotateSize(rotateSizeMB * 1024 * 1024), + frameInfoFoo(frameLookup), + jvmti_(jvmti) { // Old interface for backward compatibility and testing purposes } From 181ce41dcfd73c5e001469ecb95c8b852b95ff32 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sat, 15 Dec 2018 10:08:31 +0800 Subject: [PATCH 03/21] avoid compilation --- .gitignore | 2 ++ README.md | 1 + src/main/cpp/log_writer.cpp | 68 +++++++++++++++++++------------------ src/main/cpp/log_writer.h | 11 +++--- 4 files changed, 44 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index c9ce332fb..2dd70980a 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ Testing src/main/cpp/CMakeLists.txt src/main/cpp/cmake-build-debug/ + +src/main/cpp/src/ diff --git a/README.md b/README.md index d9470b9f2..112652182 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,4 @@ A usable and honest profiler for the JVM. For documentation please refer to * [Download the Binary](http://insightfullogic.com/honest-profiler.zip) * [How to Build](https://github.com/RichardWarburton/honest-profiler/wiki/How-to-build) +UNITTEST_INCLUDE_DIRS="/usr/local/Cellar/unittest-cpp/2.0.0/include/UnitTest++/" UNITTEST_LIBRARIES="UnitTest++" cmake CMakeLists.txt diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index d6116cb79..7a46af76d 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -18,10 +18,10 @@ static bool IS_LITTLE_ENDIAN = isLittleEndian(); LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti) : fileName(fileName), - file(fileName, std::ofstream::out | std::ofstream::binary), rotateNum(rotateNum), rotateSize(rotateSizeMB * 1024 * 1024), size(0), + file(fileName, std::ofstream::out | std::ofstream::binary), output_(this->file), frameInfoFoo(NULL), jvmti_(jvmti) { if (output_.fail()) { @@ -30,18 +30,20 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm } } -LogWriter::LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : - file(), - output_(output), +LogWriter::LogWriter(ofstream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : + fileName(), rotateNum(rotateNum), rotateSize(rotateSizeMB * 1024 * 1024), + size(0), + file(), + output_(output), frameInfoFoo(frameLookup), jvmti_(jvmti) { // Old interface for backward compatibility and testing purposes } template -void LogWriter::writeValue(ofstream& fout, const T &value) { +void LogWriter::writeValue(ofstream & fout, const T &value) { if (IS_LITTLE_ENDIAN) { const char *data = reinterpret_cast(&value); for (int i = sizeof(value) - 1; i >= 0; i--) { @@ -117,7 +119,7 @@ void LogWriter::record(const JVMPI_CallTrace &trace, ThreadBucketPtr info) { } void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info) { - ofstream& fout = getOut(); + ofstream & fout = getOut(); recordTraceStart(fout, trace.num_frames, (map::HashType)trace.env_id, ts, info); for (int i = 0; i < trace.num_frames; i++) { @@ -128,16 +130,16 @@ void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadB jint bci = frame.lineno; if (bci > 0) { jint lineno = getLineNo(bci, frame.method_id); - recordFrame(bci, lineno, methodId); + recordFrame(fout, bci, lineno, methodId); } else { - recordFrame(bci, methodId); + recordFrame(fout, bci, methodId); } - inspectMethod(methodId, frame); + inspectMethod(fout, methodId, frame); } } -void LogWriter::inspectMethod(ofstream& fout, const method_id methodId, const JVMPI_CallFrame &frame) { +void LogWriter::inspectMethod(ofstream & fout, const method_id methodId, const JVMPI_CallFrame &frame) { if (knownMethods.count(methodId) > 0) { return; } @@ -151,7 +153,7 @@ void LogWriter::inspectMethod(ofstream& fout, const method_id methodId, const JV } } -void LogWriter::inspectThread(ofstream& fout, map::HashType &threadId, ThreadBucketPtr& info) { +void LogWriter::inspectThread(ofstream & fout, map::HashType &threadId, ThreadBucketPtr& info) { std::string threadName; if (info.defined()) { @@ -166,31 +168,31 @@ void LogWriter::inspectThread(ofstream& fout, map::HashType &threadId, ThreadBuc knownThreads.insert(threadId); fout.put(THREAD_META); - size++; + size+=8; writeValue(fout, threadId); writeWithSize(fout, threadName.c_str()); fout.flush(); } -void LogWriter::recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { map::HashType threadId = -envHash; - inspectThread(threadId, info); + inspectThread(fout, threadId, info); fout.put(TRACE_START); - size++; + size+=8; writeValue(fout, numFrames); writeValue(fout, threadId); fout.flush(); } -void LogWriter::recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { map::HashType threadId = -envHash; // mark unrecognized threads with negative id's inspectThread(fout, threadId, info); fout.put(TRACE_WITH_TIME); - size++; + size+=8; writeValue(fout, numFrames); writeValue(fout, threadId); writeValue(fout, (int64_t)ts.tv_sec); @@ -198,9 +200,9 @@ void LogWriter::recordTraceStart(ofstream& fout, const jint numFrames, map::Hash fout.flush(); } -void LogWriter::recordFrame(ofstream& fout, const jint bci, const jint lineNumber, const method_id methodId) { +void LogWriter::recordFrame(ofstream &fout, const jint bci, const jint lineNumber, const method_id methodId) { fout.put(FRAME_FULL); - size++; + size+=8; writeValue(fout, bci); writeValue(fout, lineNumber); writeValue(fout, methodId); @@ -208,25 +210,26 @@ void LogWriter::recordFrame(ofstream& fout, const jint bci, const jint lineNumbe } // kept for old format tests -void LogWriter::recordFrame(ofstream& fout, const jint bci, const method_id methodId) { +void LogWriter::recordFrame(ofstream &fout, const jint bci, const method_id methodId) { fout.put(FRAME_BCI_ONLY); - size++; + size+=8; writeValue(fout, bci); writeValue(fout, methodId); fout.flush(); } -void LogWriter::writeWithSize(ofstream& fout, const char *value) { +void LogWriter::writeWithSize(ofstream &fout, const char *value) { jint size = (jint) strlen(value); writeValue(fout, size); fout.write(value, size); + this->size=+size; } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *methodName) { - ofstream& fout = getOut(); + ofstream & fout = getOut(); fout.put(NEW_METHOD); - size++; + size+=8; writeValue(fout, methodId); writeWithSize(fout, fileName); writeWithSize(fout, className); @@ -237,9 +240,9 @@ void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileNa void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *genericClassName, const char *methodName, const char *methodSignature, const char *genericMethodSignature) { - ofstream& fout = getOut(); + ofstream & fout = getOut(); fout.put(NEW_METHOD_SIGNATURE); - size++; + size+=8; writeValue(fout, methodId); writeWithSize(fout, fileName); writeWithSize(fout, className); @@ -308,8 +311,8 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { return true; } -ofstream& LogWriter::getOut() { - if (size >= rotateSize) { +ofstream & LogWriter::getOut() { + if (!fileName.empty() && size >= rotateSize) { // rotate file.close(); size = 0; @@ -317,20 +320,19 @@ ofstream& LogWriter::getOut() { // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 char buff[1024]; if (i > 1) { - snprintf(buff, sizeof(buff), "%s.%d", fileName, i - 1); + snprintf(buff, sizeof(buff), "%s.%d", fileName.c_str(), i - 1); } else { - snprintf(buff, sizeof(buff), "%s", fileName); + snprintf(buff, sizeof(buff), "%s", fileName.c_str()); } char buff_target[1024]; - snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName, i); + snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); std::remove(buff_target); std::rename(buff, buff_target); } // recreate log file = std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); - } else { - return file; } + return file; } diff --git a/src/main/cpp/log_writer.h b/src/main/cpp/log_writer.h index 316ba1445..953a1fdf5 100644 --- a/src/main/cpp/log_writer.h +++ b/src/main/cpp/log_writer.h @@ -1,11 +1,12 @@ #include - -#include #include +#include -#include "thread_map.h" #include "circular_queue.h" +#include "concurrent_map.h" +#include "globals.h" #include "stacktraces.h" +#include "thread_map.h" #ifndef LOG_WRITER_H #define LOG_WRITER_H @@ -53,7 +54,7 @@ class LogWriter : public QueueListener, public MethodListener { public: explicit LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti); - explicit LogWriter(ofstream &output, GetFrameInformation frameLookup, jvmtiEnv *jvmti); + explicit LogWriter(ofstream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti); virtual void record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info = ThreadBucketPtr(nullptr)); @@ -70,8 +71,8 @@ class LogWriter : public QueueListener, public MethodListener { private: std::string fileName; - int rotateSize; int rotateNum; + int rotateSize; int size; ofstream file; From 7538cf6e839af4780f84f7e30b339296184b0bc2 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sat, 15 Dec 2018 23:31:01 +0800 Subject: [PATCH 04/21] fix compliation error --- .gitignore | 2 +- src/main/cpp/log_writer.cpp | 44 +++++++++++++++++--------------- src/main/cpp/log_writer.h | 41 +++++++++++++++-------------- src/test/cpp/test_log_writer.cpp | 22 +++++++++------- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index 2dd70980a..602471e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,4 @@ Testing src/main/cpp/CMakeLists.txt src/main/cpp/cmake-build-debug/ -src/main/cpp/src/ +# src/main/cpp/src/ diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 7a46af76d..7b57be8e2 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -3,8 +3,6 @@ #include #include -#include "concurrent_map.h" -#include "globals.h" using std::copy; @@ -21,21 +19,22 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm rotateNum(rotateNum), rotateSize(rotateSizeMB * 1024 * 1024), size(0), - file(fileName, std::ofstream::out | std::ofstream::binary), - output_(this->file), + file(NULL), + output_(*this->file), frameInfoFoo(NULL), jvmti_(jvmti) { + file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); if (output_.fail()) { // The JVM will still continue to run though; could call abort() to terminate the JVM abnormally. logError("ERROR: Failed to open file %s for writing\n", fileName.c_str()); } } -LogWriter::LogWriter(ofstream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : +LogWriter::LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : fileName(), rotateNum(rotateNum), rotateSize(rotateSizeMB * 1024 * 1024), size(0), - file(), + file(NULL), output_(output), frameInfoFoo(frameLookup), jvmti_(jvmti) { @@ -43,7 +42,7 @@ LogWriter::LogWriter(ofstream &output, int rotateNum, int rotateSizeMB, GetFrame } template -void LogWriter::writeValue(ofstream & fout, const T &value) { +void LogWriter::writeValue(ostream & fout, const T &value) { if (IS_LITTLE_ENDIAN) { const char *data = reinterpret_cast(&value); for (int i = sizeof(value) - 1; i >= 0; i--) { @@ -119,7 +118,7 @@ void LogWriter::record(const JVMPI_CallTrace &trace, ThreadBucketPtr info) { } void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info) { - ofstream & fout = getOut(); + ostream & fout = getOut(); recordTraceStart(fout, trace.num_frames, (map::HashType)trace.env_id, ts, info); for (int i = 0; i < trace.num_frames; i++) { @@ -139,7 +138,7 @@ void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadB } } -void LogWriter::inspectMethod(ofstream & fout, const method_id methodId, const JVMPI_CallFrame &frame) { +void LogWriter::inspectMethod(ostream & fout, const method_id methodId, const JVMPI_CallFrame &frame) { if (knownMethods.count(methodId) > 0) { return; } @@ -153,7 +152,7 @@ void LogWriter::inspectMethod(ofstream & fout, const method_id methodId, const J } } -void LogWriter::inspectThread(ofstream & fout, map::HashType &threadId, ThreadBucketPtr& info) { +void LogWriter::inspectThread(ostream & fout, map::HashType &threadId, ThreadBucketPtr& info) { std::string threadName; if (info.defined()) { @@ -174,7 +173,7 @@ void LogWriter::inspectThread(ofstream & fout, map::HashType &threadId, ThreadBu fout.flush(); } -void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ostream & fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info) { map::HashType threadId = -envHash; inspectThread(fout, threadId, info); @@ -186,7 +185,7 @@ void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::Has fout.flush(); } -void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { +void LogWriter::recordTraceStart(ostream & fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info) { map::HashType threadId = -envHash; // mark unrecognized threads with negative id's inspectThread(fout, threadId, info); @@ -200,7 +199,7 @@ void LogWriter::recordTraceStart(ofstream & fout, const jint numFrames, map::Has fout.flush(); } -void LogWriter::recordFrame(ofstream &fout, const jint bci, const jint lineNumber, const method_id methodId) { +void LogWriter::recordFrame(ostream & fout, const jint bci, const jint lineNumber, const method_id methodId) { fout.put(FRAME_FULL); size+=8; writeValue(fout, bci); @@ -210,7 +209,7 @@ void LogWriter::recordFrame(ofstream &fout, const jint bci, const jint lineNumbe } // kept for old format tests -void LogWriter::recordFrame(ofstream &fout, const jint bci, const method_id methodId) { +void LogWriter::recordFrame(ostream & fout, const jint bci, const method_id methodId) { fout.put(FRAME_BCI_ONLY); size+=8; writeValue(fout, bci); @@ -218,7 +217,7 @@ void LogWriter::recordFrame(ofstream &fout, const jint bci, const method_id meth fout.flush(); } -void LogWriter::writeWithSize(ofstream &fout, const char *value) { +void LogWriter::writeWithSize(ostream & fout, const char *value) { jint size = (jint) strlen(value); writeValue(fout, size); fout.write(value, size); @@ -227,7 +226,7 @@ void LogWriter::writeWithSize(ofstream &fout, const char *value) { void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *methodName) { - ofstream & fout = getOut(); + ostream & fout = getOut(); fout.put(NEW_METHOD); size+=8; writeValue(fout, methodId); @@ -240,7 +239,7 @@ void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileNa void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *genericClassName, const char *methodName, const char *methodSignature, const char *genericMethodSignature) { - ofstream & fout = getOut(); + ostream & fout = getOut(); fout.put(NEW_METHOD_SIGNATURE); size+=8; writeValue(fout, methodId); @@ -311,10 +310,11 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { return true; } -ofstream & LogWriter::getOut() { +ostream& LogWriter::getOut() { if (!fileName.empty() && size >= rotateSize) { // rotate - file.close(); + file->close(); + file = NULL; size = 0; for (int i = rotateNum; i > 0; --i) { // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 @@ -332,7 +332,9 @@ ofstream & LogWriter::getOut() { std::rename(buff, buff_target); } // recreate log - file = std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + return *file; + } else { + return output_; } - return file; } diff --git a/src/main/cpp/log_writer.h b/src/main/cpp/log_writer.h index 953a1fdf5..52124fbc1 100644 --- a/src/main/cpp/log_writer.h +++ b/src/main/cpp/log_writer.h @@ -54,12 +54,26 @@ class LogWriter : public QueueListener, public MethodListener { public: explicit LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti); - explicit LogWriter(ofstream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti); + explicit LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti); virtual void record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info = ThreadBucketPtr(nullptr)); void record(const JVMPI_CallTrace &trace, ThreadBucketPtr info = ThreadBucketPtr(nullptr)); + void inspectMethod(ostream& fout, const method_id methodId, const JVMPI_CallFrame &frame); + + void inspectThread(ostream& fout, map::HashType &threadId, ThreadBucketPtr& info); + + void recordTraceStart(ostream& fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info); + + void recordTraceStart(ostream& fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info); + + // method are unique pointers, use a long to standardise + // between 32 and 64 bits + void recordFrame(ostream& fout, const jint bci, const jint lineNumber, method_id methodId); + + void recordFrame(ostream& fout, const jint bci, method_id methodId); + bool lookupFrameInformation(const JVMPI_CallFrame &frame); virtual void recordNewMethod(method_id methodId, const char *file_name, @@ -75,8 +89,8 @@ class LogWriter : public QueueListener, public MethodListener { int rotateSize; int size; - ofstream file; - ofstream& output_; + ofstream* file; + ostream& output_; GetFrameInformation frameInfoFoo; jvmtiEnv *const jvmti_; @@ -86,27 +100,12 @@ class LogWriter : public QueueListener, public MethodListener { unordered_set knownThreads; template - void writeValue(ofstream& fout, const T &value); - - void writeWithSize(ofstream& fout, const char *value); - - void inspectMethod(ofstream& fout, const method_id methodId, const JVMPI_CallFrame &frame); - - void inspectThread(ofstream& fout, map::HashType &threadId, ThreadBucketPtr& info); - - - void recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, ThreadBucketPtr& info); - - void recordTraceStart(ofstream& fout, const jint numFrames, map::HashType envHash, const timespec &ts, ThreadBucketPtr& info); - - // method are unique pointers, use a long to standardise - // between 32 and 64 bits - void recordFrame(ofstream& fout, const jint bci, const jint lineNumber, method_id methodId); + void writeValue(ostream& fout, const T &value); - void recordFrame(ofstream& fout, const jint bci, method_id methodId); + void writeWithSize(ostream& fout, const char *value); - ofstream& getOut(); + ostream& getOut(); jint getLineNo(jint bci, jmethodID methodId); diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index 1d3fcdec5..1ee944020 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -1,12 +1,16 @@ +#include +#include #include -#include #include #include -#include "fixtures.h" -#include "ostreambuf.h" -#include "test.h" +#include "../../main/cpp/circular_queue.h" +#include "../../main/cpp/concurrent_map.h" +#include "../../main/cpp/globals.h" #include "../../main/cpp/log_writer.h" +#include "../../main/cpp/stacktraces.h" +#include "../../main/cpp/thread_map.h" +#include "ostreambuf.h" using std::ostream; using std::ofstream; @@ -26,7 +30,7 @@ bool stubFrameInformation(const JVMPI_CallFrame &frame, MethodListener &listener char buffer[100] = {}; \ ostreambuf outputBuffer(buffer, sizeof(buffer)); \ ostream output(&outputBuffer); \ - LogWriter logWriter(output, &stubFrameInformation, NULL); \ + LogWriter logWriter(output, 5, 5, &stubFrameInformation, NULL); \ CircularQueue *queue = new CircularQueue(logWriter, DEFAULT_MAX_FRAMES_TO_CAPTURE); #define done() delete queue; @@ -37,7 +41,7 @@ TEST(RecordsStartOfStackTrace) { timespec tspec = {44, 55}; ThreadBucketPtr tptr(threadInfo.get(), false); - logWriter.recordTraceStart(2, 3, tspec, tptr); + logWriter.recordTraceStart(output, 2, 3, tspec, tptr); int cnt = 0; CHECK_EQUAL(THREAD_META, buffer[cnt]); @@ -64,7 +68,7 @@ TEST(SupportsHighThreadId) { // LONG_MAX long bigNumber = std::numeric_limits::max(); ThreadBucketPtr tBuck(nullptr); - logWriter.recordTraceStart(2, (map::HashType)bigNumber, tspec, tBuck); + logWriter.recordTraceStart(output, 2, (map::HashType)bigNumber, tspec, tBuck); CHECK_EQUAL(THREAD_META, buffer[0]); CHECK_EQUAL(0, buffer[12]); @@ -78,7 +82,7 @@ TEST(SupportsHighThreadId) { TEST(RecordsStackFrames) { givenLogWriter(); - logWriter.recordFrame(5, 6); + logWriter.recordFrame(output, 5, 6); CHECK_EQUAL(FRAME_BCI_ONLY, buffer[0]); CHECK_EQUAL(5, buffer[4]); CHECK_EQUAL(0, buffer[3]); @@ -186,7 +190,7 @@ TEST(DumpTestFile) { givenStackTrace(); ofstream output("dump.hpl", ofstream::out | ofstream::binary); - LogWriter logWriter(output, &dumpStubFrameInformation, NULL); + LogWriter logWriter(output, 5, 5, &dumpStubFrameInformation, NULL); logWriter.record(trace); logWriter.record(trace); From 89b0ad175e77045d48712b05aad69acfc8d3188c Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sat, 15 Dec 2018 23:41:18 +0800 Subject: [PATCH 05/21] remove useless include --- src/test/cpp/test_log_writer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index 1ee944020..4169bdef8 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include From dc382db1d85f5eaa101ec6cd0cc37659a62f9e52 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sun, 16 Dec 2018 10:02:14 +0800 Subject: [PATCH 06/21] remove useless import to make sure complation works --- src/test/cpp/test_log_writer.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index 4169bdef8..99303b298 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -1,14 +1,12 @@ #include #include +#include #include #include -#include "../../main/cpp/circular_queue.h" -#include "../../main/cpp/concurrent_map.h" -#include "../../main/cpp/globals.h" +#include "test.h" +#include "fixtures.h" #include "../../main/cpp/log_writer.h" -#include "../../main/cpp/stacktraces.h" -#include "../../main/cpp/thread_map.h" #include "ostreambuf.h" using std::ostream; @@ -29,7 +27,7 @@ bool stubFrameInformation(const JVMPI_CallFrame &frame, MethodListener &listener char buffer[100] = {}; \ ostreambuf outputBuffer(buffer, sizeof(buffer)); \ ostream output(&outputBuffer); \ - LogWriter logWriter(output, 5, 5, &stubFrameInformation, NULL); \ + LogWriter logWriter(output, 5, 5, &stubFrameInformation, NULL); \ CircularQueue *queue = new CircularQueue(logWriter, DEFAULT_MAX_FRAMES_TO_CAPTURE); #define done() delete queue; From b341d5d4430cce84365353a37202bf5779370620 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sun, 16 Dec 2018 10:12:32 +0800 Subject: [PATCH 07/21] update readme for mac --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 112652182..54b560080 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,10 @@ A usable and honest profiler for the JVM. For documentation please refer to * [Download the Binary](http://insightfullogic.com/honest-profiler.zip) * [How to Build](https://github.com/RichardWarburton/honest-profiler/wiki/How-to-build) UNITTEST_INCLUDE_DIRS="/usr/local/Cellar/unittest-cpp/2.0.0/include/UnitTest++/" UNITTEST_LIBRARIES="UnitTest++" cmake CMakeLists.txt + +[MAC] +# Use brew to install unittest++ + +# make sure unittest++ available to compliers : export paths +export LIBRARY_PATH=/usr/local/Cellar/unittest-cpp/2.0.0/lib/ +export CPLUS_INCLUDE_PATH="/usr/local/Cellar/unittest-cpp/2.0.0/include/" From 85c4ca94bfea70b3b235dcf6cadc011b1dda1621 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sun, 16 Dec 2018 11:51:20 +0800 Subject: [PATCH 08/21] fix error initlize --- src/main/cpp/log_writer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 7b57be8e2..eefe9634c 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -20,9 +20,10 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm rotateSize(rotateSizeMB * 1024 * 1024), size(0), file(NULL), - output_(*this->file), + output_(NULL), frameInfoFoo(NULL), jvmti_(jvmti) { file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + output_ = *this->file; if (output_.fail()) { // The JVM will still continue to run though; could call abort() to terminate the JVM abnormally. logError("ERROR: Failed to open file %s for writing\n", fileName.c_str()); From f1bb59c4bbb58e4d0dceef5815ccd519a9d2280d Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Sun, 16 Dec 2018 21:14:11 +0800 Subject: [PATCH 09/21] fix sigsgev --- src/main/cpp/log_writer.cpp | 8 ++++---- src/main/cpp/log_writer.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index eefe9634c..82fe0eb9e 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -23,8 +23,8 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm output_(NULL), frameInfoFoo(NULL), jvmti_(jvmti) { file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); - output_ = *this->file; - if (output_.fail()) { + output_ = this->file; + if (output_->fail()) { // The JVM will still continue to run though; could call abort() to terminate the JVM abnormally. logError("ERROR: Failed to open file %s for writing\n", fileName.c_str()); } @@ -36,7 +36,7 @@ LogWriter::LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameI rotateSize(rotateSizeMB * 1024 * 1024), size(0), file(NULL), - output_(output), + output_(&output), frameInfoFoo(frameLookup), jvmti_(jvmti) { // Old interface for backward compatibility and testing purposes @@ -336,6 +336,6 @@ ostream& LogWriter::getOut() { file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); return *file; } else { - return output_; + return *output_; } } diff --git a/src/main/cpp/log_writer.h b/src/main/cpp/log_writer.h index 52124fbc1..9efb03b29 100644 --- a/src/main/cpp/log_writer.h +++ b/src/main/cpp/log_writer.h @@ -90,7 +90,7 @@ class LogWriter : public QueueListener, public MethodListener { int size; ofstream* file; - ostream& output_; + ostream* output_; GetFrameInformation frameInfoFoo; jvmtiEnv *const jvmti_; From d3e2cb9dc50fe4a6ad428100efe323268e070c87 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 10:03:07 +0800 Subject: [PATCH 10/21] add some log --- src/main/cpp/log_writer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 82fe0eb9e..4a2f7bd62 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -317,6 +317,7 @@ ostream& LogWriter::getOut() { file->close(); file = NULL; size = 0; + printf("rotating file start >>> "); for (int i = rotateNum; i > 0; --i) { // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 char buff[1024]; @@ -325,17 +326,20 @@ ostream& LogWriter::getOut() { } else { snprintf(buff, sizeof(buff), "%s", fileName.c_str()); } - char buff_target[1024]; snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); + printf("remove target %s ", buff_target); std::remove(buff_target); std::rename(buff, buff_target); + printf("rename from %s to target %s ", buff, buff_target); } + printf("rotating file end <<< "); // recreate log file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); return *file; } else { + printf("rotateSize: %d, rotateNum: %d, current size: %d", rotateSize, rotateNum, size); return *output_; } } From 25cbd0f63d2d88cb205e48159a6313030a6f18ad Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 10:07:02 +0800 Subject: [PATCH 11/21] delete pointer --- src/main/cpp/log_writer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 4a2f7bd62..cc24a6069 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -315,6 +315,7 @@ ostream& LogWriter::getOut() { if (!fileName.empty() && size >= rotateSize) { // rotate file->close(); + delete file; file = NULL; size = 0; printf("rotating file start >>> "); From e3b8440e2f1f7011689f2fb2055beecbf32e7522 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 10:24:50 +0800 Subject: [PATCH 12/21] better logging --- src/main/cpp/log_writer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index cc24a6069..cd780bd68 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -330,17 +330,17 @@ ostream& LogWriter::getOut() { char buff_target[1024]; snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); - printf("remove target %s ", buff_target); + printf("remove target %s \n", buff_target); std::remove(buff_target); std::rename(buff, buff_target); - printf("rename from %s to target %s ", buff, buff_target); + printf("rename from %s to target %s \n", buff, buff_target); } printf("rotating file end <<< "); // recreate log file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); return *file; } else { - printf("rotateSize: %d, rotateNum: %d, current size: %d", rotateSize, rotateNum, size); + printf("rotateSize: %d, rotateNum: %d, current size: %d\n", rotateSize, rotateNum, size); return *output_; } } From d1c628d116fc79b57f97994cf301235c0fb8197a Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 14:50:50 +0800 Subject: [PATCH 13/21] fix size increase --- src/main/cpp/log_writer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index cd780bd68..a73136cd2 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -222,7 +222,7 @@ void LogWriter::writeWithSize(ostream & fout, const char *value) { jint size = (jint) strlen(value); writeValue(fout, size); fout.write(value, size); - this->size=+size; + this->size=+4; } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, From 318c4ebc5aa85adbfbba55fe6ce48fe57ab0eeeb Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 15:18:28 +0800 Subject: [PATCH 14/21] add threadid for debugging --- src/main/cpp/log_writer.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index a73136cd2..654d54a9f 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -2,7 +2,8 @@ #include #include - +#include +#include using std::copy; @@ -168,7 +169,7 @@ void LogWriter::inspectThread(ostream & fout, map::HashType &threadId, ThreadBuc knownThreads.insert(threadId); fout.put(THREAD_META); - size+=8; + size++; writeValue(fout, threadId); writeWithSize(fout, threadName.c_str()); fout.flush(); @@ -180,7 +181,7 @@ void LogWriter::recordTraceStart(ostream & fout, const jint numFrames, map::Hash inspectThread(fout, threadId, info); fout.put(TRACE_START); - size+=8; + size++; writeValue(fout, numFrames); writeValue(fout, threadId); fout.flush(); @@ -192,7 +193,7 @@ void LogWriter::recordTraceStart(ostream & fout, const jint numFrames, map::Hash inspectThread(fout, threadId, info); fout.put(TRACE_WITH_TIME); - size+=8; + size++; writeValue(fout, numFrames); writeValue(fout, threadId); writeValue(fout, (int64_t)ts.tv_sec); @@ -202,7 +203,7 @@ void LogWriter::recordTraceStart(ostream & fout, const jint numFrames, map::Hash void LogWriter::recordFrame(ostream & fout, const jint bci, const jint lineNumber, const method_id methodId) { fout.put(FRAME_FULL); - size+=8; + size++; writeValue(fout, bci); writeValue(fout, lineNumber); writeValue(fout, methodId); @@ -212,7 +213,7 @@ void LogWriter::recordFrame(ostream & fout, const jint bci, const jint lineNumbe // kept for old format tests void LogWriter::recordFrame(ostream & fout, const jint bci, const method_id methodId) { fout.put(FRAME_BCI_ONLY); - size+=8; + size++; writeValue(fout, bci); writeValue(fout, methodId); fout.flush(); @@ -222,14 +223,14 @@ void LogWriter::writeWithSize(ostream & fout, const char *value) { jint size = (jint) strlen(value); writeValue(fout, size); fout.write(value, size); - this->size=+4; + this->size+=4; } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *methodName) { ostream & fout = getOut(); fout.put(NEW_METHOD); - size+=8; + size++; writeValue(fout, methodId); writeWithSize(fout, fileName); writeWithSize(fout, className); @@ -242,7 +243,7 @@ void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileNa const char *methodName, const char *methodSignature, const char *genericMethodSignature) { ostream & fout = getOut(); fout.put(NEW_METHOD_SIGNATURE); - size+=8; + size++; writeValue(fout, methodId); writeWithSize(fout, fileName); writeWithSize(fout, className); @@ -312,13 +313,14 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { } ostream& LogWriter::getOut() { + std::thread::id this_id = std::this_thread::get_id(); if (!fileName.empty() && size >= rotateSize) { // rotate file->close(); delete file; file = NULL; size = 0; - printf("rotating file start >>> "); + std::cout <<" threadId: " << this_id << " rotating file start >>> \n"; for (int i = rotateNum; i > 0; --i) { // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 char buff[1024]; @@ -330,17 +332,18 @@ ostream& LogWriter::getOut() { char buff_target[1024]; snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); - printf("remove target %s \n", buff_target); + std::cout <<" threadId: " << this_id << " remove target " << buff_target << " \n"; std::remove(buff_target); std::rename(buff, buff_target); - printf("rename from %s to target %s \n", buff, buff_target); + std::cout <<" threadId: " << this_id << " rename from " << buff << " to " << buff_target << " \n"; } - printf("rotating file end <<< "); + std::cout <<" threadId: " << "rotating file end <<< \n"; // recreate log file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); return *file; } else { - printf("rotateSize: %d, rotateNum: %d, current size: %d\n", rotateSize, rotateNum, size); + std::cout <<" threadId: " << "rotateSize: " << rotateSize << + ", rotateNum: " << rotateNum << " current size: " << size << "\n"; return *output_; } } From 64535c0ba9561c194e9273d0b09b0531ffed67c0 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 15:30:46 +0800 Subject: [PATCH 15/21] use sizeof jint instead of hardcode 4 --- src/main/cpp/log_writer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 654d54a9f..7d679de41 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -223,7 +223,7 @@ void LogWriter::writeWithSize(ostream & fout, const char *value) { jint size = (jint) strlen(value); writeValue(fout, size); fout.write(value, size); - this->size+=4; + this->size+=sizeof(jint); } void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, From c4dcb535171d892bee431b349626892108074a50 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 17:56:57 +0800 Subject: [PATCH 16/21] add test --- src/test/cpp/test_log_writer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index 99303b298..e0afbbd70 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -192,3 +192,19 @@ TEST(DumpTestFile) { logWriter.record(trace); logWriter.record(trace); } + +TEST(FileRotation) { + givenStackTrace(); + ofstream output("dump-rotate.hpl", ofstream::out | ofstream::binary); + LogWriter logWriter(output, 3, 1, &dumpStubFrameInformation, NULL); + + // write 1M times, which must exceeds 1M log rotation size + for (int i = 0; i < 1024*1024; i++) { + logWriter.record(trace); + } + // Now verify the rotated file exists, and it's readable by the log reader + std::ifstream infile("dump-rotate.hpl.1"); + CHECK_EQUAL(0, infile.good()); + + done(); +} From 3ff03411dbe52a9f0491582a2df92f9335ab38f3 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Mon, 17 Dec 2018 20:19:37 +0800 Subject: [PATCH 17/21] fix compile error --- src/test/cpp/test_log_writer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index e0afbbd70..9200d2b67 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -206,5 +206,4 @@ TEST(FileRotation) { std::ifstream infile("dump-rotate.hpl.1"); CHECK_EQUAL(0, infile.good()); - done(); } From 8b27f37a4b18103f7f99ee58b1dd5c2fb7e374ab Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Tue, 18 Dec 2018 08:25:15 +0800 Subject: [PATCH 18/21] disable debug output --- src/main/cpp/log_writer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 7d679de41..bdeae7114 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -320,7 +320,7 @@ ostream& LogWriter::getOut() { delete file; file = NULL; size = 0; - std::cout <<" threadId: " << this_id << " rotating file start >>> \n"; + // std::cout <<" threadId: " << this_id << " rotating file start >>> \n"; for (int i = rotateNum; i > 0; --i) { // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 char buff[1024]; @@ -332,18 +332,18 @@ ostream& LogWriter::getOut() { char buff_target[1024]; snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); - std::cout <<" threadId: " << this_id << " remove target " << buff_target << " \n"; + // std::cout <<" threadId: " << this_id << " remove target " << buff_target << " \n"; std::remove(buff_target); std::rename(buff, buff_target); - std::cout <<" threadId: " << this_id << " rename from " << buff << " to " << buff_target << " \n"; + // std::cout <<" threadId: " << this_id << " rename from " << buff << " to " << buff_target << " \n"; } - std::cout <<" threadId: " << "rotating file end <<< \n"; + // std::cout <<" threadId: " << "rotating file end <<< \n"; // recreate log file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); return *file; } else { - std::cout <<" threadId: " << "rotateSize: " << rotateSize << - ", rotateNum: " << rotateNum << " current size: " << size << "\n"; + // std::cout <<" threadId: " << "rotateSize: " << rotateSize << + // ", rotateNum: " << rotateNum << " current size: " << size << "\n"; return *output_; } } From 79546b5bac5d7dd92730219cb57d6eda7b565fd3 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Tue, 18 Dec 2018 14:23:30 +0800 Subject: [PATCH 19/21] add deconstructor --- src/main/cpp/log_writer.cpp | 10 +++++++++- src/main/cpp/log_writer.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index bdeae7114..304451c76 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -313,7 +313,7 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { } ostream& LogWriter::getOut() { - std::thread::id this_id = std::this_thread::get_id(); + // std::thread::id this_id = std::this_thread::get_id(); if (!fileName.empty() && size >= rotateSize) { // rotate file->close(); @@ -347,3 +347,11 @@ ostream& LogWriter::getOut() { return *output_; } } + +LogWriter::~LogWriter() { + if (file != NULL) { + file->close(); + delete file; + file = NULL; + } +} diff --git a/src/main/cpp/log_writer.h b/src/main/cpp/log_writer.h index 9efb03b29..2664b623d 100644 --- a/src/main/cpp/log_writer.h +++ b/src/main/cpp/log_writer.h @@ -83,6 +83,8 @@ class LogWriter : public QueueListener, public MethodListener { const char *className, const char *genericClassName, const char *methodName, const char *methodSignature, const char *genericMethodSignature); + virtual ~LogWriter(); + private: std::string fileName; int rotateNum; From c7d20f70455fdc34739c0b1a9433b06f087c8933 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Tue, 18 Dec 2018 15:03:37 +0800 Subject: [PATCH 20/21] fix bug when rotation:forget to assign output_ --- src/main/cpp/log_writer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index 304451c76..f24b35be9 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -340,7 +340,8 @@ ostream& LogWriter::getOut() { // std::cout <<" threadId: " << "rotating file end <<< \n"; // recreate log file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); - return *file; + output_ = file; + return *output_; } else { // std::cout <<" threadId: " << "rotateSize: " << rotateSize << // ", rotateNum: " << rotateNum << " current size: " << size << "\n"; From 0fe82075119525f2b5bdfee9400989dfdb2b4e89 Mon Sep 17 00:00:00 2001 From: Ralph Su Date: Tue, 18 Dec 2018 19:44:14 +0800 Subject: [PATCH 21/21] beautify the PR --- .gitignore | 4 - src/main/cpp/globals.h | 8 +- src/main/cpp/log_writer.cpp | 138 +++++++++++++++---------------- src/test/cpp/test_log_writer.cpp | 23 +++--- 4 files changed, 84 insertions(+), 89 deletions(-) diff --git a/.gitignore b/.gitignore index 602471e4e..26181d3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,3 @@ Testing .project .cproject -src/main/cpp/CMakeLists.txt -src/main/cpp/cmake-build-debug/ - -# src/main/cpp/src/ diff --git a/src/main/cpp/globals.h b/src/main/cpp/globals.h index 513663fd8..c2e117bd9 100755 --- a/src/main/cpp/globals.h +++ b/src/main/cpp/globals.h @@ -54,8 +54,8 @@ struct ConfigurationOptions { ConfigurationOptions() : samplingIntervalMin(DEFAULT_SAMPLING_INTERVAL), samplingIntervalMax(DEFAULT_SAMPLING_INTERVAL), - rotateNum(DEFAULT_ROTATE_NUM), - rotateSizeMB(DEFAULT_ROTATE_SIZE_MB), + rotateNum(DEFAULT_ROTATE_NUM), + rotateSizeMB(DEFAULT_ROTATE_SIZE_MB), logFilePath(""), host(""), port(""), @@ -66,8 +66,8 @@ struct ConfigurationOptions { ConfigurationOptions(const ConfigurationOptions &config) : samplingIntervalMin(config.samplingIntervalMin), samplingIntervalMax(config.samplingIntervalMax), - rotateNum(config.rotateNum), - rotateSizeMB(config.rotateSizeMB), + rotateNum(config.rotateNum), + rotateSizeMB(config.rotateSizeMB), logFilePath(config.logFilePath), host(config.host), port(config.port), diff --git a/src/main/cpp/log_writer.cpp b/src/main/cpp/log_writer.cpp index f24b35be9..20bc2b6fc 100644 --- a/src/main/cpp/log_writer.cpp +++ b/src/main/cpp/log_writer.cpp @@ -16,15 +16,15 @@ bool isLittleEndian() { static bool IS_LITTLE_ENDIAN = isLittleEndian(); LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvmtiEnv *jvmti) : - fileName(fileName), - rotateNum(rotateNum), - rotateSize(rotateSizeMB * 1024 * 1024), - size(0), + fileName(fileName), + rotateNum(rotateNum), + rotateSize(rotateSizeMB * 1024 * 1024), + size(0), file(NULL), - output_(NULL), + output_(NULL), frameInfoFoo(NULL), jvmti_(jvmti) { - file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); - output_ = this->file; + file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + output_ = this->file; if (output_->fail()) { // The JVM will still continue to run though; could call abort() to terminate the JVM abnormally. logError("ERROR: Failed to open file %s for writing\n", fileName.c_str()); @@ -32,14 +32,14 @@ LogWriter::LogWriter(std::string &fileName, int rotateNum, int rotateSizeMB, jvm } LogWriter::LogWriter(ostream &output, int rotateNum, int rotateSizeMB, GetFrameInformation frameLookup, jvmtiEnv *jvmti) : - fileName(), - rotateNum(rotateNum), - rotateSize(rotateSizeMB * 1024 * 1024), - size(0), + fileName(), + rotateNum(rotateNum), + rotateSize(rotateSizeMB * 1024 * 1024), + size(0), file(NULL), - output_(&output), - frameInfoFoo(frameLookup), - jvmti_(jvmti) { + output_(&output), + frameInfoFoo(frameLookup), + jvmti_(jvmti) { // Old interface for backward compatibility and testing purposes } @@ -48,31 +48,31 @@ void LogWriter::writeValue(ostream & fout, const T &value) { if (IS_LITTLE_ENDIAN) { const char *data = reinterpret_cast(&value); for (int i = sizeof(value) - 1; i >= 0; i--) { - fout.put(data[i]); + fout.put(data[i]); } } else { - fout.write(reinterpret_cast(&value), sizeof(value)); + fout.write(reinterpret_cast(&value), sizeof(value)); } size += sizeof(value); } static jint bci2line(jint bci, jvmtiLineNumberEntry *table, jint entry_count) { - jint line_number = -101; - if ( entry_count == 0 ) { - return line_number; - } - line_number = -102; + jint line_number = -101; + if ( entry_count == 0 ) { + return line_number; + } + line_number = -102; // We're looking for a line whose 'start_location' is nearest AND >= BCI - // We assume the table is sorted by 'start_location' + // We assume the table is sorted by 'start_location' // Do a binary search to quickly approximate 'start_index" in table - int half = entry_count >> 1; + int half = entry_count >> 1; int start_index = 0; while ( half > 0 ) { jint start_location = table[start_index + half].start_location; if ( bci > start_location ) { start_index = start_index + half; } else if ( bci == start_location ) { - // gotcha + // gotcha return table[start_index + half].line_number; } half = half >> 1; @@ -80,13 +80,13 @@ static jint bci2line(jint bci, jvmtiLineNumberEntry *table, jint entry_count) { /* Now start the table search from approximated start_index */ for (int i = start_index ; i < entry_count ; i++ ) { - // start_location > BCI: means line starts after the BCI, we'll take the previous match + // start_location > BCI: means line starts after the BCI, we'll take the previous match if ( bci < table[i].start_location ) { break; } else if (bci == table[i].start_location) { - // gotcha - return table[i].line_number; + // gotcha + return table[i].line_number; } line_number = table[i].line_number; } @@ -120,7 +120,7 @@ void LogWriter::record(const JVMPI_CallTrace &trace, ThreadBucketPtr info) { } void LogWriter::record(const timespec &ts, const JVMPI_CallTrace &trace, ThreadBucketPtr info) { - ostream & fout = getOut(); + ostream & fout = getOut(); recordTraceStart(fout, trace.num_frames, (map::HashType)trace.env_id, ts, info); for (int i = 0; i < trace.num_frames; i++) { @@ -228,7 +228,7 @@ void LogWriter::writeWithSize(ostream & fout, const char *value) { void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *methodName) { - ostream & fout = getOut(); + ostream & fout = getOut(); fout.put(NEW_METHOD); size++; writeValue(fout, methodId); @@ -241,7 +241,7 @@ void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileNa void LogWriter::recordNewMethod(const map::HashType methodId, const char *fileName, const char *className, const char *genericClassName, const char *methodName, const char *methodSignature, const char *genericMethodSignature) { - ostream & fout = getOut(); + ostream & fout = getOut(); fout.put(NEW_METHOD_SIGNATURE); size++; writeValue(fout, methodId); @@ -313,46 +313,46 @@ bool LogWriter::lookupFrameInformation(const JVMPI_CallFrame &frame) { } ostream& LogWriter::getOut() { - // std::thread::id this_id = std::this_thread::get_id(); - if (!fileName.empty() && size >= rotateSize) { - // rotate - file->close(); - delete file; - file = NULL; - size = 0; - // std::cout <<" threadId: " << this_id << " rotating file start >>> \n"; - for (int i = rotateNum; i > 0; --i) { - // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 - char buff[1024]; - if (i > 1) { - snprintf(buff, sizeof(buff), "%s.%d", fileName.c_str(), i - 1); - } else { - snprintf(buff, sizeof(buff), "%s", fileName.c_str()); - } - char buff_target[1024]; - snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); - - // std::cout <<" threadId: " << this_id << " remove target " << buff_target << " \n"; - std::remove(buff_target); - std::rename(buff, buff_target); - // std::cout <<" threadId: " << this_id << " rename from " << buff << " to " << buff_target << " \n"; - } - // std::cout <<" threadId: " << "rotating file end <<< \n"; - // recreate log - file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); - output_ = file; - return *output_; - } else { - // std::cout <<" threadId: " << "rotateSize: " << rotateSize << - // ", rotateNum: " << rotateNum << " current size: " << size << "\n"; - return *output_; - } + // std::thread::id this_id = std::this_thread::get_id(); + if (!fileName.empty() && size >= rotateSize) { + // rotate + file->close(); + delete file; + file = NULL; + size = 0; + // std::cout <<" threadId: " << this_id << " rotating file start >>> \n"; + for (int i = rotateNum; i > 0; --i) { + // rename files: delete logN, rename logN-1 to logN; ...; delete log1, log to log1 + char buff[1024]; + if (i > 1) { + snprintf(buff, sizeof(buff), "%s.%d", fileName.c_str(), i - 1); + } else { + snprintf(buff, sizeof(buff), "%s", fileName.c_str()); + } + char buff_target[1024]; + snprintf(buff_target, sizeof(buff_target), "%s.%d", fileName.c_str(), i); + + // std::cout <<" threadId: " << this_id << " remove target " << buff_target << " \n"; + std::remove(buff_target); + std::rename(buff, buff_target); + // std::cout <<" threadId: " << this_id << " rename from " << buff << " to " << buff_target << " \n"; + } + // std::cout <<" threadId: " << "rotating file end <<< \n"; + // recreate log + file = new std::ofstream(fileName, std::ofstream::out | std::ofstream::binary); + output_ = file; + return *output_; + } else { + // std::cout <<" threadId: " << "rotateSize: " << rotateSize << + // ", rotateNum: " << rotateNum << " current size: " << size << "\n"; + return *output_; + } } LogWriter::~LogWriter() { - if (file != NULL) { - file->close(); - delete file; - file = NULL; - } + if (file != NULL) { + file->close(); + delete file; + file = NULL; + } } diff --git a/src/test/cpp/test_log_writer.cpp b/src/test/cpp/test_log_writer.cpp index 9200d2b67..fc25e8695 100644 --- a/src/test/cpp/test_log_writer.cpp +++ b/src/test/cpp/test_log_writer.cpp @@ -194,16 +194,15 @@ TEST(DumpTestFile) { } TEST(FileRotation) { - givenStackTrace(); - ofstream output("dump-rotate.hpl", ofstream::out | ofstream::binary); - LogWriter logWriter(output, 3, 1, &dumpStubFrameInformation, NULL); - - // write 1M times, which must exceeds 1M log rotation size - for (int i = 0; i < 1024*1024; i++) { - logWriter.record(trace); - } - // Now verify the rotated file exists, and it's readable by the log reader - std::ifstream infile("dump-rotate.hpl.1"); - CHECK_EQUAL(0, infile.good()); - + givenStackTrace(); + ofstream output("dump-rotate.hpl", ofstream::out | ofstream::binary); + LogWriter logWriter(output, 3, 1, &dumpStubFrameInformation, NULL); + + // write 1M times, which must exceeds 1M log rotation size + for (int i = 0; i < 1024*1024; i++) { + logWriter.record(trace); + } + // Now verify the rotated file exists, and it's readable by the log reader + std::ifstream infile("dump-rotate.hpl.1"); + CHECK_EQUAL(0, infile.good()); }