Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/output/LogWriter.cc @ 9550

Last change on this file since 9550 was 9550, checked in by landauf, 11 years ago

merged testing branch back to trunk. unbelievable it took me 13 months to finish this chore…

  • Property svn:eol-style set to native
File size: 5.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Reto Grieder
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of the LogWriter singleton.
32*/
33
34#include "LogWriter.h"
35
36#include <ctime>
37#include <cstdlib>
38
39#include "OutputManager.h"
40#include "MemoryWriter.h"
41#include "util/Convert.h"
42
43namespace orxonox
44{
45    static const int MAX_ARCHIVED_FILES = 9;
46
47    /**
48        @brief Constructor, initializes the desired output levels and the name and path of the log-file, and opens the log-file.
49
50        By default, LogWriter receives all output up to level::internal_info.
51        The log-file has a default name which usually doesn't change. The path
52        is initialized with a temporary directory, depending on the system,
53        and can be changed later.
54    */
55    LogWriter::LogWriter() : BaseWriter("Log")
56    {
57        this->setLevelMax(level::internal_info);
58
59        this->filename_ = "orxonox.log";
60
61        // get the path for a temporary file, depending on the system
62#ifdef ORXONOX_PLATFORM_WINDOWS
63        this->directory_ = getenv("TEMP");
64#else
65        this->directory_ = "/tmp";
66#endif
67
68        // send a message to the user so that he can find the file in the case of a crash.
69        OutputManager::getInstance().pushMessage(level::user_info, context::undefined(), "Opening log file " + this->getPath());
70
71        this->openFile();
72    }
73
74    /**
75        @brief Destructor, closes the log-file.
76    */
77    LogWriter::~LogWriter()
78    {
79        this->closeFile();
80    }
81
82    /**
83        @brief Opens the log-file in order to write output to it.
84    */
85    void LogWriter::openFile()
86    {
87        // archive the old log file
88        this->archive();
89
90        // open the file
91        this->file_.open(this->getPath().c_str(), std::fstream::out);
92
93        // check if it worked and print some output
94        if (this->file_.is_open())
95            this->printLine("Log file opened", level::none);
96        else
97            OutputManager::getInstance().pushMessage(level::user_warning, context::undefined(), "Failed to open log file. File logging disabled.");
98    }
99
100    /**
101        @brief Closes the log-file.
102    */
103    void LogWriter::closeFile()
104    {
105        if (this->file_.is_open())
106        {
107            this->printLine("Log file closed", level::none);
108            this->file_.close();
109        }
110    }
111
112    /**
113     * @brief Archives old copies of the log file by adding increasing numbers to the filename.
114     */
115    void LogWriter::archive(int index)
116    {
117        std::string oldPath = this->getArchivedPath(index);
118
119        // see if the file already exists, otherwise return
120        std::ifstream stream(oldPath.c_str());
121        bool exists = stream.is_open();
122        stream.close();
123
124        if (!exists)
125            return;
126
127        if (index < MAX_ARCHIVED_FILES)
128        {
129            // increment the index and archive the file with the next higher index
130            this->archive(++index);
131
132            // create the new path based on the incremented index
133            std::string newPath = this->getArchivedPath(index);
134
135            // move the file
136            std::rename(oldPath.c_str(), newPath.c_str());
137        }
138        else
139        {
140            // delete the file
141            std::remove(oldPath.c_str());
142        }
143    }
144   
145    /**
146     * @brief Returns the path for archived copies of the logfile (based on the archive index)
147     */
148    std::string LogWriter::getArchivedPath(int index) const
149    {
150        std::string path = this->getPath();
151        if (index > 0)
152            path += '.' + multi_cast<std::string>(index);
153        return path;
154    }
155
156    /**
157        @brief Changes the path of the log-file. Re-writes the log-file by using MemoryWriter.
158    */
159    void LogWriter::setLogDirectory(const std::string& directory)
160    {
161        // notify about the change of the log-file (because the old file will no longer be updated)
162        OutputManager::getInstance().pushMessage(level::internal_info, context::undefined(), "Migrating log file from " + this->directory_ + "\nto " + directory);
163
164        // close the old file, update the path and open the new file
165        this->closeFile();
166        this->directory_ = directory;
167        this->openFile();
168
169        // request old output from MemoryWriter
170        if (OutputManager::getInstance().getMemoryWriter())
171            OutputManager::getInstance().getMemoryWriter()->resendOutput(this);
172    }
173
174    /**
175        @brief Inherited function from BaseWriter, writers output together with a timestamp to the log-file.
176    */
177    void LogWriter::printLine(const std::string& line, OutputLevel)
178    {
179        if (!this->file_.is_open())
180            return;
181
182        // get the current time
183        time_t rawtime;
184        struct tm* timeinfo;
185        time(&rawtime);
186        timeinfo = localtime(&rawtime);
187
188        // print timestamp and output line to the log file
189        this->file_ << (timeinfo->tm_hour < 10 ? "0" : "") << timeinfo->tm_hour << ':' <<
190                       (timeinfo->tm_min  < 10 ? "0" : "") << timeinfo->tm_min  << ':' <<
191                       (timeinfo->tm_sec  < 10 ? "0" : "") << timeinfo->tm_sec  << ' ' << line << std::endl;
192    }
193}
Note: See TracBrowser for help on using the repository browser.