I'm too tired ??
[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 slow but simplifies the area cache handling and removing a target should be
49         // relatively 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     if (rib_.empty())
89         return;
90     RIB::iterator i;
91     if (index < 0) {
92         if (RIB::size_type(-index) >= rib_.size())
93             i = rib_.begin();
94         else {
95             i = rib_.end();
96             std::advance(i, index);
97         }
98     } else {
99         if (RIB::size_type(index+1) >= rib_.size()) {
100             i = rib_.end();
101             --i;
102         } else {
103             i = rib_.begin();
104             std::advance(i, index);
105         }
106     }
107     if (i == rib_.end())
108         return;
109     RoutingEntry entry (*i);
110     rib_.erase(i);
111     if (entry.action_ == ACCEPT)
112         updateRoutingCache(entry.stream_, entry.area_);
113 }
114
115 prefix_ void senf::log::Target::clear()
116 {
117     RIB old;
118     rib_.swap(old);
119     RIB::const_iterator i (old.begin());
120     RIB::const_iterator const i_end (old.end());
121     for (; i != i_end; ++i)
122         if (i->action_ == ACCEPT)
123             updateRoutingCache(i->stream_, i->area_);
124 }
125
126 ////////////////////////////////////////
127 // private members
128
129 prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
130                                       detail::AreaBase const * area, unsigned level,
131                                       action_t action, int index)
132 {
133     RIB::iterator i;
134     if (index < 0) {
135         if (RIB::size_type(-index-1) >= rib_.size())
136             i = rib_.begin();
137         else {
138             i = rib_.end();
139             std::advance(i, index + 1 );
140         }
141     } else {
142         if (RIB::size_type(index) >= rib_.size())
143             i = rib_.end();
144         else {
145             i = rib_.begin();
146             std::advance(i, index);
147         }
148     }
149     rib_.insert(i, RoutingEntry(stream, area, level, action));
150     if (action == ACCEPT)
151         updateRoutingCache(stream, area);
152     // This disables the initial fallback routing
153     detail::TargetRegistry::instance().routed();
154 }
155
156 prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
157                                         detail::AreaBase const * area, unsigned level,
158                                         action_t action)
159 {
160     RIB::iterator i = std::find(rib_.begin(), rib_.end(),
161                                 RoutingEntry(stream, area, level, action));
162     if (i != rib_.end())
163         unroute(std::distance(rib_.begin(), i));
164 }
165
166 prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * stream,
167                                                    detail::AreaBase const * area)
168 {
169     if (! stream) {
170         StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin());
171         StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end());
172         for (; i != i_end ; ++i)
173             updateRoutingCache(i->second, area);
174         return;
175     }
176     if (! area) {
177         AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin());
178         AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end());
179         for (; i != i_end ; ++i)
180             updateRoutingCache(stream, i->second);
181         return;
182     }
183     unsigned limit (DISABLED::value);
184     RIB::iterator i (rib_.begin());
185     RIB::iterator const i_end (rib_.end());
186     for(; i != i_end; ++i)
187         if ( (! i->stream_ || i->stream_ == stream) &&
188              (! i->area_ || i->area_ == area) &&
189              i->action_ == ACCEPT ) {
190             unsigned l (i->level_ == NONE::value ? stream->defaultRuntimeLimit() : i->level_);
191             if (l < limit)
192                 limit = l;
193         }
194     if (limit == DISABLED::value)
195         area->removeRoutingCache(*this, *stream);
196     else
197         area->updateRoutingCache(*this, *stream, limit);
198 }
199
200 prefix_ void senf::log::Target::write(time_type timestamp,
201                                       detail::StreamBase const & stream,
202                                       detail::AreaBase const & area, unsigned level,
203                                       std::string const & message)
204 {
205     RIB::iterator i (rib_.begin());
206     RIB::iterator const i_end (rib_.end());
207     for (; i != i_end; ++i)
208         if ( (! i->stream_ || i->stream_ == &stream) &&
209              (! i->area_ || i->area_ == &area) &&
210              (i->level_ == NONE::value ? stream.defaultRuntimeLimit() : i->level_) <= level ) {
211             if (i->action_ == ACCEPT)
212                 v_write(timestamp, stream.v_name(), area.v_name(), level, message);
213             return;
214         }
215 }
216
217 ///////////////////////////////////////////////////////////////////////////
218 // senf::log::detail::TargetRegistry
219
220 prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
221                                                       AreaBase const & area, unsigned level,
222                                                       std::string const & msg)
223 {
224     if (fallbackRouting_) {
225         if (level >= stream.defaultRuntimeLimit())
226             static_cast<Target &>(ConsoleTarget::instance()).v_write(
227                 TimeSource::now(), stream.v_name(), area.v_name(), level, msg );
228     }
229     else
230         area.write( TimeSource::now(), stream, level, msg );
231 }
232 ///////////////////////////////////////////////////////////////////////////
233 // namespace members
234
235 prefix_ std::ostream & senf::log::operator<<(std::ostream & os, senf::log::Target::action_t const & action)
236 {
237     if( action == Target::ACCEPT) os << "ACCEPT";
238     else if( action == Target::REJECT) os << "REJECT";
239     else os << "unknown action";
240     return os;
241 }
242
243
244 ///////////////////////////////cc.e////////////////////////////////////////
245 #undef prefix_
246 //#include "Target.mpp"
247
248
249 // Local Variables:
250 // mode: c++
251 // fill-column: 100
252 // comment-column: 40
253 // c-file-style: "senf"
254 // indent-tabs-mode: nil
255 // ispell-local-dictionary: "american"
256 // compile-command: "scons -u test"
257 // End: