content: package com.sohu.cache.server.data;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.regex.Pattern;
  
  import org.apache.commons.lang.math.NumberUtils;
  /**
   * io读写情况
   */
  public class Disk implements LineParser{
  	public static final String FLAG = "DISK";
  	public static final Pattern PATTERN = Pattern.compile("^BBBP,[0-9]+,/bin/df-m,");
  	public static final Pattern SUBPARTITION_PATTERN = Pattern.compile("[0-9]+$");
  	//包括总的状况及各个分区的状况
  	private Map<DiskUsageType, List<Usage>> diskMap = new HashMap<Disk.DiskUsageType, List<Usage>>();
  	
  	/**
  	 * line format:
  	 * DISKBUSY,Disk %Busy iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1
  	 * DISKREAD,Disk Read KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1
  	 * DISKWRITE,Disk Write KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1
  	 * DISKXFER,Disk transfers per second iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1
  	 * DISKBSIZE,Disk Block Size iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1
  	 * DISKBUSY,T0001,0.0,0.0,0.0,0.0
  	 * DISKREAD,T0001,0.0,0.0,0.0,0.0
  	 * DISKWRITE,T0001,0.0,0.0,0.0,0.0
  	 * DISKXFER,T0001,0.0,0.0,0.0,0.0
  	 * DISKBSIZE,T0001,0.0,0.0,0.0,0.0
  	 * BBBP,173,/bin/df-m,"ddev/xvda1         20158 16018      3117  84% /"
  	 */
  	public void parse(String line, String timeKey) throws Exception{
  		if(line.startsWith(FLAG)) {
  			String[] items = line.split(",");
  			if(!items[1].equals(timeKey)) {
  				DiskUsageType type = DiskUsageType.getType(items[0]);
  				if(type == null) {
  					return;
  				}
  				List<Usage> list = diskMap.get(type);
  				if(list == null) {
  					list = new ArrayList<Usage>();
  					diskMap.put(type, list);
  				}
  				for(int i = 2; i < items.length; ++i) {
  					Usage usage = new Usage();
  					usage.setDiskUsageTyp(type);
  					usage.setName(items[i]);
  					list.add(usage);
  				}
  			} else {
  				DiskUsageType type = DiskUsageType.getType(items[0]);
  				if(type == null) {
  					return;
  				}
  				List<Usage> list = diskMap.get(type);
  				if(list == null) {
  					return;
  				}
  				for(int i = 2; i < items.length; ++i) {
  					float value = NumberUtils.toFloat(items[i]);
  					if(value > 0) {
  						list.get(i-2).setValue(value);
  					}
  				}
  			}
  		} else if(PATTERN.matcher(line).find()) {
  			String[] tmp = line.split(",\"");
  			if(tmp.length > 0) {
  				String[] item = tmp[tmp.length - 1].split("\\s+");
  				if(item.length != 6 || !item[4].contains("%")) {
  					return;
  				}
  				List<Usage> list = diskMap.get(DiskUsageType.busy);
  				String[] tp = item[0].split("/");
  				String mount = tp[tp.length - 1];
  				for(Usage usage : list) {
  					if(usage.getName().equals(mount)) {
  						List<Usage> spaceList = diskMap.get(DiskUsageType.space);
  						if(spaceList == null) {
  							spaceList = new ArrayList<Usage>();
  							diskMap.put(DiskUsageType.space, spaceList);
  						}
  						Usage spaceUsage = new Usage();
  						spaceUsage.setDiskUsageTyp(DiskUsageType.space);
  						spaceUsage.setName(usage.getName());
  						spaceUsage.setValue(NumberUtils.toFloat(item[4].split("%")[0]));
  						spaceList.add(spaceUsage);
  					}
  				}
  			}
  		}
  	}
  	
  	public Map<DiskUsageType, List<Usage>> getDiskMap() {
  		return diskMap;
  	}
  	
  	public float getRead() {
  		List<Usage> usageList = diskMap.get(DiskUsageType.read);
  		return getUsage(usageList);
  	}
  	
  	public float getWrite() {
  		List<Usage> usageList = diskMap.get(DiskUsageType.write);
  		return getUsage(usageList);
  	}
  	
  	public float getIops() {
  		List<Usage> usageList = diskMap.get(DiskUsageType.transfer);
  		return getUsage(usageList);
  	}
  	
  	public float getBusy() {
  		List<Usage> usageList = diskMap.get(DiskUsageType.busy);
  		return getUsage(usageList);
  	}
  	
  	public String getExt() {
  		StringBuilder sb = new StringBuilder();
  		for(DiskUsageType type : diskMap.keySet()) {
  			if(DiskUsageType.space == type) {
  				continue;
  			}
  			sb.append(type.getValue());
  			sb.append("=");
  			List<Usage> usageList = diskMap.get(type);
  			for(Usage use : usageList) {
                  sb.append(use.getName());
                  sb.append(":");
                  sb.append(use.getValue());
                  sb.append(",");
              }
  			sb.append(";");
  		}
  		return sb.toString();
  	}
  	
  	public String getSpace() {
  		StringBuilder sb = new StringBuilder();
  		List<Usage> usageList = diskMap.get(DiskUsageType.space);
  		if(usageList == null) {
  			return sb.toString();
  		}
  		for(Usage use : usageList) {
  			sb.append(use.getName());
  			sb.append(":");
  			sb.append(use.getValue());
  			sb.append(",");
  		}
  		return sb.toString();
  	}
  	
  	private float getUsage(List<Usage> usageList) {
  		float usage = 0;
  		if(usageList != null) {
  			for(Usage u : usageList) {
  				if(!SUBPARTITION_PATTERN.matcher(u.getName()).find()) {
  					usage += u.getValue();
  				}
  			}
  		}
  		return usage;
  	}
  
  	@Override
  	public String toString() {
  		return "Disk [diskMap=" + diskMap + "]";
  	}
  	
  	/**
  	 * 使用率
  	 */
  	class Usage{
  		//分区名字
  		private String name;
  		//使用率类型
  		private DiskUsageType diskUsageType;
  		//使用率
  		private float value;
  		public DiskUsageType getDiskUsageType() {
  			return diskUsageType;
  		}
  		public void setDiskUsageTyp(DiskUsageType diskUsageType) {
  			this.diskUsageType = diskUsageType;
  		}
  		public float getValue() {
  			return value;
  		}
  		public void setValue(float value) {
  			this.value = value;
  		}
  		public String getName() {
  			return name;
  		}
  		public void setName(String name) {
  			this.name = name;
  		}
  		@Override
  		public String toString() {
  			return "Usage [name=" + name + ", diskUsageType=" + diskUsageType
  					+ ", value=" + value + "]";
  		}
  	}
  	/**
  	 * 使用率类型
  	 */
  	enum DiskUsageType{
  		//繁忙程度
  		busy("DISKBUSY"),
  		//读
  		read("DISKREAD"),
  		//写
  		write("DISKWRITE"),
  		//io次数
  		transfer("DISKXFER"),
  		//空间使用率
  		space("df"),
  		;
  		private String value;
  		
  		private DiskUsageType(String value) {
  			this.value = value;
  		}
  		public String getValue() {
  			return value;
  		}
  		public static DiskUsageType getType(String type) {
  			for(DiskUsageType dut : DiskUsageType.values()) {
  				if(dut.getValue().equals(type)) {
  					return dut;
  				}
  			}
  			return null;
  		}
  	}
  }
  