From b3a803ed132b5f1b7a21130c5466a8deb106d193 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 3 Feb 2013 19:21:12 +0100
Subject: Make logging thread-safe.

Change-Id: Ifab368474bd9e42e10f2cb0c29ff696c0aeaf3ea

diff --git a/QA/Checker/checker.cpp b/QA/Checker/checker.cpp
index 12237dc..1ec8892 100644
--- a/QA/Checker/checker.cpp
+++ b/QA/Checker/checker.cpp
@@ -19,6 +19,8 @@ int main(int argc, char* argv[]) {
 	bool verbose = false;
 	bool outputXML = false;
 
+	Swift::Log::setLogLevel(Swift::Log::error);
+
 	// Parse parameters
 	std::vector<std::string> testsToRun;
 	for (int i = 1; i < argc; ++i) {
@@ -30,7 +32,7 @@ int main(int argc, char* argv[]) {
 			outputXML = true;
 		}
 		else if (param == "--debug") {
-			Swift::logging = true;
+			Swift::Log::setLogLevel(Swift::Log::debug);
 		}
 		else {
 			testsToRun.push_back(param);
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 0ffef0c..edd2e3b 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -291,7 +291,7 @@ void ChatController::handleFileTransferStart(std::string id, std::string descrip
 }
 
 void ChatController::handleFileTransferAccept(std::string id, std::string filename) {
-	SWIFT_LOG(debug) "handleFileTransferAccept(" << id << ", " << filename << ")" << std::endl;
+	SWIFT_LOG(debug) << "handleFileTransferAccept(" << id << ", " << filename << ")" << std::endl;
 	if (ftControllers.find(id) != ftControllers.end()) {
 		ftControllers[id]->accept(filename);
 	} else {
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 4d10956..515c83f 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -153,7 +153,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
 	}
 
 	if (options.count("debug")) {
-		Swift::logging = true;
+		Log::setLogLevel(Swift::Log::debug);
 	}
 
 	tabs_ = options.count("no-tabs") && !splitter_ ? NULL : new QtChatTabs();
diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp
index 4132353..317798c 100644
--- a/Swiften/Base/Log.cpp
+++ b/Swiften/Base/Log.cpp
@@ -1,13 +1,43 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
 #include <Swiften/Base/Log.h>
 
+#include <cstdio>
+
+
 namespace Swift {
 
-bool logging = false;
+static Log::Severity logLevel = Log::warning;
+
+Log::Log() {
+}
+
+Log::~Log() {
+	// Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic)
+	fprintf(stderr, "%s", stream.str().c_str());
+	fflush(stderr);
+}
+
+std::ostringstream& Log::getStream(
+		Severity /*severity*/, 
+		const std::string& severityString, 
+		const std::string& file, 
+		int line,
+		const std::string& function) {
+	stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": ";
+	return stream;
+}
+
+Log::Severity Log::getLogLevel() {
+	return logLevel;
+}
+
+void Log::setLogLevel(Severity level) {
+	logLevel = level;
+}
 
 }
diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h
index 6d76dc6..f8d524b 100644
--- a/Swiften/Base/Log.h
+++ b/Swiften/Base/Log.h
@@ -1,26 +1,40 @@
 /*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
 #pragma once
 
-#include <iostream>
+#include <sstream>
 
 #include <Swiften/Base/API.h>
 
 namespace Swift {
-	extern SWIFTEN_API bool logging;
-	namespace LogDetail {
-		// Only here to be able to statically check the correctness of the severity levers
-		namespace Severity {
-			enum {
-				debug, info, warning, error
+	class SWIFTEN_API Log {
+		public:
+			enum Severity {
+				error, warning, info, debug
 			};
-		}
-	}
+
+			Log();
+			~Log();
+
+			std::ostringstream& getStream(
+					Severity severity, 
+					const std::string& severityString, 
+					const std::string& file, 
+					int line,
+					const std::string& function);
+
+			static Severity getLogLevel();
+			static void setLogLevel(Severity level);
+
+		private:
+			std::ostringstream stream;
+	};
 }
 
 #define SWIFT_LOG(severity) \
-	if (!Swift::logging) {} else (void) LogDetail::Severity::severity, std::cerr << "[" << #severity << "] " << __FILE__ << ":" << __LINE__ << " " << __FUNCTION__ << ": "
+	if (Log::severity > Log::getLogLevel()) ; \
+	else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__)
diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp
index 8b0af37..7b361ef 100644
--- a/Swiften/Examples/SendFile/ReceiveFile.cpp
+++ b/Swiften/Examples/SendFile/ReceiveFile.cpp
@@ -65,7 +65,7 @@ class FileReceiver {
 
 	private:
 		void handleConnected() {
-			Swift::logging = true;
+			Log::setLogLevel(Log::debug);
 			client->getFileTransferManager()->startListeningOnPort(9999);
 			client->getFileTransferManager()->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1));
 			
diff --git a/Swiften/Examples/SendFile/SendFile.cpp b/Swiften/Examples/SendFile/SendFile.cpp
index 657949b..39a8603 100644
--- a/Swiften/Examples/SendFile/SendFile.cpp
+++ b/Swiften/Examples/SendFile/SendFile.cpp
@@ -144,7 +144,7 @@ int main(int argc, char* argv[]) {
 
 	JID sender(argv[1]);
 	JID recipient(argv[3]);
-	Swift::logging = true;
+	Log::setLogLevel(Log::debug);
 	FileSender fileSender(sender, std::string(argv[2]), recipient, boost::filesystem::path(argv[4]));
 	fileSender.start();
 	{
-- 
cgit v0.10.2-6-g49f6