Package nginx.clojure.wave

Source Code of nginx.clojure.wave.SuspendMethodVerifier$VerifyMethodInfo

package nginx.clojure.wave;

import java.lang.reflect.Method;
import java.util.ArrayList;

import nginx.clojure.Stack;
import nginx.clojure.asm.Type;
import nginx.clojure.wave.MethodDatabase.ClassEntry;
import nginx.clojure.wave.SuspendMethodTracer.MethodInfo;

public class SuspendMethodVerifier {
 
  public static class VerifyVarInfo implements Cloneable {
    public int idx = -1;
    public int dataIdx = -1;
    public String name;
    public Object value;
   
    public VerifyVarInfo clone()  {
      try {
        return (VerifyVarInfo) super.clone();
      } catch (CloneNotSupportedException e) {
        e.printStackTrace();
      }
      return null;
    }
  }
 
  public static class VerifyMethodInfo extends MethodInfo {
   
    public int idx = -1;
    public VerifyVarInfo[] vars;
    public String classAndMethod;
   
    public VerifyMethodInfo(String owner, String method) {
      super(owner, method);
      classAndMethod = owner + "." + method;
    }
  }
 
  public static class VerifyInfo {
    public long vid;
    public boolean quite = false;
    public boolean exception = false;
    public ArrayList<VerifyMethodInfo> tracerStacks = new ArrayList<SuspendMethodVerifier.VerifyMethodInfo>();
    public VerifyMethodInfo[] methodIdxInfos = new VerifyMethodInfo[8];
//    private long id;
  }

 
  protected static MethodDatabase db;
 
 
  public SuspendMethodVerifier() {
  }
 
  public static void onYield() {

    VerifyInfo vi = Stack.getVerifyInfo();
    if (vi == null) {
      return;
    }
   
    vi.quite = true;
    try {
      ArrayList<VerifyMethodInfo> stack = vi.tracerStacks;
      MethodInfo cmi = stack.get(stack.size() -1);
      if (db.meetTraceTargetClassMethod(cmi.owner, cmi.method)) {
        db.info("#%d onYield %s.%s", vi.vid , cmi.owner, cmi.method);
      }
     
      for (int i = stack.size() - 1; i > -1;  i--) {
        MethodInfo mi = stack.get(i);
        if (mi.suspendType != -1 || ("nginx/clojure/Coroutine".equals(mi.owner) && "resume()V".equals(mi.method))) {
          break;
        }
       
        ClassEntry ce = db.getClasses().get(mi.owner);
       
        if (ce == null) {
          vi.exception = true;
          db.error(new RuntimeException(String.format("#%d onYield: can not found ClassEntry for %s", vi.vid, mi.owner)));
          return;
        }
       
        if (!ce.isAlreadyInstrumented()) {
          vi.exception = true;
          db.error(new RuntimeException(String.format("#%d onYield: %s is not AlreadyInstrumented!", vi.vid, mi.owner)));
          return;
        }
       
//        boolean meetTraced = db.meetTraceTargetClassMethod(mi.owner, mi.method);
        Integer knownType = db.checkMethodSuspendType(mi.owner, mi.method, false, true);
       
       
        if (knownType == null || knownType < MethodDatabase.SUSPEND_NORMAL) {
          mi.suspendType = knownType == null ? MethodDatabase.SUSPEND_NONE : knownType;
//          db.warn("meet type %s != SUSPEND_NORMAL from %s.%s", MethodDatabase.SUSPEND_TYPE_STRS[knownType], mi.owner, mi.method);
          vi.exception = true;
          db.error( new RuntimeException(String.format("#%d onYield: meet type %s != SUSPEND_NORMAL from %s.%s", vi.vid,  MethodDatabase.SUSPEND_TYPE_STRS[knownType], mi.owner, mi.method) ));
        }else if (knownType > MethodDatabase.SUSPEND_NORMAL) {
          mi.suspendType = knownType;
//          if (meetTraced) {
//            db.info("meet traced method %s.%s, known suspend type=%s", mi.owner, mi.method, MethodDatabase.SUSPEND_TYPE_STRS[knownType]);
//          }
          //we need not record those records which has been defined by predefined configuration files
          db.warn("#%d onYield: meet predefined type %s != SUSPEND_NORMAL from %s.%s", vi.vid, MethodDatabase.SUSPEND_TYPE_STRS[knownType], mi.owner, mi.method);
          continue;
        }else {
          mi.suspendType = MethodDatabase.SUSPEND_NORMAL;
//          if (meetTraced) {
//            db.info("meet traced method %s.%s, set unknown suspend type to =%s", mi.owner, mi.method, MethodDatabase.SUSPEND_TYPE_STRS[knownType]);
//          }
        }
      }
    }finally {
      vi.quite = false;
    }
   
   
  }
 
  public static void enter(String owner, String method) {
   
    VerifyInfo vi = Stack.getVerifyInfo();
    if (vi == null) {
      return;
    }
    if (vi.quite || vi.exception) {
      return;
    }
    vi.quite = true;
    ArrayList<VerifyMethodInfo> stack = vi.tracerStacks;
    try {
      if (db.meetTraceTargetClassMethod(owner, method)) {
        db.info("#%d enter %s.%s", vi.vid , owner, method);
      }
      stack.add(new VerifyMethodInfo(owner, method));
    }finally{
      vi.quite = false;
    }
  }
 
  public static void downProxyInvoke(Method m) {

    VerifyInfo vi = Stack.getVerifyInfo();
    if (vi == null) {
      return;
    }
   
    if (vi.quite || vi.exception) {
      return;
    }
    enter(Type.getInternalName(m.getDeclaringClass()), m.getName()+Type.getMethodDescriptor(m));
  }
 
  public static void upProxyInvoke(Method m) {
    VerifyInfo vi = Stack.getVerifyInfo();
    if (vi == null) {
      return;
    }
   
    if (vi.quite || vi.exception) {
      return;
    }
    leave(Type.getInternalName(m.getDeclaringClass()), m.getName()+Type.getMethodDescriptor(m));
  }
 
  public static void leave(String owner, String method) {
    VerifyInfo vi = Stack.getVerifyInfo();
    if (vi == null) {
      return;
    }
    if (vi.quite || vi.exception) {
      return;
    }
    vi.quite = true;
   
    ArrayList<VerifyMethodInfo> stack = vi.tracerStacks;
    try{
      if (db.meetTraceTargetClassMethod(owner, method)) {
        db.info("#%d leave %s.%s", vi.vid , owner, method);
      }
      MethodInfo mi = stack.get(stack.size() - 1);
      if (!mi.owner.equals(owner) || !mi.method.equals(method)) {
        vi.exception = true;
        db.error(new RuntimeException(String.format("#%d Thread #%d, leave != enter %s.%s != %s.%s", vi.vid, Thread
            .currentThread().getId(), owner, method, mi.owner,
            mi.method)));
        return;
      }else {
        stack.remove(stack.size() - 1);
      }
    }finally{
      vi.quite = false;
    }
  }

}
TOP

Related Classes of nginx.clojure.wave.SuspendMethodVerifier$VerifyMethodInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.