aee4d6e802ac9299a248de2eef350d6e8c6de379
[senf.git] / Utils / Logger / Target.cc
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS) 
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY 
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Target non-inline non-template implementation */
25
26 #include "Target.hh"
27 #include "Target.ih"
28
29 // Custom includes
30 #include <algorithm>
31 #include "ConsoleTarget.hh"
32
33 //#include "Target.mpp"
34 #define prefix_
35 ///////////////////////////////cc.p////////////////////////////////////////
36
37 ///////////////////////////////////////////////////////////////////////////
38 // senf::log::Target
39
40 prefix_ senf::log::Target::Target()
41 {
42     detail::TargetRegistry::instance().registerTarget(this);
43 }
44
45 prefix_ senf::log::Target::~Target()
46 {
47     while( ! rib_.empty()) {
48         // This is terribly slow but simplifies the area cache handling and removing a target should
49         // be quite seldom
50         RIB::reverse_iterator i (rib_.rbegin());
51         unroute(i->stream_, i->area_, i->level_, i->action_);
52     }
53     detail::TargetRegistry::instance().unregisterTarget(this);
54 }
55
56 prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area,
57                                       unsigned level, action_t action, int index)
58 {
59     detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
60     if (!s)
61         throw InvalidStreamException();
62     detail::AreaBase const * a (0);
63     if (! area.empty()) {
64         a = AreaRegistry::instance().lookup(area);
65         if (!a)
66             throw InvalidAreaException();
67     }
68     route(s, a, level, action, index);
69 }
70
71 prefix_ void senf::log::Target::unroute(std::string const & stream, std::string const & area,
72                                         unsigned level, action_t action)
73 {
74     detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
75     if (!s)
76         throw InvalidStreamException();
77     detail::AreaBase const * a (0);
78     if (! area.empty()) {
79         a = AreaRegistry::instance().lookup(area);
80         if (!a)
81             throw InvalidAreaException();
82     }
83     unroute(s, a, level, action);
84 }
85
86 prefix_ void senf::log::Target::unroute(int index)
87 {
88     RIB::iterator i;
89     if (index < 0) {
90         if (RIB::size_type(-index) >= rib_.size())
91             i = rib_.begin();
92         else {
93             i = rib_.end();
94             std::advance(i, index);
95         }
96     } else {
97         if (RIB::size_type(index+1) >= rib_.size()) {
98             i = rib_.end();
99             --i;
100         } else {
101             i = rib_.begin();
102             std::advance(i, index);
103         }
104     }
105     if (i == rib_.end())
106         return;
107     RoutingEntry entry (*i);
108     rib_.erase(i);
109     if (entry.action_ == ACCEPT)
110         updateRoutingCache(entry.stream_, entry.area_);
111 }
112
113 ////////////////////////////////////////
114 // private members
115
116 prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
117                                       detail::AreaBase const * area, unsigned level,
118                                       action_t action, int index)
119 {
120     RIB::iterator i;
121     if (index < 0) {
122         if (RIB::size_type(-index-1) >= rib_.size())
123             i = rib_.begin();
124         else {
125             i = rib_.end();
126             std::advance(i, index + 1 );
127         }
128     } else {
129         if (RIB::size_type(index) >= rib_.size())
130             i = rib_.end();
131         else {
132             i = rib_.begin();
133             std::advance(i, index);
134         }
135     }
136     rib_.insert(i, RoutingEntry(stream, area, level, action));
137     if (action == ACCEPT)
138         updateRoutingCache(stream, area);
139     // This disables the initial fallback routing
140     detail::TargetRegistry::instance().routed();
141 }
142
143 prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
144                                         detail::AreaBase const * area, unsigned level, 
145                                         action_t action)
146 {
147     RIB::iterator i = std::find(rib_.begin(), rib_.end(), 
148                                 RoutingEntry(stream, area, level, action));
149     if (i != rib_.end())
150         unroute(std::distance(rib_.begin(), i));
151 }
152
153 prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * stream,
154                                                    detail::AreaBase const * area)
155 {
156     if (! stream) {
157         StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin());
158         StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end());
159         for (; i != i_end ; ++i)
160             updateRoutingCache(i->second, area);
161         return;
162     }
163     if (! area) {
164         AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin());
165         AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end());
166         for (; i != i_end ; ++i)
167             updateRoutingCache(stream, i->second);
168         return;
169     }
170     unsigned limit (DISABLED::value);
171     RIB::iterator i (rib_.begin());
172     RIB::iterator const i_end (rib_.end());
173     for(; i != i_end; ++i)
174         if ( (! i->stream_ || i->stream_ == stream) &&
175              (! i->area_ || i->area_ == area) &&
176              i->action_ == ACCEPT ) {
177             unsigned l (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_);
178             if (l < limit)
179                 limit = l;
180         }
181     if (limit == DISABLED::value)
182         area->removeRoutingCache(*this, *stream);
183     else
184         area->updateRoutingCache(*this, *stream, limit);
185 }
186
187 prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp,
188                                       detail::StreamBase const & stream,
189                                       detail::AreaBase const & area, unsigned level,
190                                       std::string const & message)
191 {
192     RIB::iterator i (rib_.begin());
193     RIB::iterator const i_end (rib_.end());
194     for (; i != i_end; ++i)
195         if ( (! i->stream_ || i->stream_ == &stream) &&
196              (! i->area_ || i->area_ == &area) &&
197              (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_) <= level ) {
198             if (i->action_ == ACCEPT)
199                 v_write(timestamp, stream.v_name(), area.v_name(), level, message);
200             return;
201         }
202 }
203
204 ///////////////////////////////////////////////////////////////////////////
205 // senf::log::detail::TargetRegistry
206
207 prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
208                                                       AreaBase const & area, unsigned level,
209                                                       std::string msg)
210 {
211     if (fallbackRouting_)
212         static_cast<Target &>(ConsoleTarget::instance()).v_write( 
213             (*timeSource_)(), stream.v_name(), area.v_name(), level, msg );
214     else
215         area.write( (*timeSource_)(), stream, level, msg );
216 }
217
218 ///////////////////////////////////////////////////////////////////////////
219 // senf::log::TimeSource
220
221 prefix_ senf::log::TimeSource::~TimeSource()
222 {}
223
224 ///////////////////////////////////////////////////////////////////////////
225 // senf::log::SystemTimeSource
226
227 prefix_ boost::posix_time::ptime senf::log::SystemTimeSource::operator()()
228     const
229 {
230     return boost::posix_time::microsec_clock::universal_time();
231 }
232
233 ///////////////////////////////cc.e////////////////////////////////////////
234 #undef prefix_
235 //#include "Target.mpp"
236
237 \f
238 // Local Variables:
239 // mode: c++
240 // fill-column: 100
241 // comment-column: 40
242 // c-file-style: "senf"
243 // indent-tabs-mode: nil
244 // ispell-local-dictionary: "american"
245 // compile-command: "scons -u test"
246 // End: