1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZORBA_AUDIT_SCOPED_H
18 #define ZORBA_AUDIT_SCOPED_H
19 
20 #include <iostream>
21 #include <sstream>
22 #include <cassert>
23 #include <zorba/audit.h>
24 #include <zorba/util/timer.h>
25 
26 namespace zorba {
27 namespace audit {
28 
29   class ZORBA_DLL_PUBLIC ScopedRecord {
30   public:
ScopedRecord(Event * event)31     ScopedRecord(Event* event)
32       : theEvent(event ? event : Event::get()),
33         theRecord(0) {
34       assert(theEvent);
35     }
36 
~ScopedRecord()37     ~ScopedRecord() {
38       if (theRecord) {
39         theEvent->submitRecord(theRecord);
40         theRecord = 0;
41       }
42     }
43 
getEvent()44     Event* getEvent() {
45       return theEvent;
46     }
47 
getRecord()48     Record* getRecord() {
49       if (! theRecord) {
50         theRecord = theEvent->createRecord();
51       }
52       return theRecord;
53     }
54 
55   private:
56       Event*  theEvent;
57       Record* theRecord;
58   };
59 
60   template <class T, unsigned char flags = 0> struct AuditorTraits {
61   };
62 
63   template <class T, unsigned char flags = 0> class ScopedAuditor {
64   public:
ScopedAuditor(ScopedRecord & record,const Property & prop,T & value)65     ScopedAuditor(ScopedRecord& record, const Property& prop, T& value)
66       : theRecord(record), theProperty(prop), theValue(value) {
67       theNeedToAuditFlag = record.getEvent()->audit(prop);
68       if (theNeedToAuditFlag) {
69         AuditorTraits<T, flags>::start(value);
70       }
71     }
72 
ScopedAuditor(ScopedRecord & record,const String & prop_name,T & value)73     ScopedAuditor(ScopedRecord& record, const String& prop_name, T& value)
74       : theRecord(record),
75         theProperty(*record.getEvent()->getDynamicProperty(prop_name)),
76         theValue(value) {
77       theNeedToAuditFlag = record.getEvent()->audit(prop_name);
78       if (theNeedToAuditFlag) {
79         AuditorTraits<T>::start(value);
80       }
81     }
82 
~ScopedAuditor()83     ~ScopedAuditor() {
84       now();
85     }
86 
now()87     void now() {
88       if (theNeedToAuditFlag) {
89         Record* rec = theRecord.getRecord();
90         rec->add(theProperty, AuditorTraits<T, flags>::end(theValue));
91         theNeedToAuditFlag = false;
92       }
93     }
94 
95   private:
ScopedAuditor()96     ScopedAuditor() {}
ScopedAuditor(const ScopedAuditor &)97     ScopedAuditor(const ScopedAuditor&) {}
98 
99     ScopedRecord&   theRecord;
100     const Property& theProperty;
101     bool            theNeedToAuditFlag;
102     T&              theValue;
103   };
104 
105   typedef ScopedAuditor<const std::string>       StringAuditor;
106   typedef ScopedAuditor<const int>               IntAuditor;
107   typedef ScopedAuditor<zorba::time::Timer>      DurationAuditor;
108   typedef ScopedAuditor<zorba::time::Timer, 0x1> TimestampAuditor;
109   typedef ScopedAuditor<zorba::time::Timer, 0x2> MicroDurationAuditor;
110 
111   template<> struct AuditorTraits<const std::string> {
112     typedef const std::string value_type;
113     typedef const std::string audit_type;
114     static inline void start(value_type& value) {
115     }
116     static inline audit_type end(value_type& value) {
117       return value;
118     }
119   };
120 
121   template<> struct AuditorTraits<String> {
122     typedef String value_type;
123     typedef String audit_type;
124     static inline void start(value_type& value) {
125     }
126     static inline audit_type end(value_type& value) {
127       return value;
128     }
129   };
130 
131   template<> struct AuditorTraits<const int> {
132     typedef const int       value_type;
133     typedef long long       audit_type;
134     static inline void start(value_type& value) {
135     }
136     static inline audit_type end(value_type& value) {
137       return value;
138     }
139   };
140 
141   template<> struct AuditorTraits<const char*> {
142     typedef const char* value_type;
143     typedef const char* audit_type;
144     static inline void start(value_type& value) {
145     }
146     static inline audit_type end(value_type& value) {
147       return static_cast<audit_type>(value);
148     }
149   };
150 
151   template<> struct AuditorTraits< std::pair<std::streampos, std::istream*> > {
152     typedef std::pair<std::streampos, std::istream*> value_type;
153     typedef long long      audit_type;
154     static inline void start(value_type& value) {
155       value.first = value.second->tellg();
156     }
157     static inline audit_type end(value_type& value) {
158       return value.second->tellg() - value.first;
159     }
160   };
161 
162   template<> struct AuditorTraits< std::pair<std::streampos, std::ostream*> > {
163     typedef std::pair<std::streampos, std::ostream*> value_type;
164     typedef long long      audit_type;
165     static inline void start(value_type& value) {
166       value.first = value.second->tellp();
167     }
168     static inline audit_type end(value_type& value) {
169       return value.second->tellp() - value.first;
170     }
171   };
172 
173   template<> struct AuditorTraits<zorba::time::Timer> {
174     typedef zorba::time::Timer value_type;
175     typedef long long          audit_type;
176     static inline void start(value_type& value) {
177       value.start();
178     }
179     static inline audit_type end(value_type& value) {
180       return static_cast<audit_type>(value.elapsed());
181     }
182 
183   };
184 
185   template<> struct AuditorTraits<zorba::time::Timer, 0x1> {
186     typedef zorba::time::Timer value_type;
187     typedef long long          audit_type;
188     static inline void start(value_type& value) {
189       value.start();
190     }
191     static inline audit_type end(value_type& value) {
192       return static_cast<audit_type>(value.getStart());
193     }
194   };
195 
196   template<> struct AuditorTraits<zorba::time::Timer, 0x2> {
197     typedef zorba::time::Timer value_type;
198     typedef long long          audit_type;
199     static inline void start(value_type& value) {
200       value.start();
201     }
202     static inline audit_type end(value_type& value) {
203       return static_cast<audit_type>(value.elapsed() * 1000);
204     }
205 
206   };
207 
208 }
209 }
210 #endif
211 /* vim:set et sw=2 ts=2: */
212