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)
82 string msg("\nTraces go on at: ");
85 r = write(a_stream, msg.c_str(), msg.length());
88 if(a_observed == true) {
89 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
90 observer(ii)->handleClose(a_stream);
97 unlink(a_outputFile.c_str());
98 unlink(a_outputOldFile.c_str());
102 a_outputFile = fileName;
103 a_outputOldFile = a_outputFile;
104 a_outputOldFile += ".old";
106 if(maxSize >= (256 * 1024))
109 char date [anna::functions::DateTimeSizeString + 7];
110 anna_strcpy(date, "- [");
111 anna_strcat(anna_strcat(date, getDate()), "]\n");
112 int stream = prepareOutput(date);
114 if(stream != ErrorStream) {
115 const char* aux = "\n--------------------------------------------------------------\n";
116 const char* aux2 = "- Current trace level: ";
117 r = write(stream, aux, anna_strlen(aux));
118 r = write(stream, date, anna_strlen(date));
119 r = write(stream, aux2, anna_strlen(aux2));
120 aux2 = Logger::asString(Logger::getLevel());
121 r = write(stream, aux2, anna_strlen(aux2));
122 string filesize = functions::asString("\n- Max file size : %d Kb", a_maxSize >> 10);
123 aux2 = filesize.c_str();
124 r = write(stream, aux2, anna_strlen(aux2));
125 r = write(stream, aux, anna_strlen(aux));
129 void TraceWriter::attach(TraceWriterObserver* observer)
131 if(observer != NULL) {
133 a_observers.push_back(observer);
136 observer->handleOpen(a_stream);
140 void TraceWriter::printResume()
142 cout << "Traces file ..................................: " << a_outputFile << endl;
143 cout << "Backup copy .................................: " << a_outputOldFile << endl;
144 cout << "Files size (Kbytes) ..........................: " << (a_maxSize >> 10) << endl;
145 cout << "Traces level .................................: " << Logger::asString(Logger::getLevel()) << endl << endl;
148 void TraceWriter::do_write(int level, const char* text, ...)
154 GuardNoLog guard(a_mutex);
155 DataBlock& dataBlock(Logger::Writer::getDataBlock());
156 data = dataBlock.getData();
157 size = dataBlock.getMaxSize();
160 dataBlock.allocate(size = 1024);
161 data = dataBlock.getData();
166 nbytes = vsnprintf(const_cast <char*>(data), size, text, ap);
169 dataBlock.allocate(nbytes + 1);
170 data = dataBlock.getData();
171 size = dataBlock.getMaxSize();
179 const char* aux = Logger::asString(Logger::Level(level));
180 char date [anna::functions::DateTimeSizeString + 5];
183 anna_strcat(anna_strcat(date, getDate()), "] ");
184 a_stream = prepareOutput(date);
186 if(a_stream == ErrorStream) {
187 cerr << Logger::asString(Logger::Level(level)) << " | " << date << " | " << data << endl << endl;
193 if(write(a_stream, date, anna_strlen(date)) > 0)
194 if(write(a_stream, aux, anna_strlen(aux)) > 0)
195 if(write(a_stream, " | ", 3) > 0)
196 if(write(a_stream, data, nbytes) > 0)
197 ok = (write(a_stream, "\n\n", 2) > 0);
199 if(ok == false && errno != EINTR)
200 perror("Cannot save traces");
203 const char* TraceWriter::getDate()
205 const Microsecond msnow = functions::hardwareClock();
207 if(a_lastTime == 0 || (msnow - a_lastTime) > 1000000L) {
209 char date [functions::DateTimeSizeString];
210 a_date = functions::asDateTime(functions::second(), date);
213 return a_date.c_str();
216 int TraceWriter::prepareOutput(const char* date)
218 int result = a_stream;
220 if(result == ErrorStream)
226 anna_signal_shield(r, stat(a_outputFile.c_str(), &data));
228 if(r == -1 || data.st_size > a_maxSize) {
229 if(a_observed == true) {
230 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
231 observer(ii)->handleClose(a_stream);
234 anna_signal_shield(r, close(result));
235 rename(a_outputFile.c_str(), a_outputOldFile.c_str());
242 result, open(a_outputFile.c_str(), O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
246 cerr << "Cannot open the file '" << a_outputFile << "': " << strerror(errno) << endl;
247 Logger::setLevel(Logger::Error);
248 result = ErrorStream;
251 anna_signal_shield(r, fcntl(result, F_GETFL));
254 const int opts = r | O_NONBLOCK;
255 anna_signal_shield(r, fcntl(result, F_SETFL, opts));
259 if(a_observed == true) {
260 for(observer_iterator ii = observer_begin(), maxii = observer_end(); ii != maxii; ii ++)
261 observer(ii)->handleOpen(result);