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.functions.system; 020 021import java.util.Iterator; 022import java.util.Map; 023import java.util.Map.Entry; 024 025import javax.servlet.http.HttpServletRequest; 026 027import lucee.commons.io.SystemUtil; 028import lucee.commons.io.res.Resource; 029import lucee.commons.lang.SizeAndCount; 030import lucee.commons.lang.SizeAndCount.Size; 031import lucee.loader.engine.CFMLEngineFactory; 032import lucee.runtime.CFMLFactoryImpl; 033import lucee.runtime.Mapping; 034import lucee.runtime.MappingImpl; 035import lucee.runtime.PageContext; 036import lucee.runtime.PageContextImpl; 037import lucee.runtime.PageSourceImpl; 038import lucee.runtime.PageSourcePool; 039import lucee.runtime.config.ConfigServer; 040import lucee.runtime.config.ConfigWeb; 041import lucee.runtime.config.ConfigWebImpl; 042import lucee.runtime.config.ConfigWebUtil; 043import lucee.runtime.debug.ActiveLock; 044import lucee.runtime.debug.ActiveQuery; 045import lucee.runtime.engine.CFMLEngineImpl; 046import lucee.runtime.exp.PageException; 047import lucee.runtime.ext.function.Function; 048import lucee.runtime.lock.LockManager; 049import lucee.runtime.op.Caster; 050import lucee.runtime.type.Collection; 051import lucee.runtime.type.Collection.Key; 052import lucee.runtime.type.KeyImpl; 053import lucee.runtime.type.Query; 054import lucee.runtime.type.QueryImpl; 055import lucee.runtime.type.Struct; 056import lucee.runtime.type.StructImpl; 057import lucee.runtime.type.dt.DateTimeImpl; 058import lucee.runtime.type.scope.ScopeContext; 059import lucee.runtime.type.util.KeyConstants; 060 061public final class GetUsageData implements Function { 062 063 private static final Key START_TIME = KeyImpl.init("starttime"); 064 private static final Key CACHED_QUERIES = KeyImpl.init("cachedqueries"); 065 private static final Key OPEN_CONNECTIONS = KeyImpl.init("openconnections"); 066 private static final Key ELEMENTS = KeyImpl.init("elements"); 067 private static final Key USERS = KeyImpl.init("users"); 068 private static final Key QUERIES = KeyImpl.init("queries"); 069 private static final Key LOCKS = KeyImpl.init("locks"); 070 071 public static Struct call(PageContext pc) throws PageException { 072 ConfigWeb cw = pc.getConfig(); 073 ConfigServer cs = cw.getConfigServer("server"); 074 ConfigWeb[] webs = cs.getConfigWebs(); 075 CFMLEngineFactory.getInstance(); 076 CFMLEngineImpl engine = (CFMLEngineImpl) cs.getCFMLEngine(); 077 078 Struct sct=new StructImpl(); 079 080 081 // Locks 082 /*LockManager manager = pc.getConfig().getLockManager(); 083 String[] locks = manager.getOpenLockNames(); 084 for(int i=0;i<locks.length;i++){ 085 locks[i]. 086 } 087 if(!ArrayUtil.isEmpty(locks)) 088 strLocks=" open locks at this time ("+List.arrayToList(locks, ", ")+")."; 089 */ 090 091 // Requests 092 Query req=new QueryImpl(new Collection.Key[]{KeyConstants._web,KeyConstants._uri,START_TIME,KeyConstants._timeout}, 0, "requests"); 093 sct.setEL(KeyConstants._requests, req); 094 095 // Template Cache 096 Query tc=new QueryImpl(new Collection.Key[]{KeyConstants._web,ELEMENTS,KeyConstants._size}, 0, "templateCache"); 097 sct.setEL(KeyImpl.init("templateCache"), tc); 098 099 // Scopes 100 Struct scopes=new StructImpl(); 101 sct.setEL(KeyConstants._scopes, scopes); 102 Query app=new QueryImpl(new Collection.Key[]{KeyConstants._web,KeyConstants._application,ELEMENTS,KeyConstants._size}, 0, "templateCache"); 103 scopes.setEL(KeyConstants._application, app); 104 Query sess=new QueryImpl(new Collection.Key[]{KeyConstants._web,KeyConstants._application,USERS,ELEMENTS,KeyConstants._size}, 0, "templateCache"); 105 scopes.setEL(KeyConstants._session, sess); 106 107 // Query 108 Query qry=new QueryImpl(new Collection.Key[]{KeyConstants._web,KeyConstants._application,START_TIME,KeyConstants._sql}, 0, "requests"); 109 sct.setEL(QUERIES, qry); 110 111 // Locks 112 Query lck=new QueryImpl(new Collection.Key[]{KeyConstants._web,KeyConstants._application,KeyConstants._name,START_TIME,KeyConstants._timeout,KeyConstants._type}, 0, "requests"); 113 sct.setEL(LOCKS, lck); 114 115 // Loop webs 116 ConfigWebImpl web; 117 Map<Integer, PageContextImpl> pcs; 118 PageContextImpl _pc; 119 int row,openConnections=0; 120 CFMLFactoryImpl factory; 121 ActiveQuery[] queries; 122 ActiveQuery aq; 123 ActiveLock[] locks; 124 ActiveLock al; 125 for(int i=0;i<webs.length;i++){ 126 127 // Loop requests 128 web=(ConfigWebImpl) webs[i]; 129 factory=(CFMLFactoryImpl)web.getFactory(); 130 pcs = factory.getActivePageContexts(); 131 Iterator<PageContextImpl> it = pcs.values().iterator(); 132 while(it.hasNext()){ 133 _pc = it.next(); 134 if(_pc.isGatewayContext()) continue; 135 136 // Request 137 row = req.addRow(); 138 req.setAt(KeyConstants._web, row, web.getLabel()); 139 req.setAt(KeyConstants._uri, row, getPath(_pc.getHttpServletRequest())); 140 req.setAt(START_TIME, row, new DateTimeImpl(pc.getStartTime(),false)); 141 req.setAt(KeyConstants._timeout, row, new Double(pc.getRequestTimeout())); 142 143 // Query 144 queries = _pc.getActiveQueries(); 145 if(queries!=null) { 146 for(int y=0;y<queries.length;y++){ 147 aq=queries[y]; 148 row = qry.addRow(); 149 qry.setAt(KeyConstants._web, row, web.getLabel()); 150 qry.setAt(KeyConstants._application, row, _pc.getApplicationContext().getName()); 151 qry.setAt(START_TIME, row, new DateTimeImpl(web,aq.startTime,true)); 152 qry.setAt(KeyConstants._sql, row, aq.sql); 153 } 154 } 155 156 // Lock 157 locks = _pc.getActiveLocks(); 158 if(locks!=null) { 159 for(int y=0;y<locks.length;y++){ 160 al=locks[y]; 161 row = lck.addRow(); 162 lck.setAt(KeyConstants._web, row, web.getLabel()); 163 lck.setAt(KeyConstants._application, row, _pc.getApplicationContext().getName()); 164 lck.setAt(KeyConstants._name, row, al.name); 165 lck.setAt(START_TIME, row, new DateTimeImpl(web,al.startTime,true)); 166 lck.setAt(KeyConstants._timeout, row, Caster.toDouble(al.timeoutInMillis/1000)); 167 lck.setAt(KeyConstants._type, row, al.type==LockManager.TYPE_EXCLUSIVE?"exclusive":"readonly"); 168 } 169 } 170 } 171 openConnections+=web.getDatasourceConnectionPool().openConnections(); 172 173 174 // Template Cache 175 Mapping[] mappings = ConfigWebUtil.getAllMappings(web); 176 long[] tce = templateCacheElements(mappings); 177 row = tc.addRow(); 178 tc.setAt(KeyConstants._web, row, web.getLabel()); 179 tc.setAt(KeyConstants._size, row, new Double(tce[1])); 180 tc.setAt(ELEMENTS, row, new Double(tce[0])); 181 182 // Scope Application 183 getAllApplicationScopes(web,factory.getScopeContext(),app); 184 getAllCFSessionScopes(web,factory.getScopeContext(),sess); 185 186 187 } 188 189 // Datasource 190 Struct ds=new StructImpl(); 191 sct.setEL(KeyConstants._datasources, ds); 192 193 ds.setEL(CACHED_QUERIES, Caster.toDouble(ConfigWebUtil.getCacheHandlerFactories(pc.getConfig()).query.size(pc))); // there is only one cache for all contexts 194 ds.setEL(OPEN_CONNECTIONS, Caster.toDouble(openConnections)); 195 196 // Memory 197 Struct mem=new StructImpl(); 198 sct.setEL(KeyConstants._memory, mem); 199 mem.setEL("heap", SystemUtil.getMemoryUsageAsStruct(SystemUtil.MEMORY_TYPE_HEAP)); 200 mem.setEL("nonheap", SystemUtil.getMemoryUsageAsStruct(SystemUtil.MEMORY_TYPE_NON_HEAP)); 201 202 203 // uptime 204 sct.set("uptime", new DateTimeImpl(engine.uptime(),true)); 205 206 // now 207 sct.set("now", new DateTimeImpl(pc)); 208 209 210 //SizeAndCount.Size size = SizeAndCount.sizeOf(pc.serverScope()); 211 212 213 214 return sct; 215 } 216 217 private static void getAllApplicationScopes(ConfigWebImpl web, ScopeContext sc, Query app) throws PageException { 218 Struct all = sc.getAllApplicationScopes(); 219 Iterator<Entry<Key, Object>> it = all.entryIterator(); 220 Entry<Key, Object> e; 221 int row; 222 Size sac; 223 while(it.hasNext()){ 224 e = it.next(); 225 row=app.addRow(); 226 sac = SizeAndCount.sizeOf(e.getValue()); 227 app.setAt(KeyConstants._web, row, web.getLabel()); 228 app.setAt(KeyConstants._application, row, e.getKey().getString()); 229 app.setAt(KeyConstants._size, row, new Double(sac.size)); 230 app.setAt(ELEMENTS, row, new Double(sac.count)); 231 232 } 233 } 234 235 private static void getAllCFSessionScopes(ConfigWebImpl web, ScopeContext sc, Query sess) throws PageException { 236 Struct all = sc.getAllCFSessionScopes(); 237 Iterator it = all.entryIterator(),itt; 238 Entry e,ee; 239 int row,size,count,users; 240 Size sac; 241 // applications 242 while(it.hasNext()){ 243 e = (Entry) it.next(); 244 itt = ((Map)e.getValue()).entrySet().iterator(); 245 size=0;count=0;users=0; 246 while(itt.hasNext()){ 247 ee=(Entry)itt.next(); 248 sac = SizeAndCount.sizeOf(ee.getValue()); 249 size+=sac.size; 250 count+=sac.count; 251 users++; 252 } 253 row=sess.addRow(); 254 255 sess.setAt(KeyConstants._web, row, web.getLabel()); 256 sess.setAt(USERS, row, new Double(users)); 257 sess.setAt(KeyConstants._application, row, e.getKey().toString()); 258 sess.setAt(KeyConstants._size, row, new Double(size)); 259 sess.setAt(ELEMENTS, row, new Double(count)); 260 } 261 } 262 263 private static long[] templateCacheElements(Mapping[] mappings) { 264 long elements=0,size=0; 265 266 PageSourcePool psp; 267 Object[] keys; 268 PageSourceImpl ps; 269 Resource res; 270 MappingImpl mapping; 271 for(int i=0;i<mappings.length;i++){ 272 mapping=(MappingImpl)mappings[i]; 273 psp = mapping.getPageSourcePool(); 274 keys = psp.keys(); 275 for(int y=0;y<keys.length;y++) { 276 ps = (PageSourceImpl) psp.getPageSource(keys[y], false); 277 if(ps.isLoad()) { 278 elements++; 279 res=mapping.getClassRootDirectory().getRealResource(ps.getJavaName()+".class"); 280 size+=res.length(); 281 } 282 } 283 } 284 return new long[]{elements,size}; 285 } 286 287 288 public static String getScriptName(HttpServletRequest req) { 289 return emptyIfNull(req.getContextPath())+emptyIfNull(req.getServletPath()); 290 } 291 292 public static String getPath(HttpServletRequest req) { 293 String qs=emptyIfNull(req.getQueryString()); 294 if(qs.length()>0)qs="?"+qs; 295 296 297 return emptyIfNull(req.getContextPath())+emptyIfNull(req.getServletPath())+qs; 298 } 299 300 private static String emptyIfNull(String str) { 301 if(str==null) return ""; 302 return str; 303 } 304}