00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_TRACES_EXTENDED_MERGE_HXX_
00023 # define WIFI_TRACES_EXTENDED_MERGE_HXX_
00024
00025 # include "extended_merge.hxx"
00026
00027 # include <set>
00028 # include <map>
00029 # include <utility>
00030 # include <iostream>
00031
00032 # include <boost/lexical_cast.hpp>
00033 # include <boost/tuple/tuple.hpp>
00034 # include <boost/tuple/tuple_comparison.hpp>
00035
00036 # include <wipal/pcap/stream.hh>
00037 # include <wipal/wifi/traces/merge.hh>
00038 # include <wipal/wifi/traces/similarity.hh>
00039
00040 namespace wpl
00041 {
00042
00043 namespace wifi
00044 {
00045
00046 namespace merge_helpers
00047 {
00048
00049 template <class Iterator>
00050 struct extended_merge_state
00051 {
00052 typedef std::map<Iterator, std::string> parent_map;
00053
00054 extended_merge_state(opt::list& options): options_ (options),
00055 merge_count_ (0)
00056 {
00057 typedef std::set< std::pair<unsigned, unsigned> > blist_type;
00058
00059 if (not options_.count("ref_blacklist"))
00060 options_.add("ref_blacklist", blist_type ());
00061 }
00062
00063 parent_map&
00064 pmap()
00065 {
00066 return pmap_;
00067 }
00068
00069 const parent_map&
00070 pmap() const
00071 {
00072 return pmap_;
00073 }
00074
00075 std::string
00076 output() const
00077 {
00078 return "merge-" + boost::lexical_cast<std::string>(merge_count_);
00079 }
00080
00081 void
00082 update_parent(const std::string& parent_name)
00083 {
00084 const std::string& o = output();
00085
00086 BOOST_FOREACH(typename parent_map::value_type& p, pmap_)
00087 if (p.second == parent_name)
00088 p.second = o;
00089 }
00090
00091 template <class U, class P,
00092 template <class, class, class> class I,
00093 template <class, class, class, class> class M,
00094 class T1, class T2>
00095 void
00096 merge(T1& lhs, T2& rhs)
00097 {
00098 ++merge_count_;
00099
00100 const std::string out_name = output();
00101
00102 # ifdef WP_ENABLE_INFO
00103 std::cerr << "INFO: Begining a new merge operation.\n"
00104 << "INFO: Trace 1 is " << lhs << ".\n"
00105 << "INFO: Trace 2 is " << rhs << ".\n"
00106 << "INFO: Output is " << out_name << "." << std::endl;
00107 # endif // WP_ENABLE_INFO
00108
00109
00110
00111
00112 wifi::merge<U, P, I, M>(lhs, rhs, out_name, options_);
00113 }
00114
00115 private:
00116 opt::list options_;
00117 unsigned merge_count_;
00118 parent_map pmap_;
00119 };
00120
00121 }
00122
00123 template <class U, class P,
00124 template <class, class, class> class I,
00125 template <class, class, class, class> class M,
00126 class C>
00127 std::string
00128 merge(C& traces, opt::list& options)
00129 {
00130 typedef typename C::iterator iterator;
00131 typedef merge_helpers::extended_merge_state<iterator> state;
00132 typedef typename state::parent_map parent_map;
00133 typedef boost::tuple<unsigned, iterator, iterator> score;
00134 typedef std::set<score> score_set;
00135
00136 state st (options);
00137 parent_map& pm = st.pmap();
00138 score_set ss = similarity<U, P, I>(traces, options);
00139
00140 for (typename score_set::reverse_iterator i = ss.rbegin();
00141 i != ss.rend();
00142 ++i)
00143 {
00144 iterator t1 = boost::get<1>(*i);
00145 iterator t2 = boost::get<2>(*i);
00146
00147 typename parent_map::iterator t1_parent = pm.find(t1);
00148 typename parent_map::iterator t2_parent = pm.find(t2);
00149
00150 if (t1_parent != pm.end())
00151 {
00152 if (t2_parent != pm.end())
00153 {
00154 const std::string t1_trace_name = t1_parent->second;
00155 const std::string t2_trace_name = t2_parent->second;
00156
00157 if (t1_trace_name == t2_trace_name)
00158 continue;
00159
00160 pcap::file<> t1_trace (t1_trace_name);
00161 pcap::file<> t2_trace (t2_trace_name);
00162
00163 if (t1_trace.filesize() < t2_trace.filesize())
00164 st.merge<U, P, I, M>(t1_trace, t2_trace);
00165 else
00166 st.merge<U, P, I, M>(t2_trace, t1_trace);
00167 st.update_parent(t1_trace_name);
00168 st.update_parent(t2_trace_name);
00169 }
00170 else
00171 {
00172 const std::string t1_trace_name = t1_parent->second;
00173 pcap::file<> t1_trace (t1_trace_name);
00174
00175 st.merge<U, P, I, M>(*t2, t1_trace);
00176 st.update_parent(t1_trace_name);
00177 pm[t2] = st.output();
00178 }
00179 }
00180 else
00181 {
00182 if (t2_parent != pm.end())
00183 {
00184 const std::string t2_trace_name = t2_parent->second;
00185 pcap::file<> t2_trace (t2_trace_name);
00186
00187 st.merge<U, P, I, M>(*t1, t2_trace);
00188 pm[t1] = st.output();
00189 st.update_parent(t2_trace_name);
00190 }
00191 else
00192 {
00193 st.merge<U, P, I, M>(*t1, *t2);
00194 pm[t1] = st.output();
00195 pm[t2] = st.output();
00196 }
00197 }
00198 }
00199
00200 return st.output();
00201 }
00202
00203 }
00204
00205 }
00206
00207 #endif // ! WIFI_TRACES_EXTENDED_MERGE_HXX_