c07ba211cc32349cb2857dcc8a5fbfe35366ceb9
[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     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     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     RoutingEntry entry (*i);
105     rib_.erase(i);
106     if (entry.action_ == ACCEPT)
107         updateRoutingCache(entry.stream_, entry.area_);
108 }
109
110 ////////////////////////////////////////
111 // private members
112
113 prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
114                                       detail::AreaBase const * area, unsigned level,
115                                       action_t action, int index)
116 {
117     RIB::iterator i;
118     if (index < 0) {
119         if (RIB::size_type(-index-1) >= rib_.size())
120             i = rib_.begin();
121         else {
122             i = rib_.end();
123             std::advance(i, index + 1 );
124         }
125     } else {
126         if (RIB::size_type(index) >= rib_.size())
127             i = rib_.end();
128         else {
129             i = rib_.begin();
130             std::advance(i, index);
131         }
132     }
133     rib_.insert(i, RoutingEntry(stream, area, level, action));
134     if (action == ACCEPT)
135         updateRoutingCache(stream, area);
136 }
137
138 prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
139                                         detail::AreaBase const * area, unsigned level, 
140                                         action_t action)
141 {
142     RIB::iterator i = std::find(rib_.begin(), rib_.end(), 
143                                 RoutingEntry(stream, area, level, action));
144     if (i != rib_.end())
145         unroute(std::distance(rib_.begin(), i));
146 }
147
148 prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * stream,
149                                                    detail::AreaBase const * area)
150 {
151     if (! stream) {
152         StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin());
153         StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end());
154         for (; i != i_end ; ++i)
155             updateRoutingCache(i->second, area);
156         return;
157     }
158     if (! area) {
159         AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin());
160         AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end());
161         for (; i != i_end ; ++i)
162             updateRoutingCache(stream, i->second);
163         return;
164     }
165     unsigned limit (DISABLED::value);
166     RIB::iterator i (rib_.begin());
167     RIB::iterator const i_end (rib_.end());
168     for(; i != i_end; ++i)
169         if ( (! i->stream_ || i->stream_ == stream) &&
170              (! i->area_ || i->area_ == area) &&
171              i->action_ == ACCEPT ) {
172             unsigned l (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_);
173             if (l < limit)
174                 limit = l;
175         }
176     if (limit == DISABLED::value)
177         area->removeRoutingCache(*this, *stream);
178     else
179         area->updateRoutingCache(*this, *stream, limit);
180 }
181
182 prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp,
183                                       detail::StreamBase const & stream,
184                                       detail::AreaBase const & area, unsigned level,
185                                       std::string const & message)
186 {
187     RIB::iterator i (rib_.begin());
188     RIB::iterator const i_end (rib_.end());
189     for (; i != i_end; ++i)
190         if ( (! i->stream_ || i->stream_ == &stream) &&
191              (! i->area_ || i->area_ == &area) &&
192              (i->level_ == NONE::value ? i->stream_->defaultRuntimeLimit() : i->level_) <= level ) {
193             if (i->action_ == ACCEPT)
194                 v_write(timestamp, stream.v_name(), area.v_name(), level, message);
195             return;
196         }
197 }
198
199 ///////////////////////////////////////////////////////////////////////////
200 // senf::log::TargetRegistry
201
202 prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream,
203                                               detail::AreaBase const & area, unsigned level,
204                                               std::string msg)
205 {
206     boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time());
207     area.write(timestamp, stream, level, msg);
208 }
209
210 ///////////////////////////////cc.e////////////////////////////////////////
211 #undef prefix_
212 //#include "Target.mpp"
213
214 \f
215 // Local Variables:
216 // mode: c++
217 // fill-column: 100
218 // comment-column: 40
219 // c-file-style: "senf"
220 // indent-tabs-mode: nil
221 // ispell-local-dictionary: "american"
222 // compile-command: "scons -u test"
223 // End: