01864ec65215595ce635b85179b1f036641b77c2
[senf.git] / Utils / Logger / Target.cc
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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
32 //#include "Target.mpp"
33 #define prefix_
34 ///////////////////////////////cc.p////////////////////////////////////////
35
36 ///////////////////////////////////////////////////////////////////////////
37 // senf::log::Target
38
39 prefix_ senf::log::Target::Target()
40 {
41     detail::TargetRegistry::instance().registerTarget(this);
42 }
43
44 prefix_ senf::log::Target::~Target()
45 {
46     while( ! rib_.empty()) {
47         // This is terribly slow but simplifies the area cache handling and removing a target should
48         // be quite seldom
49         RIB::reverse_iterator i (rib_.rbegin());
50         unroute(i->stream_, i->area_, i->level_, i->action_);
51     }
52     detail::TargetRegistry::instance().unregisterTarget(this);
53 }
54
55 prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area,
56                                       unsigned level, action_t action, int index)
57 {
58     detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
59     if (!s)
60         throw InvalidStreamException();
61     detail::AreaBase const * a (0);
62     if (! area.empty()) {
63         a = AreaRegistry::instance().lookup(area);
64         if (!a)
65             throw InvalidAreaException();
66     }
67     route(s, a, level, action, index);
68 }
69
70 prefix_ void senf::log::Target::unroute(std::string const & stream, std::string const & area,
71                                         unsigned level, action_t action)
72 {
73     detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
74     if (!s)
75         throw InvalidStreamException();
76     detail::AreaBase const * a (0);
77     if (! area.empty()) {
78         a = AreaRegistry::instance().lookup(area);
79         if (!a)
80             throw InvalidAreaException();
81     }
82     unroute(s, a, level, action);
83 }
84
85 prefix_ void senf::log::Target::unroute(int index)
86 {
87     RIB::iterator i;
88     if (index < 0) {
89         if (RIB::size_type(-index) >= rib_.size())
90             i = rib_.begin();
91         else {
92             i = rib_.end();
93             std::advance(i, index);
94         }
95     } else {
96         if (RIB::size_type(index+1) >= rib_.size()) {
97             i = rib_.end();
98             --i;
99         } else {
100             i = rib_.begin();
101             std::advance(i, index);
102         }
103     }
104     if (i == rib_.end())
105         return;
106     RoutingEntry entry (*i);
107     rib_.erase(i);
108     if (entry.action_ == ACCEPT)
109         updateRoutingCache(entry.stream_, entry.area_);
110 }
111
112 ////////////////////////////////////////
113 // private members
114
115 prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
116                                       detail::AreaBase const * area, unsigned level,
117                                       action_t action, int index)
118 {
119     RIB::iterator i;
120     if (index < 0) {
121         if (RIB::size_type(-index-1) >= rib_.size())
122             i = rib_.begin();
123         else {
124             i = rib_.end();
125             std::advance(i, index + 1 );
126         }
127     } else {
128         if (RIB::size_type(index) >= rib_.size())
129             i = rib_.end();
130         else {
131             i = rib_.begin();
132             std::advance(i, index);
133         }
134     }
135     rib_.insert(i, RoutingEntry(stream, area, level, action));
136     if (action == ACCEPT)
137         updateRoutingCache(stream, area);
138 }
139
140 prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
141                                         detail::AreaBase const * area, unsigned level, 
142                                         action_t action)
143 {
144     RIB::iterator i = std::find(rib_.begin(), rib_.end(), 
145                                 RoutingEntry(stream, area, level, action));
146     if (i != rib_.end())
147         unroute(std::distance(rib_.begin(), i));
148 }
149
150 prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * stream,
151                                                    detail::AreaBase const * area)
152 {
153     if (! stream) {
154         StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin());
155         StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end());
156         for (; i != i_end ; ++i)
157             updateRoutingCache(i->second, area);
158         return;
159     }
160     if (! area) {
161         AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin());
162         AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end());
163         for (; i != i_end ; ++i)
164             updateRoutingCache(stream, i->second);
165         return;
166     }
167     unsigned limit (DISABLED::value);
168     RIB::iterator i (rib_.begin());
169     RIB::iterator const i_end (rib_.end());
170     for(; i != i_end; ++i)
171         if ( (! i->stream_ || i->stream_ == stream) &&
172              (! i->area_ || i->area_ == area) &&
173              i->action_ == ACCEPT ) {
174             unsigned l (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_);
175             if (l < limit)
176                 limit = l;
177         }
178     if (limit == DISABLED::value)
179         area->removeRoutingCache(*this, *stream);
180     else
181         area->updateRoutingCache(*this, *stream, limit);
182 }
183
184 prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp,
185                                       detail::StreamBase const & stream,
186                                       detail::AreaBase const & area, unsigned level,
187                                       std::string const & message)
188 {
189     RIB::iterator i (rib_.begin());
190     RIB::iterator const i_end (rib_.end());
191     for (; i != i_end; ++i)
192         if ( (! i->stream_ || i->stream_ == &stream) &&
193              (! i->area_ || i->area_ == &area) &&
194              (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_) <= level ) {
195             if (i->action_ == ACCEPT)
196                 v_write(timestamp, stream.v_name(), area.v_name(), level, message);
197             return;
198         }
199 }
200
201 ///////////////////////////////////////////////////////////////////////////
202 // senf::log::TimeSource
203
204 prefix_ senf::log::TimeSource::~TimeSource()
205 {}
206
207 ///////////////////////////////////////////////////////////////////////////
208 // senf::log::SystemTimeSource
209
210 prefix_ boost::posix_time::ptime senf::log::SystemTimeSource::operator()()
211     const
212 {
213     return boost::posix_time::microsec_clock::universal_time();
214 }
215
216 ///////////////////////////////cc.e////////////////////////////////////////
217 #undef prefix_
218 //#include "Target.mpp"
219
220 \f
221 // Local Variables:
222 // mode: c++
223 // fill-column: 100
224 // comment-column: 40
225 // c-file-style: "senf"
226 // indent-tabs-mode: nil
227 // ispell-local-dictionary: "american"
228 // compile-command: "scons -u test"
229 // End: