/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (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/CDDLv1.0.html.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
*
* If applicable add the following below this CDDL HEADER,
* with the fields enclosed by brackets "[]" replaced with
* your own identifying information: Portions Copyright
* [year] [name of copyright owner]
*/
/*
* @(#)FaultInjection.java 1.11 05/02/06
*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*/
package com.sun.messaging.jmq.jmsserver;
import java.util.*;
import com.sun.messaging.jmq.util.selector.*;
import com.sun.messaging.jmq.util.log.*;
import java.io.*;
import com.sun.messaging.jmq.jmsserver.util.BrokerException;
import com.sun.messaging.jmq.jmsserver.Globals;
/**
* All fault target constants start with FAULT_ and
* only fault target constant starts with FAULT_
*
*/
public class FaultInjection
{
static FaultInjection fault = null;
Logger logger = Globals.getLogger();
Set injections = null;
Map injectionSelectors = null;
Map injectionProps = null;
public static boolean FAULT_INJECTION = false;
/**
* 1 is before processing
* 2 is after processing, before reply
* 3 is after reply
*/
public static String STAGE_1 = "1";
public static String STAGE_2 = "2";
public static String STAGE_3 = "3";
public static String FAULT_TXN_START_1 = "txn.start.1";
public static String FAULT_TXN_END_1 = "txn.end.1";
public static String FAULT_TXN_PREPARE_1 = "txn.prepare.1";
public static String FAULT_TXN_COMMIT_1 = "txn.commit.1";
public static String FAULT_TXN_ROLLBACK_1 = "txn.rollback.1";
public static String FAULT_TXN_START_2 = "txn.start.2";
public static String FAULT_TXN_END_2 = "txn.end.2";
public static String FAULT_TXN_PREPARE_2 = "txn.prepare.2";
public static String FAULT_TXN_COMMIT_2 = "txn.commit.2";
public static String FAULT_TXN_ROLLBACK_2 = "txn.rollback.2";
public static String FAULT_TXN_START_3 = "txn.start.3";
public static String FAULT_TXN_END_3 = "txn.end.3";
public static String FAULT_TXN_PREPARE_3 = "txn.prepare.3";
public static String FAULT_TXN_COMMIT_3 = "txn.commit.3";
public static String FAULT_TXN_ROLLBACK_3 = "txn.rollback.3";
// after db update but before reply
public static String FAULT_TXN_COMMIT_4 = "txn.commit.4";
public static String FAULT_TXN_ROLLBACK_4 = "txn.rollback.4";
// additional properties supported on acks
// mqAckCount - number of acks received
// mqIsTransacted - is in transaction
public static String MSG_ACKCOUNT_PROP = "mqAckCount";
public static String FAULT_ACK_MSG_1 = "msg.ack.1";
public static String FAULT_ACK_MSG_2 = "msg.ack.2";
public static String FAULT_ACK_MSG_3 = "msg.ack.3";
// on messages all message properties are set plut
// mqMsgCount - mumber of messages received
// MQIsTransacted - is in transaction
public static String FAULT_SEND_MSG_1 = "msg.send.1";
public static String FAULT_SEND_MSG_2 = "msg.send.2";
public static String FAULT_SEND_MSG_3 = "msg.send.3";
/********************************************************************
*REMOTE ACK - Protocol
*
* Support followoing properties
* mqAckCount:
* consumer broker -
* on sending the ?th remote ack of ackType to any remote broker
* message home broker -
* on receiving the ?th remote ack of ackType from any remote broker
*
* Fault ID syntax: msg.remote_ack.<home>.<layer>.<ackType>.<n>
*
* where <home> "home" if fault occurs on msg home broker else ""
* <layer> "p" for protocol, "c" for core
* <ackType> "" non-txn'ed or 3.5/3.6 cluster protocol
* "txnack", "txnprepare", "txnrollback", "txncommit"
* <n> meaning for protocol layer ("p")
* "1" before send (in buffer) or unpon receive (home) protocol
* "2" before receive reply or send (home) reply
* "3" after receive reply or send (home, in buffer) reply
*
********************************************************************/
public static String MSG_REMOTE_ACK_TXNACK = "txnack.";
public static String MSG_REMOTE_ACK_TXNPREPARE = "txnprepare.";
public static String MSG_REMOTE_ACK_TXNROLLBACK = "txnrollback.";
public static String MSG_REMOTE_ACK_TXNCOMMIT = "txncommit.";
public static String MSG_REMOTE_ACK_P = "msg.remote_ack.p.";
public static String MSG_REMOTE_ACK_HOME_P = "msg.remote_ack.home.p.";
public static String FAULT_MSG_REMOTE_ACK_P_TXNACK_1 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNACK+"1";
public static String FAULT_MSG_REMOTE_ACK_P_TXNACK_2 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNACK+"2";
public static String FAULT_MSG_REMOTE_ACK_P_TXNACK_3 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNACK+"3";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNACK_1 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNACK+"1";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNACK_2 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNACK+"2";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNACK_3 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNACK+"3";
public static String FAULT_MSG_REMOTE_ACK_P_TXNPREPARE_1 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNPREPARE+"1";
public static String FAULT_MSG_REMOTE_ACK_P_TXNPREPARE_2 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNPREPARE+"2";
public static String FAULT_MSG_REMOTE_ACK_P_TXNPREPARE_3 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNPREPARE+"3";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNPREPARE_1 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNPREPARE+"1";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNPREPARE_2 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNPREPARE+"2";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNPREPARE_3 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNPREPARE+"3";
public static String FAULT_MSG_REMOTE_ACK_P_TXNROLLBACK_1 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNROLLBACK+"1";
public static String FAULT_MSG_REMOTE_ACK_P_TXNROLLBACK_2 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNROLLBACK+"2";
public static String FAULT_MSG_REMOTE_ACK_P_TXNROLLBACK_3 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNROLLBACK+"3";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNROLLBACK_1 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNROLLBACK+"1";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNROLLBACK_2 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNROLLBACK+"2";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNROLLBACK_3 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNROLLBACK+"3";
public static String FAULT_MSG_REMOTE_ACK_P_TXNCOMMIT_P_1 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNCOMMIT+"1";
public static String FAULT_MSG_REMOTE_ACK_P_TXNCOMMIT_P_2 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNCOMMIT+"2";
public static String FAULT_MSG_REMOTE_ACK_P_TXNCOMMIT_P_3 =
MSG_REMOTE_ACK_P+MSG_REMOTE_ACK_TXNCOMMIT+"3";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNCOMMIT_1 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNCOMMIT+"1";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNCOMMIT_2 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNCOMMIT+"2";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_TXNCOMMIT_3 =
MSG_REMOTE_ACK_HOME_P+MSG_REMOTE_ACK_TXNCOMMIT+"3";
public static String FAULT_MSG_REMOTE_ACK_P_1 = MSG_REMOTE_ACK_P+"1";
public static String FAULT_MSG_REMOTE_ACK_P_2 = MSG_REMOTE_ACK_P+"2";
public static String FAULT_MSG_REMOTE_ACK_P_3 = MSG_REMOTE_ACK_P+"3";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_1 = MSG_REMOTE_ACK_HOME_P+"1";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_2 = MSG_REMOTE_ACK_HOME_P+"2";
public static String FAULT_MSG_REMOTE_ACK_HOME_P_3 = MSG_REMOTE_ACK_HOME_P+"3";
public static FaultInjection getInjection()
{
if (fault == null)
fault = new FaultInjection();
return fault;
}
public FaultInjection() {
injections = Collections.synchronizedSet(new HashSet());
injectionSelectors = Collections.synchronizedMap(new HashMap());
injectionProps = Collections.synchronizedMap(new HashMap());
}
public void setFault(String fault, String selector)
throws SelectorFormatException
{
setFault(fault, selector, null);
}
public void setFault(String fault, String selector, Map props)
throws SelectorFormatException
{
logger.log(Logger.INFO,"Setting Fault " + fault +
"[ selector=" + selector + "]");
injections.add(fault);
if (selector != null && selector.length() != 0) {
// create a selector and insert
Selector s = Selector.compile(selector);
injectionSelectors.put(fault, s);
}
if (props != null)
injectionProps.put(fault, props);
}
public void unsetFault(String fault) {
logger.log(Logger.INFO,"Removing Fault " + fault );
injections.remove(fault);
injectionSelectors.remove(fault);
injectionProps.remove(fault);
}
class FaultInjectionException extends Exception
{
public String toString() {
return "FaultInjectionTrace";
}
}
public void setFaultInjection(boolean inject)
{
if (FAULT_INJECTION != inject) {
if (inject) {
logger.log(Logger.INFO,"Turning on Fault Injection");
} else {
logger.log(Logger.INFO,"Turning off Fault Injection");
}
FAULT_INJECTION = inject;
}
}
public void logInjection(String fault, Selector sel)
{
String str = "Fault Injection: triggered " + fault;
if (sel != null)
str += " selector [ " + sel.toString() + "]";
Exception ex = new FaultInjectionException();
ex.fillInStackTrace();
logger.logStack(logger.INFO, str, ex);
}
public Map checkFaultGetProps(String fault, Map props)
{
if (!FAULT_INJECTION) return null;
boolean ok = checkFault(fault, props);
if (!ok) return null;
Map m = (Map)injectionProps.get(fault);
if (m == null) m = new HashMap();
return m;
}
public boolean checkFault(String fault, Map props)
{
if (!FAULT_INJECTION) return false;
if (injections.contains(fault))
{
Selector s = (Selector)injectionSelectors.get(fault);
if (s == null) {
logInjection(fault, null);
return true;
}
try {
boolean match = s.match(props, null);
if (match) {
logInjection(fault, s);
return true;
}
return false;
} catch (Exception ex) {
logger.logStack(Logger.WARNING,"Unable to apply fault ",
ex);
return false;
}
}
return false;
}
public void checkFaultAndThrowIOException(String value,
Map props)
throws IOException
{
if (!FAULT_INJECTION) return;
if (checkFault(value, props)) {
IOException ex = new IOException("Fault Insertion: "
+ value);
}
}
public void checkFaultAndThrowBrokerException(String value,
Map props)
throws BrokerException
{
if (!FAULT_INJECTION) return;
if (checkFault(value, props)) {
BrokerException ex = new BrokerException("Fault Insertion: "
+ value);
}
}
public void checkFaultAndThrowException(String value,
Map props, String ex_class)
throws Exception
{
if (!FAULT_INJECTION) return;
if (checkFault(value, props)) {
// XXX use exclass to create exception
Exception ex = new Exception("Fault Insertion: "
+ value);
}
}
public void checkFaultAndThrowError(String value,
Map props, String ex_class)
throws Error
{
if (!FAULT_INJECTION) return;
if (checkFault(value, props)) {
// XXX use exclass to create exception
Error ex = new Error("Fault Insertion: "
+ value);
}
}
public void checkFaultAndExit(String value,
Map props, int exitCode, boolean nice)
{
if (!FAULT_INJECTION) return;
if (checkFault(value, props)) {
if (nice) {
// XXX use broker method to shutdown
logger.log(Logger.INFO,"SHUTING DOWN BROKER BECAUSE OF"
+ " FAULT " + value);
System.exit(exitCode);
} else {
logger.log(Logger.INFO, "HALTING BROKER BECAUSE OF"
+ " FAULT " + value);
Runtime.getRuntime().halt(exitCode);
}
}
}
}
|