001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.engine; 020 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Map; 024 025import lucee.commons.lang.StringUtil; 026import lucee.runtime.PageContext; 027import lucee.runtime.op.Caster; 028 029public abstract class ExecutionLogSupport implements ExecutionLog { 030 031 protected static final short UNIT_NANO=1; 032 protected static final short UNIT_MICRO=2; 033 protected static final short UNIT_MILLI=4; 034 protected static final short UNIT_UNDEFINED=0; 035 private static final char CHAR_MICRO = (char)181; 036 037 private Map<String,Pair> map=Collections.synchronizedMap(new HashMap<String,Pair>()); 038 protected long min=Long.MIN_VALUE; 039 protected short unit=UNIT_UNDEFINED; 040 041 public void init(PageContext pc,Map<String,String> arguments) { 042 // min 043 if(min==Long.MIN_VALUE) { 044 min=toNanos(arguments.get("min-time"),0); 045 } 046 // unit 047 if(UNIT_UNDEFINED==unit){ 048 unit=UNIT_NANO; 049 // unit 050 String _unit=arguments.get("unit"); 051 if(_unit!=null) { 052 _unit=_unit.trim(); 053 if(_unit.equalsIgnoreCase("micro")) unit=UNIT_MICRO; 054 else if(_unit.equalsIgnoreCase(CHAR_MICRO+"s")) unit=UNIT_MICRO; 055 else if(_unit.equalsIgnoreCase("milli"))unit=UNIT_MILLI; 056 else if(_unit.equalsIgnoreCase("ms")) unit=UNIT_MILLI; 057 } 058 } 059 _init(pc,arguments); 060 } 061 062 private static long toNanos(String str, int defaultValue) { 063 if(StringUtil.isEmpty(str)) return defaultValue; 064 str=str.trim().toLowerCase(); 065 long l = Caster.toLongValue(str,Long.MIN_VALUE); 066 if(l!=Long.MIN_VALUE) return l; 067 068 if(str.endsWith("ns")) { 069 String sub=str.substring(0,str.length()-2); 070 l = Caster.toLongValue(sub.trim(),Long.MIN_VALUE); 071 if(l!=Long.MIN_VALUE) return l; 072 } 073 else if(str.endsWith(CHAR_MICRO+"s")) { 074 String sub=str.substring(0,str.length()-2); 075 double d = Caster.toDoubleValue(sub.trim(),Double.NaN); 076 if(!Double.isNaN(d)) return (long)(d*1000); 077 } 078 else if(str.endsWith("ms")) { 079 String sub=str.substring(0,str.length()-2); 080 double d = Caster.toDoubleValue(sub.trim(),Double.NaN); 081 if(!Double.isNaN(d)) return (long)(d*1000*1000); 082 } 083 else if(str.endsWith("s")) { 084 String sub=str.substring(0,str.length()-1); 085 double d = Caster.toDoubleValue(sub.trim(),Double.NaN); 086 if(!Double.isNaN(d)) return (long)(d*1000*1000); 087 } 088 089 return defaultValue; 090 } 091 092 public final void release() { 093 map.clear(); 094 _release(); 095 } 096 097 public final void start(int pos,String id) { 098 long current = System.nanoTime(); 099 map.put(id,new Pair(current,pos)); 100 } 101 102 public final void end(int pos,String id) { 103 long current = System.nanoTime(); 104 Pair pair=map.remove(id); 105 if(pair!=null) { 106 if((current-pair.time)>=min) 107 _log(pair.pos,pos,pair.time,current); 108 } 109 } 110 protected abstract void _init(PageContext pc, Map<String, String> arguments); 111 protected abstract void _log(int startPos, int endPos, long startTime, long endTime); 112 protected abstract void _release(); 113 114 115 protected String timeLongToString(long current) { 116 if(unit==UNIT_MICRO) return (current/1000L)+" "+CHAR_MICRO+"s"; 117 if(unit==UNIT_MILLI) return (current/1000000L)+" ms"; 118 return current+" ns"; 119 } 120 protected static String unitShortToString(short unit) { 121 if(unit==UNIT_MICRO) return CHAR_MICRO+"s"; 122 if(unit==UNIT_MILLI) return "ms"; 123 return "ns"; 124 } 125 126 private final static class Pair { 127 private final long time; 128 private final int pos; 129 public Pair(long time, int pos) { 130 this.time=time; 131 this.pos=pos; 132 } 133 } 134}