Imported Upstream version 15.1.0
[platform/upstream/libzypp.git] / zypp / base / Debug.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/Debug.h
10  *
11  * Debuging tools which should not be used in released code.
12 */
13 #ifndef ZYPP_NDEBUG
14 #warning ZYPP_BASE_DEBUG_H included
15 #ifndef ZYPP_BASE_DEBUG_H
16 #define ZYPP_BASE_DEBUG_H
17
18 #include <iosfwd>
19 //#include <sstream>
20 //#include <string>
21 #include "zypp/base/Logger.h"
22 #include "zypp/base/String.h"
23 #include "zypp/ExternalProgram.h"
24 #include "zypp/base/ProvideNumericId.h"
25
26 ///////////////////////////////////////////////////////////////////
27 namespace zypp
28 { /////////////////////////////////////////////////////////////////
29   ///////////////////////////////////////////////////////////////////
30   namespace debug
31   { /////////////////////////////////////////////////////////////////
32
33     /** \defgroup DEBUG Debug tools
34     */
35
36 #define TAG INT << __PRETTY_FUNCTION__ << std::endl
37
38     /** 'ps v' */
39     inline std::ostream & dumpMemOn( std::ostream & str, const std::string & msg = std::string() )
40     {
41       static std::string mypid( str::numstring( getpid() ) );
42       const char* argv[] =
43       {
44         "ps",
45         "v",
46         mypid.c_str(),
47         NULL
48       };
49       ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
50
51       str << "MEMUSAGE " << msg << std::endl;
52       for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() )
53           str << line;
54
55       prog.close();
56       return str;
57     }
58
59     ///////////////////////////////////////////////////////////////////
60     /** \defgroup DBG_TRACER Tracer
61      * \ingroup DEBUG
62     */
63     //@{
64     /** Base for a simple tracer. Provides an enum indicating which
65      * traced functions were called.
66     */
67     struct TraceCADBase
68     {
69       enum What { CTOR, COPYCTOR, ASSIGN, DTOR, PING };
70       std::string _ident;
71     };
72
73     /** \relates TraceCADBase Stream output of TraceCADBase::What. */
74     inline std::ostream & operator<<( std::ostream & str, TraceCADBase::What obj )
75     {
76       switch( obj )
77         {
78         case TraceCADBase::CTOR:     return str << "CTOR";
79         case TraceCADBase::COPYCTOR: return str << "COPYCTOR";
80         case TraceCADBase::ASSIGN:   return str << "ASSIGN";
81         case TraceCADBase::DTOR:     return str << "DTOR";
82         case TraceCADBase::PING:     return str << "PING";
83         }
84       return str;
85     }
86
87     /** A simple tracer for (copy) Construction, Assignment, and
88      * Destruction. To trace class Foo, derive public from
89      * TraceCAD<Foo>. This tracer simply calls traceCAD in each
90      * traced method, and traceCAD simply drops a line in the log.
91      *
92      * This tracer logs construction, copy construction, assignment,
93      * destruction and _PING.
94      *
95      * assignment: In case the traced class defines an operator=
96      * it must be altered to call TraceCAD::operator=, otherwise it
97      * won't be triggered.
98      *
99      * _PING: Completely up to you. Call _PING somewhere in the traced
100      * class to indicate something. In case you overload traceCAD, do
101      * whatever is appropriate on _PING. It's just an offer to perform
102      * logging or actions here, and not in the traced code.
103      *
104      * But traceCAD may be overloaded to produce more stats.
105      *
106      * \see \c Example.COW_debug.cc.
107      */
108     template<class _Tp>
109       struct TraceCAD : public base::ProvideNumericId<TraceCAD<_Tp>, unsigned long>
110                       , public TraceCADBase
111       {
112         static unsigned long & _totalTraceCAD()
113         { static unsigned long _val = 0;
114           return _val; }
115
116         TraceCAD()
117         { _ident = __PRETTY_FUNCTION__;
118           ++_totalTraceCAD();
119           traceCAD( CTOR, *this, *this ); }
120
121         TraceCAD( const TraceCAD & rhs )
122         { ++_totalTraceCAD();
123           traceCAD( COPYCTOR, *this, rhs ); }
124
125         TraceCAD & operator=( const TraceCAD & rhs )
126         { traceCAD( ASSIGN, *this, rhs ); return *this; }
127
128         virtual ~TraceCAD()
129         { --_totalTraceCAD();
130           traceCAD( DTOR, *this, *this ); }
131
132         void _PING() const
133         { traceCAD( PING, *this, *this ); }
134       };
135
136     /** \relates TraceCAD Stream output. */
137     template<class _Tp>
138       inline std::ostream & operator<<( std::ostream & str, const TraceCAD<_Tp> & obj )
139       { return str << "(ID " << obj.numericId() << ", TOTAL " << obj._totalTraceCAD()
140                    << ") [" << &obj << "] "; }
141
142     /** Drop a log line about the traced method. Overload to
143      * fit your needs.
144     */
145     template<class _Tp>
146       void traceCAD( TraceCADBase::What what_r,
147                      const TraceCAD<_Tp> & self_r,
148                      const TraceCAD<_Tp> & rhs_r )
149       {
150         switch( what_r )
151           {
152           case TraceCADBase::CTOR:
153           case TraceCADBase::PING:
154           case TraceCADBase::DTOR:
155             _DBG("DEBUG") << what_r << self_r << " (" << self_r._ident << ")" << std::endl;
156             break;
157
158           case TraceCADBase::COPYCTOR:
159           case TraceCADBase::ASSIGN:
160             _DBG("DEBUG") << what_r << self_r << "( " << rhs_r << ")" << " (" << self_r._ident << ")" << std::endl;
161             break;
162           }
163       }
164     //@}
165     ///////////////////////////////////////////////////////////////////
166
167     /////////////////////////////////////////////////////////////////
168   } // namespace debug
169   ///////////////////////////////////////////////////////////////////
170   /////////////////////////////////////////////////////////////////
171 } // namespace zypp
172 ///////////////////////////////////////////////////////////////////
173 #endif // ZYPP_BASE_DEBUG_H
174 #endif // ZYPP_NDEBUG