1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
18 #include <sys/types.h>
20 #include <anna/core/tracing/TraceWriter.hpp>
21 #include <anna/core/DataBlock.hpp>
22 #include <anna/core/functions.hpp>
23 #include <anna/core/util/Configuration.hpp>
24 #include <anna/core/tracing/TraceWriterObserver.hpp>
29 TraceWriter::TraceWriter() :
30 a_maxSize(DefaultMaxKBSize),
35 file = "/var/tmp/anna.process.";
36 file += functions::asString((int) getpid());
38 setup(file.c_str(), DefaultMaxKBSize, false);
41 TraceWriter::TraceWriter(const char* fileName, const int maxSize) :
42 a_maxSize(DefaultMaxKBSize),
46 setup(fileName, maxSize, false);
49 void TraceWriter::setup(const char* fileName, const Configuration& configuration)
51 int maxSize = a_maxSize;
56 maxSize = (configuration.getIntegerValue("Trace", "MaxFileSize") << 10);
61 Logger::setLevel(Logger::asLevel(configuration.getValue("Trace", "Level")));
62 } catch(Exception& ex) {
67 clean = (configuration.getIntegerValue("Trace", "Clean") == 1);
70 } catch(RuntimeException&) {
73 setup(fileName, maxSize, clean);
76 void TraceWriter::setup(const char* fileName, const int maxSize, const bool clean)
80 string msg("\nTraces go on at: ");
83 write(a_stream, msg.c_str(), msg.length());
86 if(a_observed == true) {
87 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
88 observer(ii)->handleClose(a_stream);
95 unlink(a_outputFile.c_str());
96 unlink(a_outputOldFile.c_str());
100 a_outputFile = fileName;
101 a_outputOldFile = a_outputFile;
102 a_outputOldFile += ".old";
104 if(maxSize >= (256 * 1024))
107 const char* aux = Logger::asString(Logger::getLevel());
108 char date [anna::functions::DateTimeSizeString + 7];
109 anna_strcpy(date, "- [");
110 anna_strcat(anna_strcat(date, getDate()), "]\n");
111 int stream = prepareOutput(date);
113 if(stream != ErrorStream) {
114 const char* aux = "\n--------------------------------------------------------------\n";
115 const char* aux2 = "- Current trace level: ";
116 write(stream, aux, anna_strlen(aux));
117 write(stream, date, anna_strlen(date));
118 write(stream, aux2, anna_strlen(aux2));
119 aux2 = Logger::asString(Logger::getLevel());
120 write(stream, aux2, anna_strlen(aux2));
121 string filesize = functions::asString("\n- Max file size : %d Kb", a_maxSize >> 10);
122 aux2 = filesize.c_str();
123 write(stream, aux2, anna_strlen(aux2));
124 write(stream, aux, anna_strlen(aux));
128 void TraceWriter::attach(TraceWriterObserver* observer)
130 if(observer != NULL) {
132 a_observers.push_back(observer);
135 observer->handleOpen(a_stream);
139 void TraceWriter::printResume()
141 cout << "Traces file ..................................: " << a_outputFile << endl;
142 cout << "Backup copy .................................: " << a_outputOldFile << endl;
143 cout << "Files size (Kbytes) ..........................: " << (a_maxSize >> 10) << endl;
144 cout << "Traces level .................................: " << Logger::asString(Logger::getLevel()) << endl << endl;
147 void TraceWriter::do_write(int level, const char* text, ...)
153 GuardNoLog guard(a_mutex);
154 DataBlock& dataBlock(Logger::Writer::getDataBlock());
155 data = dataBlock.getData();
156 size = dataBlock.getMaxSize();
159 dataBlock.allocate(size = 1024);
160 data = dataBlock.getData();
165 nbytes = vsnprintf(const_cast <char*>(data), size, text, ap);
168 dataBlock.allocate(nbytes + 1);
169 data = dataBlock.getData();
170 size = dataBlock.getMaxSize();
178 const char* aux = Logger::asString(Logger::Level(level));
179 char date [anna::functions::DateTimeSizeString + 5];
182 anna_strcat(anna_strcat(date, getDate()), "] ");
183 a_stream = prepareOutput(date);
185 if(a_stream == ErrorStream) {
186 cerr << Logger::asString(Logger::Level(level)) << " | " << date << " | " << data << endl << endl;
192 if(write(a_stream, date, anna_strlen(date)) > 0)
193 if(write(a_stream, aux, anna_strlen(aux)) > 0)
194 if(write(a_stream, " | ", 3) > 0)
195 if(write(a_stream, data, nbytes) > 0)
196 ok = (write(a_stream, "\n\n", 2) > 0);
198 if(ok == false && errno != EINTR)
199 perror("Cannot save traces");
202 const char* TraceWriter::getDate()
204 const Microsecond msnow = functions::hardwareClock();
206 if(a_lastTime == 0 || (msnow - a_lastTime) > 1000000L) {
208 char date [functions::DateTimeSizeString];
209 a_date = functions::asDateTime(functions::second(), date);
212 return a_date.c_str();
215 int TraceWriter::prepareOutput(const char* date)
217 int result = a_stream;
219 if(result == ErrorStream)
225 anna_signal_shield(r, stat(a_outputFile.c_str(), &data));
227 if(r == -1 || data.st_size > a_maxSize) {
228 if(a_observed == true) {
229 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
230 observer(ii)->handleClose(a_stream);
233 anna_signal_shield(r, close(result));
234 rename(a_outputFile.c_str(), a_outputOldFile.c_str());
241 result, open(a_outputFile.c_str(), O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
245 cerr << "Cannot open the file '" << a_outputFile << "': " << strerror(errno) << endl;
246 Logger::setLevel(Logger::Error);
247 result = ErrorStream;
250 anna_signal_shield(r, fcntl(result, F_GETFL));
253 const int opts = r | O_NONBLOCK;
254 anna_signal_shield(r, fcntl(result, F_SETFL, opts));
258 if(a_observed == true) {
259 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
260 observer(ii)->handleOpen(result);