include/wipal/wifi/frame/filter/fast_intersector.hxx

00001 /*
00002  * WiPal - A library and a set of tools to manipulate wireless traces.
00003  * Copyright (C) 2007  Universite Pierre et Marie Curie - Paris 6
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  * MA  02110-1301  USA
00019  *
00020  * Author: Thomas Claveirole <thomas.claveirole@lip6.fr>
00021  */
00022 #ifndef WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_
00023 # define WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_
00024 
00025 # include <iostream>
00026 # include <boost/foreach.hpp>
00027 
00028 # include "fast_intersector.hh"
00029 
00030 # include <wipal/wifi/frame/filter/non_noisy_prism.hh>
00031 # include <wipal/wifi/frame/filter/uniquely_identifiable.hh>
00032 
00033 namespace wifi
00034 {
00035   namespace frame
00036   {
00037     namespace filter
00038     {
00039 
00040       namespace internals
00041       {
00042 
00043         template <class I1, class I2, class B1, class B2>
00044         fast_intersector_iterator<I1, I2, B1, B2>::
00045         fast_intersector_iterator(const iterable_type& i, bool end):
00046           super_type (),
00047           iterable_ (&i),
00048           next_ (end ? i.last_ : i.first_)
00049 # ifdef ENABLE_INFO
00050         , rhs_total_ (0),
00051           ref_total_ (0)
00052 # endif // ENABLE_INFO
00053         {
00054           if (not end)
00055             increment();
00056         }
00057 
00058         template <class I1, class I2, class B1, class B2>
00059         bool
00060         fast_intersector_iterator<I1, I2, B1, B2>::
00061         equal(const fast_intersector_iterator& rhs) const
00062         {
00063           if (not rhs.value())
00064             return not this->value();
00065           return next_ == rhs.next_;
00066         }
00067 
00068         template <class I1, class I2, class B1, class B2>
00069         void
00070         fast_intersector_iterator<I1, I2, B1, B2>::increment()
00071         {
00072           const I2&             last = this->iterable_->last_;
00073           bool                  found (false);
00074 
00075           while (next_ != last and not found)
00076             {
00077               found = check();
00078               ++next_;
00079 # ifdef ENABLE_INFO
00080               ++rhs_total_;
00081 # endif // ENABLE_INFO
00082             }
00083 
00084           if (not found)
00085             {
00086               this->value() = lookahead_;
00087               lookahead_ = boost::none_t ();
00088             }
00089 
00090 # ifdef ENABLE_INFO
00091           if (not found and not this->value())
00092             {
00093               const unsigned    lhs_total = this->iterable_->arrivals_.size();
00094 
00095               std::cerr << "INFO: Trace 2 has " << rhs_total_
00096                         << " unique frames.\n"
00097                         << "INFO: " << ref_total_ << " reference frames.\n"
00098                         << "INFO: " << (ref_total_ * 100.f / lhs_total)
00099                         << "% of trace 1's unique frames.\n"
00100                         << "INFO: " << (ref_total_ * 100.f / rhs_total_)
00101                         << "% of trace 2's unique frames." << std::endl;
00102             }
00103           else
00104             ++ref_total_;
00105 # endif // ENABLE_INFO
00106         }
00107 
00108         template <class I1, class I2, class B1, class B2>
00109         bool
00110         fast_intersector_iterator<I1, I2, B1, B2>::check()
00111         {
00112           typedef typename iterable_type::arrivals_type         arrivals_type;
00113           typedef typename arrivals_type::const_iterator        iterator;
00114 
00115           const arrivals_type&  arrivals = iterable_->arrivals_;
00116           const iterator        i = arrivals.find(*next_);
00117 
00118           if (i == arrivals.end())
00119             return false;
00120 
00121           if (not lookahead_)
00122             {
00123               // First reference we encounter.  Delay it so we can
00124               // filter it out in case it is dubious.
00125 
00126               lookahead_ = value_type (*i, *next_);
00127               return false;
00128             }
00129           assert(lookahead_);
00130 
00131           value_type&                   lookahead = lookahead_.get();
00132           const tool::microseconds      dt1 (i->microseconds() -
00133                                              lookahead.first.microseconds());
00134           const tool::microseconds      dt2 (next_->microseconds() -
00135                                              lookahead.second.microseconds());
00136           const tool::microseconds      drift (dt1 - dt2);
00137 
00138           if (drift < -drift_warn_threshold or drift_warn_threshold < drift)
00139             {
00140               std::cerr << "WARNING: Dubious drift of " << (drift / 1000000.f)
00141                         << "s for "
00142                         << i->frame_id() << '-' << next_->frame_id();
00143               if (this->value())
00144                 {
00145                   // General case.  The dubious frame is the current one.
00146 
00147                   std::cerr << " (ignoring reference)." << std::endl;
00148                   return false;
00149                 }
00150               else
00151                 {
00152                   // We are on the second frame.  Consider the first frame
00153                   // as dubious, and delay this one.
00154 
00155                   std::cerr << ".\n" "WARNING: Ignoring the potentially "
00156                                "invalid previous reference "
00157                             << lookahead.first.frame_id() << '-'
00158                             << lookahead.second.frame_id() << '.' << std::endl;
00159 
00160                   lookahead = value_type (*i, *next_);
00161                   return false;
00162                 }
00163             }
00164 
00165           if (i->microseconds() < lookahead.first.microseconds())
00166             std::cerr << "WARNING: Reference " << i->frame_id() << '-'
00167                       << next_->frame_id() << " anterior to "
00168                       << lookahead.first.frame_id() << '-'
00169                       << lookahead.second.frame_id() << '.' << std::endl;
00170           else if (dt1 > dt_warn_threshold or dt2 > dt_warn_threshold)
00171             std::cerr << "WARNING: " << (dt1 / 1000000.f) << "s and "
00172                       << (dt2 / 1000000.f) << "s between "
00173                       << lookahead.first.frame_id() << '-'
00174                       << lookahead.second.frame_id() << " and "
00175                       << i->frame_id() << '-' << next_->frame_id()
00176                       << '.' << std::endl;
00177 
00178           this->value() = lookahead;
00179           lookahead = value_type (*i, *next_);
00180           return true;
00181         }
00182 
00183       } // End of namespace internals.
00184 
00185 
00186       template <class I1, class I2, class B>
00187       fast_intersector<I1, I2, B>::
00188       fast_intersector(const I1& first1, const I1& last1,
00189                        const I2& first2, const I2& last2):
00190         first_ (first2),
00191         last_ (last2)
00192 # ifndef DONT_USE_HASH
00193         , arrivals_ (hash_bucket_count)
00194 # endif
00195       {
00196         arrivals_type   collisions;
00197 
00198         for (I1 i = first1; i != last1; ++i)
00199           {
00200             typedef typename arrivals_type::iterator    iterator;
00201 
00202             std::pair<iterator, bool> r = arrivals_.insert(*i);
00203 
00204             if (not r.second)
00205               {
00206                 collisions.insert(*i);
00207                 std::cerr << "WARNING: Unique frame " << i->frame_id()
00208                           << " actually a duplicate of "
00209                           << r.first->frame_id() << " (ignoring both)."
00210                           << std::endl;
00211               }
00212           }
00213 
00214         BOOST_FOREACH(const typename I1::value_type& v, collisions)
00215           arrivals_.erase(v);
00216 
00217 # ifdef ENABLE_INFO
00218         std::cerr << "INFO: Trace 1's unique frames successfuly loaded.\n"
00219                   << "INFO: Trace 1 has " << arrivals_.size()
00220                   << " unique frames." << std::endl;
00221 # endif // ENABLE_INFO
00222 
00223       }
00224 
00225     } // End of namespace wifi::frame::filter.
00226 
00227   } // End of namespace wifi::frame.
00228 
00229 } // End of namespace wifi.
00230 
00231 #endif // ! WIFI_FRAME_FILTER_FAST_INTERSECTOR_HXX_

Generated on Wed Jan 16 16:15:14 2008 for wipal by  doxygen 1.5.4