summaryrefslogtreecommitdiff
path: root/src/mongo/logger/console.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/logger/console.cpp')
-rw-r--r--src/mongo/logger/console.cpp308
1 files changed, 151 insertions, 157 deletions
diff --git a/src/mongo/logger/console.cpp b/src/mongo/logger/console.cpp
index 19ac32793e7..90945ad7f21 100644
--- a/src/mongo/logger/console.cpp
+++ b/src/mongo/logger/console.cpp
@@ -38,169 +38,163 @@
namespace mongo {
namespace {
- /*
- * Theory of operation:
- *
- * At process start, the loader initializes "consoleMutex" to NULL. At some point during static
- * initialization, the static initialization process, running in the one and only extant thread,
- * allocates a new stdx::mutex on the heap and assigns consoleMutex to point to it. While
- * consoleMutex is still NULL, we know that there is only one thread extant, so it is safe to
- * skip locking the consoleMutex in the Console constructor. Once the mutex is initialized,
- * users of Console can start acquiring it.
- */
-
- stdx::mutex *consoleMutex = new stdx::mutex;
+/*
+ * Theory of operation:
+ *
+ * At process start, the loader initializes "consoleMutex" to NULL. At some point during static
+ * initialization, the static initialization process, running in the one and only extant thread,
+ * allocates a new stdx::mutex on the heap and assigns consoleMutex to point to it. While
+ * consoleMutex is still NULL, we know that there is only one thread extant, so it is safe to
+ * skip locking the consoleMutex in the Console constructor. Once the mutex is initialized,
+ * users of Console can start acquiring it.
+ */
+
+stdx::mutex* consoleMutex = new stdx::mutex;
#if defined(_WIN32)
- /**
- * Very basic implementation of a stream buffer backed by
- * a fixed sized internal buffer that flushes
- * to the console using WriteConsoleW().
- *
- * Implementation notes:
- * WriteConsoleW() vs std::wcout
- * std::wcout produces garbage output for messages containing 2-byte sequences
- * under all the terminal environments tested (Command Prompt, Power Shell, Cygwin).
- * 3-byte sequences will cause std::wcout to go into a bad state (failbit=true).
- * Also tried calling _setmode( _fileno(stdout), ...) with various modes (_O_U16TEXT,
- * ...), all of which produces garbage results on the console.
- */
-
- class ConsoleStreamBuffer : public std::streambuf {
- public:
-
- explicit ConsoleStreamBuffer(HANDLE consoleHandle) : _consoleHandle(consoleHandle) {
- // leave room at end of buffer for overflow character
- setp(&(_buffer[0]), &(_buffer[_bufferSize-1]));
- }
+/**
+ * Very basic implementation of a stream buffer backed by
+ * a fixed sized internal buffer that flushes
+ * to the console using WriteConsoleW().
+ *
+ * Implementation notes:
+ * WriteConsoleW() vs std::wcout
+ * std::wcout produces garbage output for messages containing 2-byte sequences
+ * under all the terminal environments tested (Command Prompt, Power Shell, Cygwin).
+ * 3-byte sequences will cause std::wcout to go into a bad state (failbit=true).
+ * Also tried calling _setmode( _fileno(stdout), ...) with various modes (_O_U16TEXT,
+ * ...), all of which produces garbage results on the console.
+ */
- int_type overflow(int_type ch) {
- if (ch == traits_type::eof()) {
- return ch;
- }
+class ConsoleStreamBuffer : public std::streambuf {
+public:
+ explicit ConsoleStreamBuffer(HANDLE consoleHandle) : _consoleHandle(consoleHandle) {
+ // leave room at end of buffer for overflow character
+ setp(&(_buffer[0]), &(_buffer[_bufferSize - 1]));
+ }
- // push to end of buffer
- *(pptr()) = ch;
- pbump(1);
-
- // If the overflow byte is part of a UTF-8 multi-byte sequence,
- // locate the beginning of the byte sequence and determine if
- // the byte sequence represents a complete unicode code point.
- // If the sequence is complete, proceed to flush the buffer.
- // If the sequence is incomplete, flush the buffer up to but
- // not including incomplete code point before re-inserting the
- // bytes back into the internal buffer.
-
- if (ch & 0x80) {
- // length of unicode byte sequence can be at most 4 in length. See RFC 3629
- int length = 0;
-
- // do not look back beyond 4 characters (maximum length for UTF-8 sequences)
- // p will point to first byte of unicode code point upon exit from loop
- char* sequenceBegin = pptr();
- for (int i = 0; i < 4; i++) {
- length++;
- sequenceBegin--;
- // check for beginning of code point
- if (*sequenceBegin & 0x40) {
- break;
- }
- // check for invalid byte. all bytes in multi-byte sequence
- // should have left most bit set
- if (!(*sequenceBegin & 0x80)) {
- break;
- }
- }
+ int_type overflow(int_type ch) {
+ if (ch == traits_type::eof()) {
+ return ch;
+ }
- // get expected length of code point
- // cast to unsigned type to avoid sign extension
- int expectedLength = _bitsToSequenceLength[uint8_t(*sequenceBegin) >> 4];
-
- // if beginning of sequence was not found, expectedLength will be zero and
- // we will consider the multi-byte sequence to be garbage and flush the
- // entire buffer
-
- // if code point is incomplete, rewind and flush buffer before
- // refilling with incomplete byte sequence
- if (length < expectedLength)
- {
- // rewind internal buffer to end before unfinished byte sequence
- pbump(-length);
-
- // store result. should eventually return
- // original overflow character on success
- int_type result = flushToConsole() ? ch : traits_type::eof();
-
- // after flushing pptr() will point to beginning of buffer
- // copy bytes starting from p to beginning of internal buffer
- for (int i = 0; i < length; i++) {
- *(pptr()) = *sequenceBegin;
- pbump(1);
- sequenceBegin++;
- }
-
- return result;
+ // push to end of buffer
+ *(pptr()) = ch;
+ pbump(1);
+
+ // If the overflow byte is part of a UTF-8 multi-byte sequence,
+ // locate the beginning of the byte sequence and determine if
+ // the byte sequence represents a complete unicode code point.
+ // If the sequence is complete, proceed to flush the buffer.
+ // If the sequence is incomplete, flush the buffer up to but
+ // not including incomplete code point before re-inserting the
+ // bytes back into the internal buffer.
+
+ if (ch & 0x80) {
+ // length of unicode byte sequence can be at most 4 in length. See RFC 3629
+ int length = 0;
+
+ // do not look back beyond 4 characters (maximum length for UTF-8 sequences)
+ // p will point to first byte of unicode code point upon exit from loop
+ char* sequenceBegin = pptr();
+ for (int i = 0; i < 4; i++) {
+ length++;
+ sequenceBegin--;
+ // check for beginning of code point
+ if (*sequenceBegin & 0x40) {
+ break;
+ }
+ // check for invalid byte. all bytes in multi-byte sequence
+ // should have left most bit set
+ if (!(*sequenceBegin & 0x80)) {
+ break;
}
}
- return flushToConsole() ? ch : traits_type::eof();
- }
+ // get expected length of code point
+ // cast to unsigned type to avoid sign extension
+ int expectedLength = _bitsToSequenceLength[uint8_t(*sequenceBegin) >> 4];
+
+ // if beginning of sequence was not found, expectedLength will be zero and
+ // we will consider the multi-byte sequence to be garbage and flush the
+ // entire buffer
+
+ // if code point is incomplete, rewind and flush buffer before
+ // refilling with incomplete byte sequence
+ if (length < expectedLength) {
+ // rewind internal buffer to end before unfinished byte sequence
+ pbump(-length);
+
+ // store result. should eventually return
+ // original overflow character on success
+ int_type result = flushToConsole() ? ch : traits_type::eof();
+
+ // after flushing pptr() will point to beginning of buffer
+ // copy bytes starting from p to beginning of internal buffer
+ for (int i = 0; i < length; i++) {
+ *(pptr()) = *sequenceBegin;
+ pbump(1);
+ sequenceBegin++;
+ }
- int sync() {
- return flushToConsole() ? 0 : -1;
+ return result;
+ }
}
- private:
-
- // keep this value reasonable. this class is used primarily
- // to buffer log messages
- static const size_t _bufferSize = 1024U;
-
- // mapping of leftmost 4 bits of first byte of code point
- // to number of expected bytes in complete code point
- // 110x -> 2
- // 1110 -> 3
- // 1111 -> 4
- static const int _bitsToSequenceLength[];
-
- // In the event that WriteConsoleW fails, return false
- // to allow stream to update error state flags (most likely badbit)
-
- bool flushToConsole() {
- std::ptrdiff_t n = pptr() - pbase();
- pbump(-n);
-
- // convert multi-byte buffer to wide characters and output using WriteConsoleW
+ return flushToConsole() ? ch : traits_type::eof();
+ }
- wchar_t bufferWide[_bufferSize];
- int length = MultiByteToWideChar(CP_UTF8, 0, _buffer, n, bufferWide, _bufferSize);
- const wchar_t* unwrittenBegin = bufferWide;
- int unwrittenCount = length; // m holds number of unwritten wide characters in buffer
+ int sync() {
+ return flushToConsole() ? 0 : -1;
+ }
- while (unwrittenCount > 0) {
- DWORD written;
- BOOL success = WriteConsoleW(_consoleHandle, unwrittenBegin, unwrittenCount,
- &written, NULL);
- if (!success) {
- return false;
- }
- unwrittenCount -= written;
- unwrittenBegin += written;
+private:
+ // keep this value reasonable. this class is used primarily
+ // to buffer log messages
+ static const size_t _bufferSize = 1024U;
+
+ // mapping of leftmost 4 bits of first byte of code point
+ // to number of expected bytes in complete code point
+ // 110x -> 2
+ // 1110 -> 3
+ // 1111 -> 4
+ static const int _bitsToSequenceLength[];
+
+ // In the event that WriteConsoleW fails, return false
+ // to allow stream to update error state flags (most likely badbit)
+
+ bool flushToConsole() {
+ std::ptrdiff_t n = pptr() - pbase();
+ pbump(-n);
+
+ // convert multi-byte buffer to wide characters and output using WriteConsoleW
+
+ wchar_t bufferWide[_bufferSize];
+ int length = MultiByteToWideChar(CP_UTF8, 0, _buffer, n, bufferWide, _bufferSize);
+ const wchar_t* unwrittenBegin = bufferWide;
+ int unwrittenCount = length; // m holds number of unwritten wide characters in buffer
+
+ while (unwrittenCount > 0) {
+ DWORD written;
+ BOOL success =
+ WriteConsoleW(_consoleHandle, unwrittenBegin, unwrittenCount, &written, NULL);
+ if (!success) {
+ return false;
}
- return true;
+ unwrittenCount -= written;
+ unwrittenBegin += written;
}
+ return true;
+ }
- HANDLE _consoleHandle;
- char _buffer[_bufferSize];
- };
+ HANDLE _consoleHandle;
+ char _buffer[_bufferSize];
+};
// 0x0 - 0xb - invalid start of multi-byte sequence`
const int ConsoleStreamBuffer::_bitsToSequenceLength[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 2, 2, 3, 4 };
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 4};
// Create a output stream to redirect console writes
// to WriteConsoleW() if there is a real console available (FILE_TYPE_CHAR)
@@ -229,26 +223,26 @@ std::ostream* getWindowsOutputStream() {
}
std::ostream* windowsOutputStream = getWindowsOutputStream();
-#endif // defined(_WIN32)
+#endif // defined(_WIN32)
} // namespace
- Console::Console() : _consoleLock() {
- if (consoleMutex) {
- stdx::unique_lock<stdx::mutex> lk(*consoleMutex);
- lk.swap(_consoleLock);
- }
+Console::Console() : _consoleLock() {
+ if (consoleMutex) {
+ stdx::unique_lock<stdx::mutex> lk(*consoleMutex);
+ lk.swap(_consoleLock);
}
+}
- std::ostream& Console::out() {
+std::ostream& Console::out() {
#if defined(_WIN32)
- // check value of ostream in case
- // static initializer has not been invoked
- if (windowsOutputStream) {
- return *windowsOutputStream;
- }
-#endif // defined(_WIN32)
- return std::cout;
+ // check value of ostream in case
+ // static initializer has not been invoked
+ if (windowsOutputStream) {
+ return *windowsOutputStream;
}
+#endif // defined(_WIN32)
+ return std::cout;
+}
} // namespace mongo