1 /* Copyright (C) 2014 InfiniDB, Inc.
2    Copyright (C) 2016 MariaDB Corporation
3 
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License
6    as published by the Free Software Foundation; version 2 of
7    the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17    MA 02110-1301, USA. */
18 
19 /*****************************************************************************
20  * $Id: tracer.cpp 1823 2013-01-21 14:13:09Z rdempsey $
21  *
22  ****************************************************************************/
23 
24 #include <iostream>
25 #include <fstream>
26 #include <algorithm>
27 
28 #ifdef _MSC_VER
29 #include <process.h>
30 #include <ctime>
31 #endif
32 
33 #include <unistd.h>
34 
35 #define TRACER_DLLEXPORT
36 #include "tracer.h"
37 #undef TRACER_DLLEXPORT
38 
39 #include "mcsconfig.h"
40 
41 using namespace std;
42 
43 namespace BRM
44 {
45 #ifdef BRM_INFO
46 std::ofstream brmlog(string(MCSLOGDIR) + "/brm.log", std::ios::app);
47 
Tracer(const std::string & file,int line,const std::string & msg,bool debug,bool writeNow)48 Tracer::Tracer(const std::string& file, int line, const std::string& msg, bool debug, bool writeNow): fFileName(file), fLine(line), fMsg(msg), fDebug(debug), fpid(getpid())
49 {
50     if (writeNow)
51         writeBegin();
52 }
53 
~Tracer()54 Tracer::~Tracer()
55 {
56     writeEnd();
57 }
58 
59 
printIntVec(const pair<string,const int * > & p)60 void printIntVec(const pair<string, const int*>& p)
61 {
62     brmlog << p.first << ": (" << *p.second << ") ";
63 }
64 
printBoolVec(const pair<string,const bool * > & p)65 void printBoolVec(const pair<string, const bool*>&  p)
66 {
67     brmlog << p.first << ": (" << *p.second << ") ";
68 }
69 
printStrVec(const pair<string,const string * > & p)70 void printStrVec(const pair<string, const string*>& p)
71 {
72     brmlog << p.first << ": (" << *p.second << ") ";
73 }
74 
printShortVec(const pair<string,const short * > & p)75 void printShortVec(const pair<string, const short*>& p)
76 {
77     brmlog << p.first << ": (" << *p.second << ") ";
78 }
79 
printInt64Vec(const pair<string,const int64_t * > & p)80 void printInt64Vec(const pair<string, const int64_t*>& p)
81 {
82     brmlog << p.first << ": (" << *p.second << ") ";
83 }
84 
85 
writeBegin()86 void Tracer::writeBegin()
87 {
88     brmlog << timeStamp() << fpid << ":" << fFileName << "@" << fLine << " " << fMsg << " begin - ";
89     for_each(fInputs.begin(), fInputs.end(), printIntVec);
90     for_each(fBoolInputs.begin(), fBoolInputs.end(), printBoolVec);
91     for_each(fStrInputs.begin(), fStrInputs.end(), printStrVec);
92     for_each(fShortInputs.begin(), fShortInputs.end(), printShortVec);
93     for_each(fInt64Inputs.begin(), fInt64Inputs.end(), printInt64Vec);
94     brmlog << endl << flush;
95 
96 }
97 
writeEnd()98 void Tracer::writeEnd()
99 {
100     brmlog << timeStamp() << fpid << ":" << fFileName << " " << fMsg << " end ";
101 
102     if (! fOutputs.empty() || ! fBoolOutputs.empty())
103         brmlog << "- ";
104 
105     for_each(fOutputs.begin(), fOutputs.end(), printIntVec);
106     for_each(fBoolOutputs.begin(), fBoolOutputs.end(), printBoolVec);
107     for_each(fShortOutputs.begin(), fShortOutputs.end(), printShortVec);
108     for_each(fInt64Outputs.begin(), fInt64Outputs.end(), printInt64Vec);
109     brmlog << endl << flush;
110 
111 }
112 
writeDirect(const std::string & msg)113 void Tracer::writeDirect(const std::string& msg)
114 {
115     brmlog << msg << endl;
116 }
117 
timeStamp()118 string Tracer::timeStamp()
119 {
120     time_t outputTime;
121     time(&outputTime);
122     string datestr(ctime(&outputTime));
123 
124     try
125     {
126         //replace newline
127         return datestr.replace(datestr.length() - 1, 1, string(":"));
128     }
129     catch (exception& ex)
130     {
131         size_t tries = 3;
132 
133         while (!datestr.length() && tries--)
134             datestr = ctime(&outputTime);
135 
136         if (datestr.length())
137             return datestr.replace(datestr.length() - 1, 1, string(":"));
138         else
139         {
140             std::cerr << __FILE__ << "@" << __LINE__ << " " << ex.what() << " ";
141             cerr << datestr << " length " << datestr.length() << " Source: ";
142             cerr << fFileName << "@" << fLine << " " << fMsg << endl;
143             return string("timestamp error:");
144         }
145     }
146 }
147 
148 
addInput(const string & name,const int * value)149 void Tracer::addInput(const string& name, const int* value)
150 {
151     fInputs.push_back(make_pair(name, value));
152 }
153 
addInput(const string & name,const string * value)154 void Tracer::addInput(const string& name, const string* value)
155 {
156     fStrInputs.push_back(make_pair(name, value));
157 }
158 
addInput(const string & name,const bool * value)159 void Tracer::addInput(const string& name, const bool* value)
160 {
161     fBoolInputs.push_back(make_pair(name, value));
162 }
163 
addInput(const string & name,const short * value)164 void Tracer::addInput(const string& name, const short* value)
165 {
166     fShortInputs.push_back(make_pair(name, value));
167 }
168 
addInput(const string & name,const int64_t * value)169 void Tracer::addInput(const string& name, const int64_t* value)
170 {
171     fInt64Inputs.push_back(make_pair(name, value));
172 }
173 
174 
addOutput(const string & name,const int * value)175 void Tracer::addOutput(const string& name, const int* value)
176 {
177     fOutputs.push_back(make_pair(name, value));
178 }
179 
addOutput(const string & name,const bool * value)180 void Tracer::addOutput(const string& name, const bool* value)
181 {
182     fBoolOutputs.push_back(make_pair(name, value));
183 }
184 
addOutput(const string & name,const short * value)185 void Tracer::addOutput(const string& name, const short* value)
186 {
187     fShortOutputs.push_back(make_pair(name, value));
188 }
189 
addOutput(const string & name,const int64_t * value)190 void Tracer::addOutput(const string& name, const int64_t* value)
191 {
192     fInt64Outputs.push_back(make_pair(name, value));
193 }
194 
195 #endif
196 
197 } //namespace
198