1 /*
   2  * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
   3  * 
   4  * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
   5  * Virtual Machine, which is developed at Christian Doppler Laboratory on
   6  * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
   7  * contact us at <http://mevss.jku.at/> if you need additional information
   8  * or have any questions.
   9  *
  10  * This code is free software; you can redistribute it and/or modify it
  11  * under the terms of the GNU General Public License version 2 only, as
  12  * published by the Free Software Foundation.
  13  *
  14  * This code is distributed in the hope that it will be useful, but WITHOUT
  15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17  * version 2 for more details (a copy is included in the LICENSE file that
  18  * accompanied this code).
  19  *
  20  * You should have received a copy of the GNU General Public License version
  21  * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
  22  *
  23  */ 
  24 package sun.evtracing.parser.metadata;
  25 
  26 import java.util.Comparator;
  27 import java.util.Iterator;
  28 
  29 import sun.evtracing.parser.metadata.JavaMethod;
  30 import sun.evtracing.parser.metadata.JavaStack;
  31 import sun.evtracing.parser.metadata.JavaStackFrame;
  32 import sun.evtracing.parser.metadata.MethodFilter;
  33 
  34 /**
  35  * Compares stack traces using only method and class names, disregarding class
  36  * loaders and identifiers.
  37  */
  38 public class JavaStackDeepComparator implements Comparator<JavaStack> {
  39 
  40         public static final JavaStackDeepComparator INSTANCE = new JavaStackDeepComparator();
  41 
  42         public static JavaStackDeepComparator forTopMethodOnly(MethodFilter filter) {
  43                 return new JavaStackDeepComparator(filter);
  44         }
  45 
  46         private final boolean topMethodOnly;
  47         private final MethodFilter filter;
  48 
  49         private JavaStackDeepComparator() {
  50                 this.topMethodOnly = false;
  51                 this.filter = null;
  52         }
  53         
  54         private JavaStackDeepComparator(MethodFilter filter) {
  55                 assert (filter != null);
  56                 this.topMethodOnly = true;
  57                 this.filter = filter;
  58         }
  59 
  60         @Override
  61         public int compare(JavaStack o1, JavaStack o2) {
  62                 if (o1 == o2) {
  63                         return 0;
  64                 }
  65                 if (o1.isSet() && !o2.isSet()) {
  66                         return 1;
  67                 }
  68                 if (!o1.isSet() && o2.isSet()) {
  69                         return -1;
  70                 }
  71                 if (!o1.isSet() && !o2.isSet()) {
  72                         return 0;
  73                 }
  74                 if (o1.isUnknown() && o2.isUnknown()) {
  75                         return System.identityHashCode(o1) - System.identityHashCode(o2);
  76                 }
  77                 if (o1.isUnknown() && !o2.isUnknown()) {
  78                         return -1;
  79                 }
  80                 if (!o1.isUnknown() && o2.isUnknown()) {
  81                         return 1;
  82                 }
  83                 if (o1.frameCount() == 0 || o2.frameCount() == 0 || (!topMethodOnly && o1.frameCount() != o2.frameCount())) {
  84                         return (o1.frameCount() - o2.frameCount());
  85                 }
  86                 if (topMethodOnly) {
  87                         JavaMethod m1 = filter.getFirstUnmatched(o1);
  88                         JavaMethod m2 = filter.getFirstUnmatched(o2);
  89                         return JavaMethodDeepComparator.INSTANCE.compare(m1, m2);
  90                 }
  91                 int result;
  92                 Iterator<JavaStackFrame> i1 = o1.iterator();
  93                 Iterator<JavaStackFrame> i2 = o2.iterator();
  94                 do {
  95                         JavaStackFrame f1 = i1.next();
  96                         JavaStackFrame f2 = i2.next();
  97                         result = JavaMethodDeepComparator.INSTANCE.compare(f1.method(), f2.method());
  98                         /*if (result == 0) {
  99                          result = f1.bci() - f2.bci();
 100                          }*/
 101                 } while (result == 0 && i1.hasNext());
 102                 return result;
 103         }
 104 
 105 }