Index: code/trunk/src/libraries/util/OutputHandler.cc
===================================================================
--- code/trunk/src/libraries/util/OutputHandler.cc	(revision 7401)
+++ code/trunk/src/libraries/util/OutputHandler.cc	(revision 8729)
@@ -69,5 +69,5 @@
         */
         LogFileWriter()
-            : OutputListener(OutputHandler::logFileOutputListenerName_s)
+            : OutputListener("LogFile")
         {
             // Get path for a temporary file
@@ -85,9 +85,10 @@
             timeinfo = localtime(&rawtime);
 
-            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
-            this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
-            this->logFile_.flush();
-
-            this->outputStream_ = &this->logFile_;
+            this->openFile();
+            if (this->logFile_.is_open())
+            {
+                this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
+                this->logFile_.flush();
+            }
         }
 
@@ -95,6 +96,9 @@
         ~LogFileWriter()
         {
-            this->logFile_ << "Closed log" << std::endl;
-            this->logFile_.close();
+            if (this->logFile_.is_open())
+            {
+                this->logFile_ << "Closed log" << std::endl;
+                this->logFile_.close();
+            }
         }
 
@@ -102,16 +106,36 @@
         void setLogPath(const std::string& path)
         {
-            this->logFile_.close();
-            // Read old file into a buffer
-            std::ifstream old(this->logFilename_.c_str());
+            if (this->logFile_.is_open())
+                this->logFile_.close();
+
+            // Open the new file
             this->logFilename_ = path + logFileBaseName_g;
-            // Open the new file and feed it the content of the old one
+            this->openFile();
+        }
+
+        //! Erases the log file
+        void clearFile()
+        {
+            if (this->logFile_.is_open())
+            {
+                this->logFile_.close();
+                this->openFile();
+            }
+        }
+
+    private:
+        void openFile()
+        {
             this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
-            this->logFile_ << old.rdbuf();
-            this->logFile_.flush();
-            old.close();
-        }
-
-    private:
+
+            if (this->logFile_.is_open())
+                this->outputStream_ = &this->logFile_;
+            else
+            {
+                COUT(2) << "Warning: Failed to open log file. File logging disabled." << std::endl;
+                this->outputStream_ = NULL;
+            }
+        }
+
         std::ofstream logFile_;     //!< File handle for the log file
         std::string   logFilename_; //!< Filename of the log file
@@ -133,5 +157,5 @@
         //! Only assigns the output stream with std::cout
         ConsoleWriter()
-            : OutputListener("consoleLog")
+            : OutputListener("Console")
         {
             this->outputStream_ = &std::cout;
@@ -147,7 +171,8 @@
         OutputListener that writes all the output piece by piece to an array
         associated with the corresponding output level.
+        Used as buffer until all output devices have been initialised.
     @note
-        Only output below or equal to the current soft debug level is written
-        to minimise huge arrays for the normal run.
+        At some point, OutputHandler::disableMemoryLog() has to be called in
+        order to avoid large memory footprints of this class.
     */
     class MemoryLogWriter : public OutputListener
@@ -156,8 +181,4 @@
         friend class OutputHandler;
 
-        /**
-        @brief
-            Sets the right soft debug level and registers itself
-        */
         MemoryLogWriter()
             : OutputListener("memoryLog")
@@ -166,5 +187,5 @@
         }
 
-        //! Pushed the just written output to the internal array
+        //! Push the just written output to the internal array
         void outputChanged(int level)
         {
@@ -180,6 +201,6 @@
 
     private:
-        std::ostringstream                        buffer_; //!< Stream object used to process the output
-        std::vector<std::pair<int, std::string> > output_; //!< Vector containing ALL output
+        std::ostringstream          buffer_; //!< Stream object used to process the output
+        OutputHandler::OutputVector output_; //!< Vector containing ALL output
     };
 
@@ -188,6 +209,5 @@
     ///// OutputHandler /////
     /////////////////////////
-    const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
-          int         OutputHandler::softDebugLevel_s = hardDebugLevel;
+    int OutputHandler::softDebugLevel_s = hardDebugLevel;
 
     //! Creates the LogFileWriter and the MemoryLogWriter
@@ -195,25 +215,28 @@
         : outputLevel_(OutputLevel::Verbose)
     {
+        // Note: These levels only concern startup before orxonox.ini is read.
 #ifdef ORXONOX_RELEASE
-        const OutputLevel::Value defaultLevelConsole = OutputLevel::Error;
-        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Info;
+        const OutputLevel::Value initialLevelConsole = OutputLevel::Error;
 #else
-        const OutputLevel::Value defaultLevelConsole = OutputLevel::Info;
-        const OutputLevel::Value defaultLevelLogFile = OutputLevel::Debug;
+        const OutputLevel::Value initialLevelConsole = OutputLevel::Info;
 #endif
+        // Use high log level because we rewrite the log file anyway with the
+        // correct level. But if Orxonox were to crash before that, we might be
+        // grateful to have a high debug level, esp. for releases.
+        const OutputLevel::Value intialLevelLogFile = OutputLevel::Debug;
 
         this->logFile_ = new LogFileWriter();
         // Use default level until we get the configValue from the Core
-        this->logFile_->softDebugLevel_ = defaultLevelLogFile;
+        this->logFile_->softDebugLevel_ = intialLevelLogFile;
         this->registerOutputListener(this->logFile_);
 
         this->consoleWriter_ = new ConsoleWriter();
-        this->consoleWriter_->softDebugLevel_ = defaultLevelConsole;
+        this->consoleWriter_->softDebugLevel_ = initialLevelConsole;
         this->registerOutputListener(this->consoleWriter_);
 
-        this->output_ = new MemoryLogWriter();
-        // We capture as much input as the listener with the highest level
-        this->output_->softDebugLevel_ = getSoftDebugLevel();
-        this->registerOutputListener(this->output_);
+        this->memoryBuffer_ = new MemoryLogWriter();
+        // Write everything, e.g. use hardDebugLevel
+        this->memoryBuffer_->softDebugLevel_ = hardDebugLevel;
+        this->registerOutputListener(this->memoryBuffer_);
     }
 
@@ -223,5 +246,5 @@
         delete this->logFile_;
         delete this->consoleWriter_;
-        delete this->output_;
+        delete this->memoryBuffer_; // Might already be NULL
     }
 
@@ -234,5 +257,5 @@
     void OutputHandler::registerOutputListener(OutputListener* listener)
     {
-        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
             if ((*it)->name_ == listener->name_)
@@ -243,11 +266,18 @@
         }
         this->listeners_.push_back(listener);
-        // Update global soft debug level
-        this->setSoftDebugLevel(listener->getOutputListenerName(), listener->getSoftDebugLevel());
+        this->updateGlobalDebugLevel();
     }
 
     void OutputHandler::unregisterOutputListener(OutputListener* listener)
     {
-        this->listeners_.remove(listener);
+        for (std::vector<OutputListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((*it)->name_ == listener->name_)
+            {
+                this->listeners_.erase(it);
+                break;
+            }
+        }
+        this->updateGlobalDebugLevel();
     }
 
@@ -255,4 +285,20 @@
     {
         this->logFile_->setLogPath(path);
+        this->rewriteLogFile();
+    }
+
+    void OutputHandler::rewriteLogFile()
+    {
+        logFile_->clearFile();
+
+        if (logFile_->outputStream_ == NULL)
+            return;
+
+        for (OutputVector::const_iterator it = this->getOutput().begin(); it != this->getOutput().end(); ++it)
+        {
+            if (it->first <= logFile_->softDebugLevel_)
+                (*logFile_->outputStream_) << it->second;
+        }
+        logFile_->outputStream_->flush();
     }
 
@@ -267,17 +313,19 @@
     }
 
-    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
-    {
-        return this->output_->output_.begin();
-    }
-
-    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
-    {
-        return this->output_->output_.end();
+    void OutputHandler::disableMemoryLog()
+    {
+        this->unregisterOutputListener(this->memoryBuffer_);
+        // Only clear the buffer so we can still reference the vector
+        this->memoryBuffer_->output_.clear();
+    }
+
+    const OutputHandler::OutputVector& OutputHandler::getOutput() const
+    {
+        return this->memoryBuffer_->output_;
     }
 
     int OutputHandler::getSoftDebugLevel(const std::string& name) const
     {
-        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
             if ((*it)->name_ == name)
@@ -289,13 +337,19 @@
     void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
     {
-        int globalSoftDebugLevel = -1;
-        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
         {
             if ((*it)->name_ == name)
                 (*it)->softDebugLevel_ = level;
-            if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
-                globalSoftDebugLevel = (*it)->softDebugLevel_;
-        }
-        // Update global soft debug level
+        }
+        this->updateGlobalDebugLevel();
+    }
+
+    void OutputHandler::updateGlobalDebugLevel()
+    {
+        int globalSoftDebugLevel = -1;
+        std::vector<OutputListener*>::const_iterator it = this->listeners_.begin();
+        for (; it != this->listeners_.end(); ++it)
+            globalSoftDebugLevel = std::max(globalSoftDebugLevel, (*it)->softDebugLevel_);
+
         OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
     }
