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