package cn.edu.sjtu.omnilab.syslogcleanser.ppefilter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; public class PPDetector2 { public PPDetector2(){} public static List<APRecord> removePingPong ( List<String> tmp_ap_list, List<Long> tmp_start_times, List<Long> tmp_durations, List<Boolean> tmp_flags) /* * @Param: tmp_ap_list: sequence of APs with potential ping-pong * @Param: tmp_start_times: sequence of AP session starting time aligned to AP list * @Param: tmp_durations: sequence of AP durations aligned to AP list * @Param: tmp_flags: sequence of AP flags that indicate to accumulate the AP duration or not. */ { List<String> ap_list = tmp_ap_list; List<Long> ap_start_time_list = tmp_start_times; List<Long> ap_duration_list = tmp_durations; List<Boolean> ap_flag_list = tmp_flags; int ap_count = ap_duration_list.size(); if ( DebugFlag.debug ){ System.out.println("\nPing-pong len: " + ap_count); for (int i=0; i<ap_count; i++) { System.out.println(ap_list.get(i)+"\t"+ap_duration_list.get(i)+"\t"+ap_flag_list.get(i)); } } List<APRecord> filtered_records = new ArrayList<APRecord>(); List<PPPair> pp_pairs_list = new ArrayList<PPPair>(); if ( ap_count >= 3) { // Only sequence of longer than 3 are processed... // Step 1: find ping-pong pairs of AP sequence for ( int i = 0; i< ap_count; i++) { for ( int j = i+1; j< ap_count; j++) { if ( ap_list.get(j).equals(ap_list.get(i))) { if ( j-i < 4) { pp_pairs_list.add(new PPPair(i, j-i)); } break; } else if ( j-i >= 4) { break; } } } if (DebugFlag.debug) { System.out.println("\nPing-pong pairs:"); for ( PPPair pair : pp_pairs_list){ System.out.println(pair.offset+","+(pair.offset+pair.distance)+" "); } } // Step 2: merge several ping-pong pairs into ping-pong segment /* * For AP pair set {Pi | i > 0}, we define a valid ping-pong segment as: * for any AP pair Pi, there is at least one Pj to make c(Pi, Pj) > 0, where * c(.) is the function to calculate the coverage of two AP pairs. * Here we define c(.) as dist(i) - |offset(i) - offset(j)| where i < j; */ List<List<PPPair>> pp_segment_list = new ArrayList<List<PPPair>>(); for ( PPPair candPair : pp_pairs_list){ boolean found = false; for ( List<PPPair> pp_segment : pp_segment_list) { for ( PPPair pp_pair: pp_segment ) { if ( candPair.coverage(pp_pair) > 0) { found = true; break; } } if ( found == true) { pp_segment.add(candPair); break; } } if ( found == false) { List<PPPair> new_segment = new ArrayList<PPPair>(); new_segment.add(candPair); pp_segment_list.add(new_segment); } } // Step 3: construct new AP sequence from ping-pong segments List<PPPair> ppps = new ArrayList<PPPair>(); for ( List<PPPair> segment : pp_segment_list){ int new_head = ap_count+1; int new_tail = 0; for ( PPPair ppp : segment ) { new_head = (ppp.offset < new_head) ? ppp.offset : new_head; new_tail = ppp.offset+ppp.distance > new_tail ? ppp.offset+ppp.distance : new_tail; } ppps.add(new PPPair(new_head, new_tail-new_head)); } if (DebugFlag.debug) { System.out.println("\nMerged ping-pong segments:"); for ( PPPair pair : ppps){ System.out.println(pair.offset+","+(pair.offset+pair.distance)+" "); } } for ( PPPair pair : ppps ){ String fap_name = ""; //**************************************** // To generate final AP name as concatenating // all present APs Set<String> fap_name_set = new HashSet<String>(); //**************************************** //**************************************** // To generate final AP name as the AP with // longest duration // Map<String, Long> fap_name_map = new HashMap(); //**************************************** // start time long fap_start_time = -1; // duration long fap_duration = 0; for ( int i = pair.offset; i<=pair.offset + pair.distance; i++) { // NOTE: we accumulate the durations from start to stop and without the // stop, to avoid the repeated addition of the item when two segments // have the covered number (==1) String ap_name = ap_list.get(i); boolean ap_flag = ap_flag_list.get(i); long ap_start_time = ap_start_time_list.get(i); long ap_duration = ap_duration_list.get(i); //**************************************** // To generate final AP name as concatenating // all present APs fap_name_set.add(ap_name); //**************************************** //**************************************** // To generate final AP name as the AP with // longest duration. // Accumulate duration time for each AP // if ( fap_name_map.containsKey(ap_name) ){ // fap_name_map.put(ap_name, fap_name_map.get(ap_name) + ap_duration); // } else { // fap_name_map.put(ap_name, ap_duration); // } //**************************************** // Update Ping-ping start time if ( fap_start_time == -1 && ap_flag == true ) fap_start_time = ap_start_time; // Update flags if ( ap_flag == true){ fap_duration += ap_duration; ap_flag_list.set(i, false); } } //**************************************** // To generate final AP name as concatenating // all present APs for ( String s : fap_name_set) { if ( fap_name.equals("")) fap_name += s; else fap_name += (","+s); } //**************************************** //**************************************** // To generate final AP name as the AP with // longest duration. // Accumulate duration time for each AP // long longest_duration = -1; // for ( String ap : fap_name_map.keySet()) { // if ( fap_name_map.get(ap) >= longest_duration ){ // fap_name = ap; // longest_duration = fap_name_map.get(ap); // } // } //**************************************** // Add this new record filtered_records.add(new APRecord(fap_name, fap_start_time, fap_duration)); if (DebugFlag.debug){ System.out.println("Merged result:"); System.out.println(fap_name+"\t"+fap_start_time+"\t"+fap_duration); } } } // Add the left records which are not contained by the ping-pong segments for ( int j=0; j<ap_flag_list.size(); j++) if ( ap_flag_list.get(j) == true) filtered_records.add(new APRecord(ap_list.get(j), ap_start_time_list.get(j), ap_duration_list.get(j))); // Order the records by start_time Collections.sort(filtered_records,new Comparator<APRecord>(){ public int compare(APRecord arg0, APRecord arg1) { return new Long(arg0.start_time).compareTo(new Long(arg1.start_time)); } }); return filtered_records; } }