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