00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_
00023 # define WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_
00024
00025 # include <iostream>
00026
00027 # include "windowed_merge.hh"
00028
00029 # include <wipal/wifi/frame/filter/merge.hh>
00030
00031 namespace wifi
00032 {
00033 namespace frame
00034 {
00035 namespace filter
00036 {
00037
00038 namespace internals
00039 {
00040
00041 # ifdef WP_ENABLE_INFO
00042 # define WP_increment(X) ++(X)
00043 # define WP_increase(X, Y...) ((X) += (Y))
00044 # else // ! WP_ENABLE_INFO
00045 # define WP_increment(X) (void) 0
00046 # define WP_increase(X, Y...) (void) (Y)
00047 # endif // WP_ENABLE_INFO
00048
00049 template <class HT, class I1, class I2, class B1, class B2>
00050 windowed_merge_iterator<HT, I1, I2, B1, B2>::
00051 windowed_merge_iterator(const iterable_type& i, bool end):
00052 iterable_ (&i),
00053 next1_ (end ? i.last1_ : i.first1_),
00054 next2_ (end ? i.last2_ : i.first2_),
00055 current_ (-1)
00056 # ifdef WP_ENABLE_INFO
00057 , lhs_total_ (0),
00058 rhs_total_ (0),
00059 shared_ (0),
00060 total_ (0),
00061 sync_error_ (0)
00062 # endif
00063 {
00064 if (not end)
00065 {
00066 WP_increase(lhs_total_, fill(win1_, next1_, iterable_->last1_,
00067 window_size));
00068 WP_increase(rhs_total_, fill(win2_, next2_, iterable_->last2_,
00069 window_size));
00070 update_current();
00071 }
00072 }
00073
00074 template <class HT, class I1, class I2, class B1, class B2>
00075 bool
00076 windowed_merge_iterator<HT, I1, I2, B1, B2>::
00077 equal(const windowed_merge_iterator& rhs) const
00078 {
00079 return (next1_ == rhs.next1_ and win1_.size() == rhs.win1_.size() and
00080 next2_ == rhs.next2_ and win2_.size() == rhs.win2_.size());
00081 }
00082
00083 #define WP_advance(Counter, N) \
00084 do \
00085 { \
00086 WP_increase(Counter, fill(win ## N ## _, next ## N ## _, \
00087 iterable_->last ## N ## _, 1)); \
00088 win ## N ## _.pop_front(); \
00089 } \
00090 while (0)
00091
00092 template <class HT, class I1, class I2, class B1, class B2>
00093 void
00094 windowed_merge_iterator<HT, I1, I2, B1, B2>::increment()
00095 {
00096 assert(current_ == 0 or current_ == 1);
00097
00098 if (win1_.empty())
00099 WP_advance(rhs_total_, 2);
00100 else if (win2_.empty())
00101 WP_advance(lhs_total_, 1);
00102 else if (const optional_match r = match())
00103 {
00104 # ifdef WP_ENABLE_INFO
00105 {
00106 const tool::microseconds& t1 = r->first->microseconds();
00107 const tool::microseconds& t2 = r->second->microseconds();
00108
00109 if (t1 > t2)
00110 sync_error_ += tool::microseconds (t1 - t2).get_ui();
00111 else
00112 sync_error_ += tool::microseconds (t2 - t1).get_ui();
00113 }
00114 ++shared_;
00115 # endif // WP_ENABLE_INFO
00116 win1_.erase(r->first);
00117 win2_.erase(r->second);
00118 WP_increase(lhs_total_,
00119 fill(win1_, next1_, iterable_->last1_, 1));
00120 WP_increase(rhs_total_,
00121 fill(win2_, next2_, iterable_->last2_, 1));
00122 }
00123 else
00124 {
00125 if (current_)
00126 WP_advance(rhs_total_, 2);
00127 else
00128 WP_advance(lhs_total_, 1);
00129 }
00130 WP_increment(total_);
00131
00132 update_current();
00133
00134 # ifdef WP_ENABLE_INFO
00135 if (current_ == -1)
00136 std::cerr << "INFO: " << shared_ << " frames shared by"
00137 " both traces.\n"
00138 << "INFO: Trace 1 has " << lhs_total_ << " frames ("
00139 << (shared_ * 100.f / lhs_total_) << "% shared).\n"
00140 << "INFO: Trace 2 has " << rhs_total_ << " frames ("
00141 << (shared_ * 100.f / rhs_total_) << "% shared).\n"
00142 << "INFO: Output has " << total_ << " frames ("
00143 << (shared_ * 100.f / total_) << "% shared).\n"
00144 << "INFO: Mean sync. error is "
00145 << (sync_error_ / shared_) << " microseconds."
00146 << std::endl;
00147 # endif // WP_ENABLE_INFO
00148 }
00149
00150 # undef WP_advance
00151 # undef WP_increment
00152 # undef WP_increase
00153
00154 template <class HT, class I1, class I2, class B1, class B2>
00155 int
00156 windowed_merge_iterator<HT, I1, I2, B1, B2>::first_packet() const
00157 {
00158 const bool first_at_end = win1_.empty();
00159 const bool second_at_end = win2_.empty();
00160
00161 if (first_at_end)
00162 return second_at_end ? -1 : 1;
00163 if (second_at_end)
00164 return 0;
00165
00166 return win1_.front().microseconds() < win2_.front().microseconds() ?
00167 0 : 1;
00168 }
00169
00170 template <class HT, class I1, class I2, class B1, class B2>
00171 void
00172 windowed_merge_iterator<HT, I1, I2, B1, B2>::update_current()
00173 {
00174 switch (current_ = first_packet())
00175 {
00176 case -1:
00177 this->value() = boost::none_t ();
00178 break;
00179
00180 case 0:
00181 this->value() = win1_.front();
00182 break;
00183
00184 case 1:
00185 this->value() = win2_.front();
00186 break;
00187
00188 default:
00189 throw std::logic_error ("Internal error, this code should not "
00190 "be reachable. Please fill a bug "
00191 "report.");
00192 }
00193 }
00194
00195 template <class HT, class I1, class I2, class B1, class B2>
00196 template <class WindowType, class I>
00197 unsigned
00198 windowed_merge_iterator<HT, I1, I2, B1, B2>::
00199 fill(WindowType& w,
00200 I& i,
00201 const I& last,
00202 size_t n)
00203 {
00204 unsigned r;
00205
00206 for (r = 0; r < n and i != last; ++r)
00207 w.push_back(*i++);
00208 return r;
00209 }
00210
00211 template <class HT, class I1, class I2, class B1, class B2>
00212 typename windowed_merge_iterator<HT, I1, I2, B1, B2>::optional_match
00213 windowed_merge_iterator<HT, I1, I2, B1, B2>::match()
00214 {
00215 using internals::make_equal;
00216
00217 if (current_)
00218 {
00219 const win1_iterator f = win1_.begin();
00220 const win1_iterator l = win1_.end();
00221 const win1_iterator r =
00222 std::find(f, l,
00223 make_equal<HT>(win2_.front(),
00224 iterable_->precision_,
00225 iterable_->phy_end_,
00226 iterable_->pcap_tstamps_));
00227
00228 if (r == l)
00229 return boost::none_t ();
00230
00231 return match_type (r, win2_.begin());
00232 }
00233 else
00234 {
00235 const win2_iterator f = win2_.begin();
00236 const win2_iterator l = win2_.end();
00237 const win2_iterator r =
00238 std::find(f, l,
00239 make_equal<HT>(win1_.front(),
00240 iterable_->precision_,
00241 iterable_->phy_end_,
00242 iterable_->pcap_tstamps_));
00243
00244 if (r == l)
00245 return boost::none_t ();
00246
00247 return match_type (win1_.begin(), r);
00248 }
00249 }
00250
00251 }
00252
00253 template <class HeaderType,
00254 class InputIterator1,
00255 class InputIterator2,
00256 class Bottom>
00257 windowed_merge<HeaderType, InputIterator1, InputIterator2, Bottom>::
00258 windowed_merge(const InputIterator1& first1, const InputIterator1& last1,
00259 const InputIterator2& first2, const InputIterator2& last2,
00260 const unsigned precision,
00261 const tool::endian::endianness phy_end,
00262 const bool pcap_tstamps):
00263 precision_ (precision),
00264 phy_end_ (phy_end),
00265 pcap_tstamps_ (pcap_tstamps),
00266 first1_ (first1),
00267 last1_ (last1),
00268 first2_ (first2),
00269 last2_ (last2)
00270 {
00271 }
00272
00273 }
00274
00275 }
00276
00277 }
00278
00279 #endif // ! WIFI_FRAME_FILTER_WINDOWED_MERGE_HXX_