/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* AgentImpl.java
* $Id: AgentImpl.java,v 1.37 2007/05/05 05:24:17 tcfujii Exp $
* $Date: 2007/05/05 05:24:17 $
* $Revision: 1.37 $
*/
package com.sun.enterprise.admin.monitor.callflow;
import java.util.UUID;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.enterprise.web.connector.extension.GrizzlyConfig;
import com.sun.enterprise.admin.common.constant.AdminConstants;
/**
* This class implements a call flow agent, which collects call flow data
* and sends it to data store, for later querying and analysis.
*
* It is possible to filter the requests for which call flow data is gathered,
* based on caller host IP address, and caller id (user name).
*
* @author Ram Jeyaraman, Harpreet Singh, Nazrul Islam, Siraj Ghaffar
* @date March 21, 2005
**/
public class AgentImpl implements Agent {
/** Static definitions. */
private static final Logger logger =
Logger.getLogger(AdminConstants.kLoggerName);
static class RequestData {
private RequestType requestType;
private long requestStartTime;
private long requestStartTimeMillis;
private String callerIPAddress;
private String remoteUser;
RequestType getRequestType() {
return requestType;
}
void setRequestType(RequestType requestType) {
this.requestType = requestType;
}
long getRequestStartTime() {
return requestStartTime;
}
void setRequestStartTime(long requestStartTime) {
this.requestStartTime = requestStartTime;
}
long getRequestStartTimeMillis() {
return requestStartTimeMillis;
}
void setRequestStartTimeMillis(long requestStartTimeMillis) {
this.requestStartTimeMillis = requestStartTimeMillis;
}
String getCallerIPAddress() {
return callerIPAddress;
}
void setCallerIPAddress(String callerIPAddress) {
this.callerIPAddress = callerIPAddress;
}
String getRemoteUser() {
return remoteUser;
}
void setRemoteUser(String remoteUser) {
this.remoteUser = remoteUser;
}
}
// Non-synchronized Stack implementation.
static class FlowStack<E> extends LinkedList<E> {
// Note: Java SE 1.6 introduced these methods
// on java.util.Deque. Keeping these methods
// for backward compatibility with Java SE 1.5
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
}
public static class ThreadLocalState implements ThreadLocalData {
private String requestId;
private boolean initialized = false;
private boolean storeData = false;
// The following attributes are used primarily by the log manager
// to log these values into the log message. ThreadId is not cached
// at this point, because the log manager does not require it.
private String methodName;
private String componentType;
private String applicationName;
private String moduleName;
private String componentName;
private String transactionId;
private String securityId;
// RequestStart data holder.
private RequestData requestData;
// To handle nested container trap point invocations.
private FlowStack<ContainerTypeOrApplicationType> flowStack;
ThreadLocalState() {
requestId = UUID.randomUUID().toString();
requestData = new RequestData();
flowStack = new FlowStack<ContainerTypeOrApplicationType>();
}
public String getRequestId() {
return requestId;
}
boolean getInitialized() {
return initialized;
}
void setInitialized(boolean initialized) {
this.initialized = initialized;
}
boolean getStoreData() {
return storeData;
}
void setStoreData(boolean storeData) {
this.storeData = storeData;
}
public String getMethodName() {
return methodName;
}
void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getApplicationName() {
return applicationName;
}
void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getModuleName() {
return moduleName;
}
void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public String getComponentName() {
return componentName;
}
void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getComponentType() {
return componentType;
}
void setComponentType(String componentType) {
this.componentType = componentType;
}
public String getTransactionId() {
return transactionId;
}
void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getSecurityId() {
return securityId;
}
void setSecurityId(String securityId) {
this.securityId = securityId;
}
RequestData getRequestData() {
return requestData;
}
FlowStack<ContainerTypeOrApplicationType> getFlowStack() {
return flowStack;
}
}
// Thread local object.
private static final ThreadLocal<ThreadLocalState> threadLocal =
new ThreadLocal() {
protected ThreadLocalState initialValue() {
return new ThreadLocalState();
}
};
/** Instance variables. */
private static Agent __singletonAgent = new AgentImpl();
private AtomicBoolean storeData = new AtomicBoolean (false);
// With Perf Improvement. This logic will go away. When a complete
// shift is done to completely delete the non-perf code. This will be junked
private int dataWriterThreadCount;
private String callerIPAddressFilter;
private String callerPrincipalFilter;
private AsyncHandlerIntf asyncHandler = AsyncHandlerFactory.getInstance();
private DbAccessObject dbAccessObject = DbAccessObjectImpl.getInstance();
private boolean traceOn; // generates flow sequence trace debug messages.
private List<Listener> listeners =
java.util.Collections.synchronizedList(new ArrayList<Listener>());
// To allow plugging the performant thread implementation.
private boolean perfImpl =
System.getProperty("com.sun.enterprise.callflow.perf", "true").equals("true");
private AgentImpl() {
traceOn = TraceOnHelper.isTraceOn();
}
public static Agent getInstance(){
return __singletonAgent;
}
/** Call flow trap points. */
public void requestStart(RequestType requestType) {
try {
if (!getStoreData())
return;
threadLocal.remove(); // sanity check
ThreadLocalState tls = threadLocal.get();
tls.getFlowStack().clear();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", requestStart()");
}
// NOTE: The request start trap point
// data is written out during the first startTime trap point.
tls.getRequestData().setRequestType(requestType);
tls.getRequestData().setRequestStartTime(System.nanoTime());
tls.getRequestData().
setRequestStartTimeMillis(System.currentTimeMillis());
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.request_start_operation_failed", e);
}
}
public void addRequestInfo(RequestInfo requestInfo, String value) {
try {
if(!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(
Level.INFO, tls.getRequestId() + ", addRequestInfo()");
}
if (tls.getInitialized()) {
logger.log(
Level.FINE,
"callflow.add_request_info_disallowed");
return;
}
if (requestInfo == RequestInfo.CALLER_IP_ADDRESS) {
tls.getRequestData().setCallerIPAddress(value);
} else if (requestInfo == RequestInfo.REMOTE_USER) {
tls.getRequestData().setRemoteUser(value);
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.add_request_info_operation_failed", e);
}
}
/**
* Called only from startTime method. startTime is the first trap point
* that is called after all the request information such as callerIPAddress
* and remoteUser is supplied by the container.
*
* Upon being called, this method initializes the request thread local
* state. Even though this method may be called several times by various
* startTime invocations, only the first call for this request succeeds in
* initializing the thread local state.
*
* Note, the trap point call sequence has a specific order:
*
* {
* requestStart, addRequestInfo*,
* (startTime, (webMethodStart|ejbMethodStart))*,
* ((ejbMethodEnd|webMethodEnd), endTime)*,
* requestEnd
* }
*
* The startTime is the first trap point to be called after all the
* request information is supplied via addRequestInfo method.
*/
private void initialize() {
ThreadLocalState tls = threadLocal.get();
if (tls.getInitialized()) {
return;
}
// Check filters.
RequestData requestData = tls.getRequestData();
String callerIPAddress = requestData.getCallerIPAddress();
String remoteUser = requestData.getRemoteUser();
boolean filtered = false;
if ((this.callerIPAddressFilter != null) &&
!(this.callerIPAddressFilter.equals(callerIPAddress))) {
filtered = true;
}
if ((this.callerPrincipalFilter != null) &&
!(this.callerPrincipalFilter.equals(remoteUser))) {
filtered = true;
}
// Allow storing the data, iff the call is not filtered and
// storeData flag is turned on.
tls.setStoreData(!filtered && getStoreData());
// Create asychronous data asyncHandler iff there is atleast one thread
// whose storeData flag is set.
if (!perfImpl){
if (!filtered && getStoreData()) {
synchronized (asyncHandler) {
if (dataWriterThreadCount == 0) {
this.asyncHandler.enable();
}
dataWriterThreadCount++;
}
}
}
// Note, this flag has to be set before the delayed write.
// Otherwise, this will result in unterminated recursion,
// due to the startTime() method call.
tls.setInitialized(true);
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.requestStart(
tls.getRequestId(), requestData.getRequestType(),
callerIPAddress, remoteUser);
}
}
}
long otherEndTime = System.nanoTime();
// Store data (delayed write).
if (tls.getStoreData()) {
storeRequestStartData(
tls.getRequestId(), requestData.getRequestStartTime(),
requestData.getRequestStartTimeMillis(),
requestData.getRequestType(), callerIPAddress, remoteUser,
tls.getFlowStack(), listenersPresent, otherStartTime,
otherEndTime);
}
}
public void requestEnd() {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", requestEnd()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.requestEnd(tls.getRequestId());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeRequestEndData(
tls.getRequestId(), tls.getFlowStack(),
listenersPresent, otherStartTime, otherEndTime);
}
// Check if there are any more data writer threads. If this is the
// last one, no need for the async data asyncHandler thread.
if (!perfImpl){
if (tls.getStoreData()) {
synchronized (asyncHandler) {
dataWriterThreadCount--;
if (dataWriterThreadCount == 0) {
this.asyncHandler.disable();
}
}
}
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.request_end_operation_failed", e);
} finally {
threadLocal.remove();
}
}
public void startTime(ContainerTypeOrApplicationType type) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", startTime()");
}
// Note: In the natural callflow sequence, startTime() is the first
// method that is called after all the addRequestInfo() calls are
// complete. So, we use the very first startTime() operation to
// do the initialization, filtering, et cetera.
initialize(); // idempotent
if (tls.getStoreData()) {
storeStartTimeData(
tls.getRequestId(), type, tls.getFlowStack());
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.start_time_operation_failed", e);
}
}
public void endTime() {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", endTime()");
}
if (tls.getStoreData()) {
storeEndTimeData(tls.getRequestId(), tls.getFlowStack());
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.end_time_operation_failed", e);
}
}
public void ejbMethodStart(CallFlowInfo info) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(
Level.INFO, tls.getRequestId() + ", ejbMethodStart()");
}
String requestId = tls.getRequestId();
String methodName = info.getMethod().toString();
ComponentType componentType = info.getComponentType();
String applicationName = info.getApplicationName();
String moduleName = info.getModuleName();
String componentName = info.getComponentName();
String transactionId = info.getTransactionId();
String securityId = info.getCallerPrincipal();
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.ejbMethodStart(
requestId, methodName, applicationName,
moduleName, componentName, componentType,
securityId, transactionId);
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodStartData(
tls.getRequestId(), info.getMethod().toString(),
info.getComponentType(), info.getApplicationName(),
info.getModuleName(), info.getComponentName(),
Thread.currentThread().getName(), info.getTransactionId(),
info.getCallerPrincipal(), tls.getFlowStack(),
ContainerTypeOrApplicationType.EJB_APPLICATION,
listenersPresent, otherStartTime, otherEndTime);
}
// Update thread local state.
tls.setMethodName(methodName);
tls.setApplicationName(applicationName);
tls.setModuleName(moduleName);
tls.setComponentName(componentName);
tls.setComponentType(componentType.toString());
tls.setTransactionId(transactionId);
tls.setSecurityId(securityId);
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.ejb_method_start_operation_failed", e);
}
}
public void ejbMethodEnd(CallFlowInfo info) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", ejbMethodEnd()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.ejbMethodEnd(
tls.getRequestId(), info.getException());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodEndData(
tls.getRequestId(), info.getException(), tls.getFlowStack(),
listenersPresent, otherStartTime, otherEndTime);
}
// Clear relevant thread local state.
tls.setMethodName(null);
tls.setApplicationName(null);
tls.setModuleName(null);
tls.setComponentName(null);
tls.setComponentType(null);
tls.setTransactionId(null);
tls.setSecurityId(null);
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.ejb_method_end_operation_failed", e);
}
}
public void webMethodStart(
String methodName, String applicationName, String moduleName,
String componentName, ComponentType componentType,
String callerPrincipal) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(
Level.INFO, tls.getRequestId() + ", webMethodStart()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.webMethodStart(
tls.getRequestId(), methodName, applicationName,
moduleName, componentName, componentType,
callerPrincipal);
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodStartData(
tls.getRequestId(), methodName, componentType,
applicationName, moduleName,
componentName, Thread.currentThread().getName(),
null, callerPrincipal, tls.getFlowStack(),
ContainerTypeOrApplicationType.WEB_APPLICATION,
listenersPresent, otherStartTime, otherEndTime);
}
// Update thread local state.
tls.setMethodName(methodName);
tls.setApplicationName(applicationName);
tls.setModuleName(moduleName);
tls.setComponentName(componentName);
tls.setComponentType(componentType.toString());
tls.setTransactionId(null);
tls.setSecurityId(callerPrincipal);
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.web_method_start_operation_failed", e);
}
}
public void webMethodEnd(Throwable exception) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", webMethodEnd()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.webMethodEnd(tls.getRequestId(), exception);
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodEndData(
tls.getRequestId(), exception, tls.getFlowStack(),
listenersPresent, otherStartTime, otherEndTime);
}
// Clear relevant thread local state.
tls.setMethodName(null);
tls.setApplicationName(null);
tls.setModuleName(null);
tls.setComponentName(null);
tls.setComponentType(null);
tls.setTransactionId(null);
tls.setSecurityId(null);
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.web_method_end_operation_failed", e);
}
}
public void entityManagerQueryStart(EntityManagerQueryMethod queryMethod) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(
Level.INFO, tls.getRequestId() +
", entityManagerQuerytart()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.entityManagerQueryStart(
tls.getRequestId(), queryMethod, tls.getApplicationName(),
tls.getModuleName(), tls.getComponentName(),
ComponentType.JPA, tls.getSecurityId());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodStartData(
tls.getRequestId(), queryMethod.toString(), ComponentType.JPA,
tls.getApplicationName(), tls.getModuleName(),
tls.getComponentName(), Thread.currentThread().getName(),
null, tls.getSecurityId(), tls.getFlowStack(),
ContainerTypeOrApplicationType.JAVA_PERSISTENCE,
listenersPresent, otherStartTime, otherEndTime);
}
} catch (Exception e) {
// XXX change the warning method
logger.log(
Level.WARNING,
"callflow.web_method_start_operation_failed", e);
}
}
public void entityManagerQueryEnd() {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() + ", entityManagerQueryEnd()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.entityManagerQueryEnd(tls.getRequestId());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodEndData(
tls.getRequestId(), null, tls.getFlowStack(),
listenersPresent, otherStartTime, otherEndTime);
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.ejb_method_end_operation_failed", e);
}
}
public void entityManagerMethodStart(EntityManagerMethod entityManagerMethod) {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(
Level.INFO, tls.getRequestId() +
", entityManagerMethodStart()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.entityManagerMethodStart(
tls.getRequestId(), entityManagerMethod,
tls.getApplicationName(),
tls.getModuleName(), tls.getComponentName(),
ComponentType.JPA, tls.getSecurityId());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodStartData(
tls.getRequestId(), entityManagerMethod.toString(), ComponentType.JPA,
tls.getApplicationName(), tls.getModuleName(),
tls.getComponentName(), Thread.currentThread().getName(),
null, tls.getSecurityId(), tls.getFlowStack(),
ContainerTypeOrApplicationType.JAVA_PERSISTENCE,
listenersPresent, otherStartTime, otherEndTime);
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.web_method_start_operation_failed", e);
}
}
public void entityManagerMethodEnd() {
try {
if (!getStoreData())
return;
ThreadLocalState tls = threadLocal.get();
if (traceOn) {
logger.log(Level.INFO, tls.getRequestId() +
", entityManagerMethodEnd()");
}
// Notify listeners.
boolean listenersPresent = false;
long otherStartTime = System.nanoTime();
if (listeners.isEmpty() == false) {
listenersPresent = true;
synchronized (listeners) {
for (Listener listener : listeners) {
listener.entityManagerMethodEnd(tls.getRequestId());
}
}
}
long otherEndTime = System.nanoTime();
// Store data.
if (tls.getStoreData()) {
storeMethodEndData(
tls.getRequestId(), null, tls.getFlowStack(),
listenersPresent, otherStartTime, otherEndTime);
}
} catch (Exception e) {
logger.log(
Level.WARNING,
"callflow.ejb_method_end_operation_failed", e);
}
}
// Private methods.
/**
* Note: This method is called lazily from startTime/initialize().
*/
private void storeRequestStartData(
String requestId, long timeStamp, long timeStampMillis,
RequestType requestType, String callerIPAddress,
String remoteUser,
FlowStack<ContainerTypeOrApplicationType> flowStack,
boolean listenersPresent, long otherStartTime, long otherEndTime) {
if (requestType == RequestType.REMOTE_WEB) {
flowStack.push(ContainerTypeOrApplicationType.WEB_CONTAINER);
} else if (requestType == RequestType.REMOTE_EJB) {
// Remote EJBs first enter via the ORB layer.
flowStack.push(ContainerTypeOrApplicationType.ORB_CONTAINER);
} else { // Timer EJB or MDB
flowStack.push(ContainerTypeOrApplicationType.EJB_CONTAINER);
}
asyncHandler.handleRequestStart(
requestId, timeStamp, timeStampMillis,
requestType, callerIPAddress, remoteUser);
asyncHandler.handleStartTime(requestId, timeStamp, flowStack.peek());
if (listenersPresent) {
flowStack.push(ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleStartTime(
requestId, otherStartTime,
ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleEndTime(
requestId, otherEndTime, flowStack.pop());
}
}
private void storeRequestEndData(
String requestId,
FlowStack<ContainerTypeOrApplicationType> flowStack,
boolean listenersPresent, long otherStartTime, long otherEndTime) {
asyncHandler.handleEndTime(
requestId, System.nanoTime(), flowStack.pop());
if (listenersPresent) {
flowStack.push(ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleStartTime(
requestId, otherStartTime,
ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleEndTime(
requestId, otherEndTime, flowStack.pop());
}
asyncHandler.handleRequestEnd(requestId, System.nanoTime());
}
private void storeMethodStartData(
String requestId, String methodName,
ComponentType componentType, String applicationName,
String moduleName, String componentName, String threadId,
String transactionId, String securityId,
FlowStack<ContainerTypeOrApplicationType> flowStack,
ContainerTypeOrApplicationType appType,
boolean listenersPresent, long otherStartTime, long otherEndTime) {
asyncHandler.handleEndTime(
requestId, System.nanoTime(), flowStack.peek());
if (listenersPresent) {
flowStack.push(ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleStartTime(
requestId, otherStartTime,
ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleEndTime(
requestId, otherEndTime, flowStack.pop());
}
asyncHandler.handleMethodStart(
requestId, System.nanoTime(), methodName, componentType,
applicationName, moduleName, componentName, threadId,
transactionId, securityId);
flowStack.push(appType);
asyncHandler.handleStartTime(requestId, System.nanoTime(), appType);
}
private void storeMethodEndData(
String requestId, Throwable exception,
FlowStack<ContainerTypeOrApplicationType> flowStack,
boolean listenersPresent, long otherStartTime, long otherEndTime) {
asyncHandler.handleEndTime(
requestId, System.nanoTime(), flowStack.pop());
asyncHandler.handleMethodEnd(requestId, System.nanoTime(), exception);
if (listenersPresent) {
flowStack.push(ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleStartTime(
requestId, otherStartTime,
ContainerTypeOrApplicationType.OTHER);
asyncHandler.handleEndTime(
requestId, otherEndTime, flowStack.pop());
}
asyncHandler.handleStartTime(
requestId, System.nanoTime(), flowStack.peek());
}
private void storeStartTimeData(
String requestId,
ContainerTypeOrApplicationType type,
FlowStack<ContainerTypeOrApplicationType> flowStack) {
asyncHandler.handleEndTime(
requestId, System.nanoTime(), flowStack.peek());
flowStack.push(type);
asyncHandler.handleStartTime(requestId, System.nanoTime(), type);
}
private void storeEndTimeData(
String requestId,
FlowStack<ContainerTypeOrApplicationType> flowStack) {
asyncHandler.handleEndTime(
requestId, System.nanoTime(), flowStack.pop());
asyncHandler.handleStartTime(
requestId, System.nanoTime(), flowStack.peek());
}
/** Data accessors. */
public ThreadLocalData getThreadLocalData() {
return (ThreadLocalData) threadLocal.get();
}
/** Support for notification. */
public void registerListener(Listener listener) {
if (listeners.contains(listener) == false) {
listeners.add(listener);
}
}
public void unregisterListener(Listener listener) {
listeners.remove(listener);
}
public boolean getStoreData (){
return this.storeData.get();
}
public void setStoreData (boolean value){
this.storeData.set(value);
}
/** API to support AMX MBean calls. */
public void setEnable(boolean enable) {
synchronized (this){
if (enable) {
asyncHandler = AsyncHandlerFactory.getInstance();
if(perfImpl){ // perf impl
asyncHandler.enable();
}
if (getStoreData() == false){
boolean result = this.dbAccessObject.enable();
if (result) {
enableGrizzly(true);
logger.log(Level.INFO, "callflow.enable_succeeded");
} else {
logger.log(Level.SEVERE, "callflow.enable_failed");
throw new RuntimeException("Callflow Enable Failed");
}
}
} else {
this.callerIPAddressFilter = null;
this.callerPrincipalFilter = null;
if (perfImpl){
if(asyncHandler != null){
asyncHandler.disable();
}
asyncHandler = null;
}
if (getStoreData() == true) {
enableGrizzly(false);
this.dbAccessObject.disable();
logger.log(Level.INFO, "callflow.disable_succeeded");
}
}
setStoreData(enable);
}
}
public boolean isEnabled() {
return storeData.get();
}
public void enableGrizzly(boolean enable) {
List<GrizzlyConfig> grizzlies = GrizzlyConfig.getGrizzlyConfigInstances();
for (GrizzlyConfig grizzly: grizzlies){
grizzly.setEnableCallFlow(true);
}
}
public void setCallerIPFilter(String ipAddress) {
this.callerIPAddressFilter = ipAddress;
if ((callerIPAddressFilter != null) &&
(callerIPAddressFilter.equals(""))) {
callerIPAddressFilter = null;
}
}
public String getCallerIPFilter() {
return this.callerIPAddressFilter;
}
public void setCallerPrincipalFilter(String callerPrincipal) {
this.callerPrincipalFilter = callerPrincipal;
if ((callerPrincipalFilter != null) &&
(callerPrincipalFilter.equals(""))) {
callerPrincipalFilter = null;
}
}
public String getCallerPrincipalFilter() {
return this.callerPrincipalFilter;
}
public void clearData() {
if (getStoreData() == false){
dbAccessObject.clearData();
} else {
logger.log(
Level.WARNING,
"callflow.turn_off_callflow_before_clearData");
}
}
public boolean deleteRequestIds(String[] requestIds) {
return dbAccessObject.deleteRequestIds(requestIds);
}
public List<Map<String, String>> getRequestInformation() {
// flush AsyncHandlerQ's so that if asyncThread is awake, we get
// freshly cooked informtion
if (asyncHandler != null)
this.asyncHandler.flush();
return dbAccessObject.getRequestInformation();
}
public List<Map<String, String>> getCallStackForRequest(String requestId) {
return dbAccessObject.getCallStackInformation(requestId);
}
public java.util.Map<String, String> getPieInformation(String requestID) {
return dbAccessObject.getPieInformation(requestID);
}
}
|