Imported Upstream version 16.3.2
[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, MOVECTOR, ASSIGN, MOVEASSIGN, 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::MOVECTOR:    return str << "MOVECTOR";
81         case TraceCADBase::ASSIGN:      return str << "ASSIGN";
82         case TraceCADBase::MOVEASSIGN:  return str << "MOVEASSIGN";
83         case TraceCADBase::DTOR:        return str << "DTOR";
84         case TraceCADBase::PING:        return str << "PING";
85         }
86       return str;
87     }
88
89     /** A simple tracer for (copy) Construction, Assignment, and
90      * Destruction. To trace class Foo, derive public from
91      * TraceCAD<Foo>. This tracer simply calls traceCAD in each
92      * traced method, and traceCAD simply drops a line in the log.
93      *
94      * This tracer logs construction, copy construction, assignment,
95      * destruction and ping.
96      *
97      * assignment: In case the traced class defines an operator=
98      * it must be altered to call TraceCAD::operator=, otherwise it
99      * won't be triggered.
100      *
101      * ping: Completely up to you. Call ping somewhere in the traced
102      * class to indicate something. In case you overload traceCAD, do
103      * whatever is appropriate on ping. It's just an offer to perform
104      * logging or actions here, and not in the traced code.
105      *
106      * But traceCAD may be overloaded to produce more stats.
107      *
108      * \see \c Example.COW_debug.cc.
109      */
110     template<class Tp>
111       struct TraceCAD : public base::ProvideNumericId<TraceCAD<Tp>, unsigned long>
112                       , public TraceCADBase
113       {
114         static unsigned long & _totalTraceCAD()
115         { static unsigned long _val = 0;
116           return _val; }
117
118         TraceCAD()
119         { _ident = __PRETTY_FUNCTION__;
120           ++_totalTraceCAD();
121           traceCAD( CTOR, *this, *this ); }
122
123         TraceCAD( const TraceCAD & rhs )
124         { ++_totalTraceCAD();
125           traceCAD( COPYCTOR, *this, rhs ); }
126
127         TraceCAD( TraceCAD && rhs )
128         { ++_totalTraceCAD();
129           traceCAD( MOVECTOR, *this, rhs ); }
130
131         TraceCAD & operator=( const TraceCAD & rhs )
132         { traceCAD( ASSIGN, *this, rhs ); return *this; }
133
134         TraceCAD & operator=( TraceCAD && rhs )
135         { traceCAD( MOVEASSIGN, *this, rhs ); return *this; }
136
137         virtual ~TraceCAD()
138         { --_totalTraceCAD();
139           traceCAD( DTOR, *this, *this ); }
140
141         void ping() const
142         { traceCAD( PING, *this, *this ); }
143       };
144
145     /** \relates TraceCAD Stream output. */
146     template<class Tp>
147       inline std::ostream & operator<<( std::ostream & str, const TraceCAD<Tp> & obj )
148       { return str << "(ID " << obj.numericId() << ", TOTAL " << obj._totalTraceCAD()
149                    << ") [" << &obj << "] "; }
150
151     /** Drop a log line about the traced method. Overload to
152      * fit your needs.
153     */
154     template<class Tp>
155       void traceCAD( TraceCADBase::What what_r,
156                      const TraceCAD<Tp> & self_r,
157                      const TraceCAD<Tp> & rhs_r )
158       {
159         switch( what_r )
160           {
161           case TraceCADBase::CTOR:
162           case TraceCADBase::PING:
163           case TraceCADBase::DTOR:
164             L_DBG("DEBUG") << what_r << self_r << " (" << self_r._ident << ")" << std::endl;
165             break;
166
167           case TraceCADBase::COPYCTOR:
168           case TraceCADBase::MOVECTOR:
169           case TraceCADBase::ASSIGN:
170           case TraceCADBase::MOVEASSIGN:
171             L_DBG("DEBUG") << what_r << self_r << "( " << rhs_r << ")" << " (" << self_r._ident << ")" << std::endl;
172             break;
173           }
174       }
175     //@}
176     ///////////////////////////////////////////////////////////////////
177
178     /////////////////////////////////////////////////////////////////
179   } // namespace debug
180   ///////////////////////////////////////////////////////////////////
181   /////////////////////////////////////////////////////////////////
182 } // namespace zypp
183 ///////////////////////////////////////////////////////////////////
184 #endif // ZYPP_BASE_DEBUG_H
185 #endif // ZYPP_NDEBUG