content: /*
   *  Copyright Beijing 58 Information Technology Co.,Ltd.
   *
   *  Licensed to the Apache Software Foundation (ASF) under one
   *  or more contributor license agreements.  See the NOTICE file
   *  distributed with this work for additional information
   *  regarding copyright ownership.  The ASF licenses this file
   *  to you under the Apache License, Version 2.0 (the
   *  "License"); you may not use this file except in compliance
   *  with the License.  You may obtain a copy of the License at
   *
   *        http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing,
   *  software distributed under the License is distributed on an
   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   *  KIND, either express or implied.  See the License for the
   *  specific language governing permissions and limitations
   *  under the License.
   */
  package com.bj58.spat.gaea.server.performance.commandhelper;
  
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.jboss.netty.buffer.ChannelBuffers;
  import org.jboss.netty.channel.Channel;
  import org.jboss.netty.channel.MessageEvent;
  
  import com.bj58.spat.gaea.server.contract.context.GaeaContext;
  import com.bj58.spat.gaea.server.contract.context.StopWatch;
  import com.bj58.spat.gaea.server.performance.Command;
  import com.bj58.spat.gaea.server.performance.CommandType;
  import com.bj58.spat.gaea.server.performance.MonitorCenter;
  import com.bj58.spat.gaea.server.performance.MonitorChannel;
  import com.bj58.spat.gaea.server.performance.ShowColumn;
  
  /**
   * 
   * @author Service Platform Architecture Team (spat@58.com)
   */
  public class Time extends CommandHelperBase {
  	
  	private static List<MonitorChannel> taskList = new ArrayList<MonitorChannel>();
  
  	@Override
  	public Command createCommand(String commandStr) {
  		if(commandStr != null && !commandStr.equalsIgnoreCase("")) {
  			String[] args = commandStr.split("\\|");
  			if(args[0].trim().equalsIgnoreCase("time")) {
  				List<String> grepList = new ArrayList<String>();
  				List<ShowColumn> scList = new ArrayList<ShowColumn>();
  				
  				Command entity = new Command();
  				scList.add(ShowColumn.All);
  				entity.setCommandType(CommandType.Time);
  				
  				for(int i=1; i<args.length; i++) {
  					if(args[i].trim().startsWith("grep")) {
  						grepList.add(args[i].trim().replaceFirst("grep ", "").trim());
  					} else if(args[i].trim().startsWith("group")) {
  						entity.setGroup(Integer.parseInt(args[i].trim().replaceFirst("group ", "").trim()));
  					} else if(args[i].trim().startsWith("column")) {
  						scList.clear();
  						String cs = args[i].trim().replaceFirst("column -", "");
  						if(cs.indexOf("a") >= 0) {
  							if(!scList.contains(ShowColumn.All)) {
  								scList.add(ShowColumn.All);
  							}
  						} else {
  							String[] csAry = cs.split("");
  							for(String item : csAry) {
  								if(item.equalsIgnoreCase("t")) {
  									if(!scList.contains(ShowColumn.Time)) {
  										scList.add(ShowColumn.Time);
  									}
  								} else if(item.equalsIgnoreCase("k")) {
  									if(!scList.contains(ShowColumn.Key)) {
  										scList.add(ShowColumn.Key);
  									}
  								} else if(item.equalsIgnoreCase("d")) {
  									if(!scList.contains(ShowColumn.Description)) {
  										scList.add(ShowColumn.Description);
  									}
  								}
  							}
  						}
  					}
  				}
  				entity.setGrep(grepList);
  				entity.setColumnList(scList);
  				return entity;
  			}
  		}
  		return null;
  	}
  	
  	
  	@SuppressWarnings("rawtypes")
  	@Override
  	public void messageReceived(GaeaContext context) {
  		if(taskList.size() <= 0) {
  			return;
  		}
  		
  		StopWatch sw = context.getStopWatch();
  		if (sw != null) {
  			Map<String, StopWatch.PerformanceCounter> mapCounter = sw.getMapCounter();
  			Iterator itSW = mapCounter.entrySet().iterator();
  			while (itSW.hasNext()) {
  				Map.Entry entrySW = (Map.Entry) itSW.next();
  				StopWatch.PerformanceCounter pc = (StopWatch.PerformanceCounter) entrySW.getValue();
  				
  				StringBuilder sbAllMsg = new StringBuilder();
  				sbAllMsg.append("time:");
  				sbAllMsg.append(pc.getEndTime() - pc.getStartTime());
  				sbAllMsg.append("ms--key:");
  				sbAllMsg.append(pc.getKey());
  				sbAllMsg.append("--description:");
  				sbAllMsg.append(pc.getDescription());
  				
  				
  				try {
  					String allMsg = sbAllMsg.toString();
  					for (MonitorChannel mc : taskList) {
  						boolean match = false;
  						for(String key : mc.getCommand().getGrep()) {
  							if (allMsg.indexOf(key) >= 0) {
  								match = true;
  							}
  						}
  						if (match) {
  							sendMsg(mc, pc, sbAllMsg);
  						}
  					}
  				} catch (UnsupportedEncodingException e) {
  					logger.error("send monitor data", e);
  				}
  			}
  		}
  	}
  	
  	
  	@Override
  	public void execCommand(Command command, MessageEvent event) throws Exception {
  		if(command.getCommandType() == CommandType.Time) {
  			MonitorCenter.addFilter(); // add filter
  			logger.info("add time monitor channel:" + event.getChannel().getRemoteAddress());
  			for(int i=0; i<taskList.size(); i++) {
  				if(taskList.get(i).getChannel().equals(event.getChannel()) || !taskList.get(i).getChannel().isOpen()) {
  					taskList.remove(i);
  				}
  			}
  			taskList.add(new MonitorChannel(command, event.getChannel(), event.getChannel().getRemoteAddress()));
  		}
  	}
  	
  	@Override
  	public void removeChannel(Command command, Channel channel) {
  		if(command.getCommandType() != CommandType.Time) {
  			for(int i=0; i<taskList.size(); i++) {
  				if(taskList.get(i).getChannel().equals(channel) || !taskList.get(i).getChannel().isOpen()) {
  					taskList.remove(i);
  				}
  			}
  		}
  	}
  	
  	@Override
  	public int getChannelCount() {
  		for(int i=0; i<taskList.size(); i++) {
  			if(!taskList.get(i).getChannel().isOpen()) {
  				taskList.remove(i);
  			}
  		}
  		return taskList.size();
  	}
  	
  	
  	
  	/**
  	 * 
  	 * @param mc
  	 * @param pc
  	 * @param sbAllMsg
  	 * @throws UnsupportedEncodingException
  	 */
  	private void sendMsg(MonitorChannel mc, StopWatch.PerformanceCounter pc, StringBuilder sbAllMsg) throws UnsupportedEncodingException{
  		if(mc.getCommand().getGroup() > 0) {
  			if(mc.getConvergeCount() < mc.getCommand().getGroup()) {
  				mc.setConvergeCount(mc.getConvergeCount() + 1);
  				mc.setConvergeTime(mc.getConvergeTime() + (pc.getEndTime() - pc.getStartTime()));
  			} else {
  				StringBuilder sbSendMsg = new StringBuilder();
  				sbSendMsg.append("group ");
  				sbSendMsg.append(mc.getCommand().getGroup() );
  				sbSendMsg.append(" all time:");
  				sbSendMsg.append(mc.getConvergeTime());
  				sbSendMsg.append("--average time:");
  				sbSendMsg.append(mc.getConvergeTime() / mc.getConvergeCount());
  				sbSendMsg.append("\n\r");
  				
  				byte[] responseByte = sbSendMsg.toString().getBytes("utf-8");
  				mc.getChannel().write(ChannelBuffers.copiedBuffer(responseByte));
  				
  				mc.setConvergeCount(0);
  				mc.setConvergeTime(0L);
  			}
  		} else {
  			StringBuilder sbSendMsg = new StringBuilder();
  			for(ShowColumn sc : mc.getCommand().getColumnList()) {
  				if(sc == ShowColumn.All) {
  					sbSendMsg = sbAllMsg;
  					break;
  				} else if(sc == ShowColumn.Time) {
  					sbSendMsg.append("time:");
  					sbSendMsg.append(pc.getEndTime() - pc.getStartTime());
  				} else if(sc == ShowColumn.Key) {
  					sbSendMsg.append("ms--key:");
  					sbSendMsg.append(pc.getKey());
  				} else if(sc == ShowColumn.Description) {
  					sbSendMsg.append("--description:");
  					sbSendMsg.append(pc.getDescription());
  				}
  			}
  			sbSendMsg.append("\n\r");
  			byte[] responseByte = sbSendMsg.toString().getBytes("utf-8");
  			mc.getChannel().write(ChannelBuffers.copiedBuffer(responseByte));
  		}
  	}
  }