Package com.taobao.top.analysis

Source Code of com.taobao.top.analysis.HttpAgentNode$Callback

package com.taobao.top.analysis;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.taobao.top.analysis.node.IJobManager;
import com.taobao.top.analysis.util.ExtFilenameFilter;
/**
*
* @author zijiang.jl
*
*
* 分布式http节点,提供分析器与外部应用的通道,基于http协议。
*
*
*
* 1.健康检查
*
* http://url/web?command=check
*
*
* 2.运行时内存数据管理
*
*
* http://url/web?command=manage&instance=in&method=mh&entry=en&key=k&value=val
*
*
* method 支持:
* get     获取数据
* put     创建数据
* post    修改数据
* delete  删除数据
*
*
* 3.属性文件和配置文件管理
*
* http://url/web?command=config&instance=in&type=0&method=get
*
* type:
* 0   属性文件
* 1   规则文件
*
* method:
* get 获取文件
* post 推送文件
*
*
*/

public class HttpAgentNode extends Thread {
  private static final Log logger = LogFactory.getLog(HttpAgentNode.class);
  private static final String COMMAND="command";
  private static final String COMMAND_CHECK="check";
  private static final String COMMAND_CONFIG="config";
  private static final String COMMAND_MANAGE="manage";
 
 
  private static final String METHOD="method";
  private static final String TYPE="type";
  private static final String INSTANCE="instance";
  private static final String LEVEL="level";
  private static final String ENTRY="entry";
  private static final String ALLENTRY="a_check_for_all_reference_entry";
  public static final String _DEFAULT_REGISTER_ = "_DEFAULT_RULE_REGISTRY_";
 
 
 
  private IJobManager jobManager;
 

  /**
     * @param jobManager the jobManager to set
     */
    public void setJobManager(IJobManager jobManager) {
        this.jobManager = jobManager;
    }

    private static String ip;
  static {
    try {
      ip = InetAddress.getLocalHost().getHostAddress();
    } catch (UnknownHostException e) {
    }
  }



  interface Callback{
    public void callback(int code,long len) throws IOException;
  }
 

  @Override
  public void run() {
    try {
        Thread.sleep(2000);
        logger.error("jobManager:" + jobManager + ", config:" + jobManager.getConfig());
      HttpServer httpServer = HttpServer.create(
          new InetSocketAddress(jobManager.getConfig().getHttpPort()), 0);
      httpServer.createContext(
          jobManager.getConfig().getHttpContext(),
          new HttpHandler() {
            private AtomicInteger checkCnt=new AtomicInteger(0);
            private AtomicInteger configCnt=new AtomicInteger(0);
            @Override
            public void handle(final HttpExchange arg0)throws IOException {
                try{
                  String qu=arg0.getRequestURI().getQuery();
                  if(qu==null) qu="command=check";
                  java.util.Map<String, String> quMap=new java.util.HashMap<String, String>();
                  StringBuilder sb = new StringBuilder();
                  StringTokenizer st = new StringTokenizer(qu, "&");
                    while (st.hasMoreTokens()) {
                          String pair = st.nextToken();
                          int pos = pair.indexOf('=');
                          if (pos != -1) {
                            String key = parseName(pair.substring(0, pos), sb);
                            String val = parseName(pair.substring(pos+1, pair.length()), sb);
                            quMap.put(key, java.net.URLDecoder.decode(val,"UTF-8"));
                          }
                     }
                   
                  String command=quMap.get(COMMAND);
                 
                  if(command==null||"".equals(command)) command=COMMAND_CHECK;
                 
                  logger.warn("http agent node accept command "+command);
                  java.lang.StringBuilder exetime=new StringBuilder("the command:");
                  exetime.append(command);
                  exetime.append(" execute time:");
                 
                 
                  if(COMMAND_CHECK.equals(command)){
                    long start=System.currentTimeMillis();
                    handleCheck(arg0.getRequestBody(),arg0.getResponseBody(),new Callback(){
                      @Override
                      public void callback(int code,long len) throws IOException{
                        arg0.sendResponseHeaders(code, len);
                       
                      }
                     
                    });
                    long end=System.currentTimeMillis();
                    checkCnt.incrementAndGet();
                    exetime.append(end-start);
                    exetime.append(",execute count:");
                    exetime.append(checkCnt.get());
                    logger.warn(exetime.toString());
                    return;
                  }
                 
                  if(COMMAND_MANAGE.equals(command)){
                                        long start=System.currentTimeMillis();
                                        String method=quMap.get(METHOD);
                                        String level=quMap.get(LEVEL);
                                        String instance=quMap.get(INSTANCE);
                                        String entry=quMap.get(ENTRY);
                                        String key=quMap.get("key");
                                        String value=quMap.get("value");
                                        handleManage(arg0.getRequestBody(),arg0.getResponseBody(),new Callback(){
                                            @Override
                                            public void callback(int code,long len) throws IOException{
                                                arg0.sendResponseHeaders(code, len);
                                               
                                            }
                                           
                                        },method,level,instance,entry,key,value);
                                       
                                        long end=System.currentTimeMillis();
                                        exetime.append(end-start);
                                        exetime.append(",execute count:");
                                        logger.warn(exetime.toString());
                                        return;
                                    }
                 
                  if(COMMAND_CONFIG.equals(command)){
                    long start=System.currentTimeMillis();
                    String instance=quMap.get(INSTANCE);
                    String type=quMap.get(TYPE);
                    String method=quMap.get(METHOD);
                    handleConfig(arg0.getRequestBody(),arg0.getResponseBody(),new Callback(){
                      @Override
                      public void callback(int code,long len) throws IOException{
                        arg0.sendResponseHeaders(code, len);
                       
                      }
                     
                    },type,method,instance);
                    long end=System.currentTimeMillis();
                    configCnt.incrementAndGet();
                    exetime.append(end-start);
                    exetime.append(",execute count:");
                    exetime.append(configCnt.get());
                    logger.warn(exetime.toString());
                    return;
                  }
                 
                  logger.error("http agent node command:"+command+" was not supported");
                 
                }catch(Throwable t){
                  logger.error("http handle error", t);
                }
            }

          });
      httpServer.start();
    } catch (Throwable e) {
      logger.error("nested http server error", e);
    }
  }
 
  /**
     * //未做并发保护,谨慎使用
     * @param arg0
     * @param method
     * @param instance
     * @param entry
     * @param key
     * @param value
     */
    private void handleManage(InputStream is,OutputStream os,Callback callback,String method,String level,String instance,String entry,String key,String value){
        StringBuilder node = new StringBuilder("");
        try {
            if(instance!=null){
                if(jobManager.getJobs().get(instance)!=null){
                    if("get".equals(method)){
                        if(entry!=null){
                            if(jobManager.getJobs().get(instance).getJobResult().get(entry)!=null){
                                if(key!=null){
                                    node.append(jobManager.getJobs().get(instance).getJobResult().get(key));
                                }else{
                                    Map<String, Object> map=jobManager.getJobs().get(instance).getJobResult().get(entry);
                                    java.util.Iterator<String> it=map.keySet().iterator();
                                    while(it.hasNext()){
                                        node.append(it.next());
                                        node.append(",");
                                    }
                                }
                            }else{
                                node.append("not find entry "+entry+" in memory");
                                node.append("\r\n");
                                callback.callback(415,node.toString().getBytes("UTF-8").length);
                                os.write(node.toString().getBytes("UTF-8"));
                                os.flush();
                                os.close();
                                return;
       
                            }
                           
                        }else{
                            java.util.Iterator<String> it=jobManager.getJobs().get(instance).getJobResult().keySet().iterator();
                            node.append(ALLENTRY).append(",");
                            while(it.hasNext()){
                                node.append(it.next());
                                node.append(",");
                            }
                        }
                    } else if("put".equals(method)){
                        if(jobManager.getJobs().get(instance).getJobResult().get(entry)==null) jobManager.getJobs().get(instance).getJobResult().put(entry, new java.util.HashMap<String, Object>());
                        if(key!=null&&value!=null) jobManager.getJobs().get(instance).getJobResult().get(entry).put(key, value);
                    } else if("post".equals(method)){
                        if(entry!=null&&key!=null&&value!=null&&jobManager.getJobs().get(instance).getJobResult().get(entry)!=null) jobManager.getJobs().get(instance).getJobResult().get(entry).put(key, value);
                    }else if("delete".equals(method)){
                        if("1".equals(level)){
                            Map<String, Map<String, Object>> m=jobManager.getJobs().get(instance).getJobResult();
                            if(m!=null) m.clear();
                        }
                        if("2".equals(level)){
                            Map<String, Map<String, Object>> m=jobManager.getJobs().get(instance).getJobResult();
                            if(m!=null){
                                if(ALLENTRY.equals(entry)){
                                    java.util.Iterator<String> it=m.keySet().iterator();
                                    while(it.hasNext()){
                                        String st=it.next();
                                        if(jobManager.getJobs().get(instance).getStatisticsRule().getEntryPool().containsKey(st)) continue;
                                        Map<String, Object> b=m.remove(st);
                                        if(b!=null) b.clear();
                                    }  
                                }else{
                                    Map<String, Object> b=m.remove(entry);
                                    if(b!=null) b.clear();
                                }
                            }
                        }
                       
                        if("3".equals(level)){
                            Map<String, Map<String, Object>> m=jobManager.getJobs().get(instance).getJobResult();
                            if(m!=null){
                                Map<String, Object> b=m.get(entry);
                                if(b!=null) b.remove(key);
                            }
                        }
                    }else{
                        node.append("not support!method error");
                        node.append("\r\n");
                        callback.callback(415,node.toString().getBytes("UTF-8").length);
                        os.write(node.toString().getBytes("UTF-8"));
                        os.flush();
                        os.close();
                        return;
                    }
                }else{
                    node.append("not find instance "+instance+" in memory");
                    node.append("\r\n");
                    callback.callback(415,node.toString().getBytes("UTF-8").length);
                    os.write(node.toString().getBytes("UTF-8"));
                    os.flush();
                    os.close();
                    return;
                }
            }else{
                if(jobManager != null && jobManager.getConfig() != null){
                    java.util.Iterator<String> in=jobManager.getJobs().keySet().iterator();
                    while(in.hasNext()){
                        node.append(in.next());
                        node.append(",");
                    }
                }else{
                    node.append(_DEFAULT_REGISTER_);
                }

            }
       
            callback.callback(HttpServletResponse.SC_OK,node.toString().getBytes("UTF-8").length);
            os.write(node.toString().getBytes("UTF-8"));
            os.flush();
            os.close();
        } catch (IOException e) {
            try {
                if(os!=null) os.close();
            } catch (IOException ex) {
                logger.error(ex.getMessage(), ex);
            }
            logger.error(e.getMessage(), e);
        }
    }
 
  /**
   *
   * @param arg0
   */
  private void handleCheck(InputStream is,OutputStream os,Callback callback){
    StringBuilder node = new StringBuilder("");
    Set<String> ins = jobManager.getJobs().keySet();
    String in;
    java.util.Iterator<String> its = ins
        .iterator();
    while (its.hasNext()) {
      in = its.next();
      node.append(in);
      node.append(":");
      node.append("success");

      node.append(":");
      node.append("0");
      node.append("\r\n");
    }
   
    try {
      callback.callback(HttpServletResponse.SC_OK,node.toString().getBytes("UTF-8").length);
      os.write(node.toString().getBytes("UTF-8"));
      os.flush();
      os.close();
    } catch (IOException e) {
      try {
        if(os!=null) os.close();
      } catch (IOException ex) {
        logger.error(ex.getMessage(), ex);
      }
      logger.error(e.getMessage(), e);
     
    }
  }
 
   
  /**
   *
   *
   * sendResponseHeaders  这方法存在重复设置的问题。但一般情况下不会出现。
   *
   *
   * @param arg0
   * @param type
   * @param method
   * @param instance
   */
  private void handleConfig(InputStream is,OutputStream os,Callback callback,String type,String method,String instance){

    java.io.DataInputStream dis=new java.io.DataInputStream(new BufferedInputStream(is));
    java.io.DataOutputStream dos=new java.io.DataOutputStream(new BufferedOutputStream(os));
    FileInputStream fis=null;
    FileOutputStream fos=null;
    try{
      if(instance!=null&&this.jobManager.getJobs().get(instance)!=null){
        //属性文件
        if("0".equals(type)){
          if("get".equals(method)){
            File file=new File(this.jobManager.getConfig().getConfigFile());
            byte[] fd=file.getAbsolutePath().getBytes("UTF-8");
            if(file.exists()){
              fis=new java.io.FileInputStream(file);
              callback.callback(HttpServletResponse.SC_OK,4+4+fd.length+4+fis.available());
              dos.writeInt(1);
              dos.writeInt(fd.length);
              dos.write(fd);
              dos.writeInt(fis.available());
              byte[] buf=new byte[1024];
              int pos=-1;
              while((pos=fis.read(buf))!=-1){
                dos.write(buf, 0, pos);
                dos.flush();
              }
              fis.close();
              dos.close();
            }else{
              callback.callback(415,0);
              dos.write("property not exist".getBytes("UTF-8"));
              dos.flush();
              dos.close();
            }
          }
         
          if("post".equals(method)){
            int flen=dis.readInt();
            byte[] fb=new byte[flen];
            dis.read(fb);
            String fName=new String(fb,"UTF-8");
            boolean load=false;
            if(fName.endsWith(this.jobManager.getConfig().getConfigFile())) load=true;
            if(load){
              //临时文件输出
              File temp=new File(this.jobManager.getConfig().getConfigFile()+".temp");
              if(temp.exists()) temp.delete();
              fos=new FileOutputStream(temp);
             
              int a=-1;
              byte[] buf=new byte[1024];
              while((a=dis.read(buf))!=-1){
                fos.write(buf, 0, a);
                fos.flush();
               
              }
              dis.close();
              fos.close();
              File file=new File(this.jobManager.getConfig().getConfigFile());
              File bak=new File(this.jobManager.getConfig().getConfigFile()+".bak");
              if(bak.exists()) bak.delete();
              if(file.exists()){
                file.renameTo(bak);
              }
              temp.renameTo(file);
              callback.callback(HttpServletResponse.SC_OK,0);
              dos.flush();
              dos.close();
            }else{
              callback.callback(415,0);
              dos.write("file can't loaded".getBytes("UTF-8"));
              dos.flush();
              dos.close();
            }

          }
          return;
        }
       
       
        //XML文件,只能修改本地文件
        if("1".equals(type)){
          if(jobManager != null && jobManager.getConfig() != null){
            if("get".equals(method)){
              String[] configFiles=jobManager.getJobs().get(instance).getJobConfig().getReportConfigs();
              FileAttr files=new FileAttr();
              for (String config : configFiles) {
                String temp=config.substring(config.indexOf(":")+1);
                File cfg=new File(temp);
                listFile(files,cfg);
              }
              callback.callback(HttpServletResponse.SC_OK,4+8*files.size()+files.getFileLen()+files.getFnLen());
              dos.writeInt(files.size());
              for(int i=0;i<files.size();i++){
                dos.writeInt(files.getFileName().get(i).length);
                dos.write(files.getFileName().get(i));
                dos.writeInt(files.getFisList().get(i).available());
                byte[] buf=new byte[1024];
                int pos=-1;
                while((pos=files.getFisList().get(i).read(buf))!=-1){
                  dos.write(buf, 0, pos);
                  dos.flush();
                }
                files.getFisList().get(i).close();
              }
              dos.close()
            }
           
           
            if("post".equals(method)){
              String[] configFiles=jobManager.getJobs().get(instance).getJobConfig().getReportConfigs();
              java.util.List<String> dirs=new java.util.ArrayList<String>();
              for (String config : configFiles) {
                String temp=config.substring(config.indexOf(":")+1);
                File cfg=new File(temp);
                if(cfg.isDirectory()){
                  dirs.add(cfg.getAbsolutePath());
                }
              }
             
              int flen=dis.readInt();
              byte[] fb=new byte[flen];
              dis.read(fb);
              String fname=new String(fb,"UTF-8");
             
              //对于上传的文件需要判断能否被分析器加载。
              boolean load=false;
              for(String dir:dirs){
                if(fname.startsWith(dir)) load=true;
              }
              if(load){
               
                File temp=new File(fname+".temp");
                if(temp.exists()) temp.delete();
                fos=new FileOutputStream(temp);
                int a=-1;
                byte[] buf=new byte[1024];
                while((a=dis.read(buf))!=-1){
                  fos.write(buf, 0, a);
                  fos.flush();
                 
                }
                dis.close();
                fos.close();

                File file=new File(fname);
                File bak=new File(fname+".bak");
               
                if(bak.exists()) bak.delete();
                if(file.exists()) {
                  file.renameTo(bak);
                }
                temp.renameTo(file);
                callback.callback(HttpServletResponse.SC_OK,0);
                dos.flush();
                dos.close();
              }else{
                callback.callback(415,0);
                dos.write("file can't loaded".getBytes("UTF-8"));
                dos.flush();
                dos.close();
              }
            }
           
            return;
          }else{
            callback.callback(415,0);
            dos.write("slave can't find xml file".getBytes("UTF-8"));
            dos.flush();
            dos.close();
          }

        }
       
        callback.callback(415,0);
        dos.write("parameter error".getBytes("UTF-8"));
        dos.flush();
        dos.close();
      }else{
        callback.callback(415,0);
        dos.write("Can't find instance:".getBytes("UTF-8"));
        dos.write(instance.getBytes("UTF-8"));
        dos.flush();
        dos.close();
     
    }catch(Throwable t){
      try {
        callback.callback(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,0);
        dos.flush();
        dos.close();
      } catch (IOException e) {
        logger.error(e.getMessage(), e);
       
      }
    }finally{
      try {
        if(fis!=null) fis.close();
        if(fos!=null) fos.close();
        if(dis!=null) dis.close();
        if(dos!=null) dos.close();
      } catch (IOException e) {
        logger.error(e.getMessage(), e);
       
      }
    }
  }
   
  private static class FileAttr{
    private java.util.List<FileInputStream> fis=new java.util.ArrayList<FileInputStream>();
    private java.util.List<byte[]> fileName=new java.util.ArrayList<byte[]>();
   
    private int fileLen;
    private int fnLen;
   
 
   
    public int size(){
      if(fis.size()==fileName.size()) return fis.size();
      throw new java.lang.RuntimeException("the size is wrong");
    }
   
    public final java.util.List<byte[]> getFileName() {
      return fileName;
    }
    public final void addFileName(byte[] fileName) {
      this.fileName.add(fileName);
    }
   
    public final java.util.List<FileInputStream> getFisList() {
      return fis;
    }
    public final void addFileInputStream(java.io.FileInputStream is) {
      fis.add(is);
    }
   
    public final void removeFileInputStream(java.io.FileInputStream is) {
      fis.remove(is);
    }
   
    public final int getFileLen() {
      return fileLen;
    }
    public final void addFileLen(int fileLen) {
      this.fileLen+=fileLen;
    }
    public final int getFnLen() {
      return fnLen;
    }
    public final void addFnLen(int fnLen) {
      this.fnLen += fnLen;
    }
   
   
   
   
  }
 
  /**
   * 递归枚举所有的文件
   * @param files
   * @param file
   */
  public static void listFile(FileAttr files,File file){
    if(file.isFile()) {
      java.io.FileInputStream fs=null;
      boolean flag=false;
      try {
        fs = new java.io.FileInputStream(file);
        flag=true;
        files.addFileInputStream(fs);
        files.addFileLen(fs.available());
        byte[] a=file.getAbsolutePath().getBytes("UTF-8");
        files.addFileName(a);
        files.addFnLen(a.length);
      } catch (Exception e) {
        if(flag&&fs!=null) files.removeFileInputStream(fs);
      }
      return;
    }
    if(file.isDirectory()){
      File[] temps = file.listFiles(new ExtFilenameFilter(".xml"));
      for(File f:temps){
        listFile(files, f);
      }
    }
  }
 
  /**
   * 解析字符或者编码后的字符
   * @param s
   * @param sb
   * @return
   */
    private String parseName(String s, StringBuilder sb) {
        sb.setLength(0);
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
            case '+':
                sb.append(' ');
                break;
            case '%':
                try {
                    sb.append((char) Integer.parseInt(s.substring(i+1, i+3),
                                                      16));
                    i += 2;
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException();
                } catch (StringIndexOutOfBoundsException e) {
                    String rest  = s.substring(i);
                    sb.append(rest);
                    if (rest.length()==2)
                        i++;
                }
               
                break;
            default:
                sb.append(c);
                break;
            }
        }
        return sb.toString();
    }
}
TOP

Related Classes of com.taobao.top.analysis.HttpAgentNode$Callback

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.