All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.JChannelProbeHandler Maven / Gradle / Ivy

package org.jgroups;

import org.jgroups.blocks.MethodCall;
import org.jgroups.jmx.AdditionalJmxObjects;
import org.jgroups.jmx.ResourceDMBean;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.jgroups.stack.DiagnosticsHandler;
import org.jgroups.stack.Protocol;
import org.jgroups.util.Util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author Bela Ban
 * @since  4.0
 */
public class JChannelProbeHandler implements DiagnosticsHandler.ProbeHandler {
    protected final JChannel ch;
    protected final Log log;

    public JChannelProbeHandler(JChannel ch) {
        this.ch=ch;
        log=LogFactory.getLog(ch.getClass());
    }

    public Map handleProbe(String... keys) {
        Map map=new TreeMap<>();
        for(String key: keys) {
            if(key.startsWith("jmx")) {
                handleJmx(map, key);
                continue;
            }
            if(key.startsWith("reset-stats")) {
                resetAllStats();
                continue;
            }
            if(key.startsWith("invoke") || key.startsWith("op")) {
                int index=key.indexOf('=');
                if(index != -1) {
                    try {
                        handleOperation(map, key.substring(index+1));
                    }
                    catch(Throwable throwable) {
                        log.error(Util.getMessage("OperationInvocationFailure"), key.substring(index+1), throwable);
                    }
                }
            }
        }
        return map;
    }

    public String[] supportedKeys() {
        return new String[]{"reset-stats", "jmx", "op=[]"};
    }

    protected JChannel resetAllStats() {
        List prots=ch.getProtocolStack().getProtocols();
        prots.forEach(Protocol::resetStatistics);
        return ch.resetStats();
    }

    protected void handleJmx(Map map, String input) {
        Map tmp_stats;
        int index=input.indexOf('=');
        if(index > -1) {
            List list=null;
            String protocol_name=input.substring(index +1);
            index=protocol_name.indexOf('.');
            if(index > -1) {
                String rest=protocol_name;
                protocol_name=protocol_name.substring(0, index);
                String attrs=rest.substring(index +1); // e.g. "num_sent,msgs,num_received_msgs"
                list=Util.parseStringList(attrs, ",");

                // check if there are any attribute-sets in the list
                for(Iterator it=list.iterator(); it.hasNext();) {
                    String tmp=it.next();
                    index=tmp.indexOf('=');
                    if(index != -1) {
                        String attrname=tmp.substring(0, index);
                        String attrvalue=tmp.substring(index+1);
                        Object target=ch.getProtocolStack().findProtocol(protocol_name);
                        Field field=target != null? Util.getField(target.getClass(), attrname) : null;
                        if(field == null && target instanceof AdditionalJmxObjects) {
                            Object[] objs=((AdditionalJmxObjects)target).getJmxObjects();
                            if(objs != null && objs.length > 0) {
                                for(Object o: objs) {
                                    field=o != null? Util.getField(o.getClass(), attrname) : null;
                                    if(field != null) {
                                        target=o;
                                        break;
                                    }
                                }
                            }
                        }

                        if(field != null) {
                            Object value=Util.convert(attrvalue, field.getType());
                            if(value != null) {
                                if(target instanceof Protocol)
                                    ((Protocol)target).setValue(attrname, value);
                                else
                                    Util.setField(field, target, value);
                            }
                        }
                        else {
                            // try to find a setter for X, e.g. x(type-of-x) or setX(type-of-x)
                            ResourceDMBean.Accessor setter=ResourceDMBean.findSetter(target, attrname);  // Util.getSetter(prot.getClass(), attrname);
                            if(setter == null && target instanceof AdditionalJmxObjects) {
                                Object[] objs=((AdditionalJmxObjects)target).getJmxObjects();
                                if(objs != null && objs.length > 0) {
                                    for(Object o: objs) {
                                        setter=o != null? ResourceDMBean.findSetter(target, attrname) : null;
                                        if(setter!= null)
                                            break;
                                    }
                                }
                            }

                            if(setter != null) {
                                try {
                                    Class type=setter instanceof ResourceDMBean.FieldAccessor?
                                      ((ResourceDMBean.FieldAccessor)setter).getField().getType() :
                                      setter instanceof ResourceDMBean.MethodAccessor?
                                        ((ResourceDMBean.MethodAccessor)setter).getMethod().getParameterTypes()[0] : null;
                                    Object converted_value=Util.convert(attrvalue, type);
                                    setter.invoke(converted_value);
                                }
                                catch(Exception e) {
                                    log.error("unable to invoke %s() on %s: %s", setter, protocol_name, e);
                                }
                            }
                            else
                                log.warn(Util.getMessage("FieldNotFound"), attrname, protocol_name);
                        }

                        it.remove();
                    }
                }
            }
            tmp_stats=ch.dumpStats(protocol_name, list);
            if(tmp_stats != null) {
                for(Map.Entry entry : tmp_stats.entrySet()) {
                    Map tmp_map=(Map)entry.getValue();
                    String key=entry.getKey();
                    map.put(key, tmp_map != null? tmp_map.toString() : null);
                }
            }
        }
        else {
            tmp_stats=ch.dumpStats();
            if(tmp_stats != null) {
                for(Map.Entry entry : tmp_stats.entrySet()) {
                    Map tmp_map=(Map)entry.getValue();
                    String key=entry.getKey();
                    map.put(key, tmp_map != null? tmp_map.toString() : null);
                }
            }
        }
    }

    /**
     * Invokes an operation and puts the return value into map
     * @param map
     * @param operation Protocol.OperationName[args], e.g. STABLE.foo[arg1 arg2 arg3]
     */
    protected void handleOperation(Map map, String operation) throws Exception {
        int index=operation.indexOf('.');
        if(index == -1)
            throw new IllegalArgumentException("operation " + operation + " is missing the protocol name");
        String prot_name=operation.substring(0, index);
        Protocol prot=ch.getProtocolStack().findProtocol(prot_name);
        if(prot == null)
            return; // less drastic than throwing an exception...


        int args_index=operation.indexOf('[');
        String method_name;
        if(args_index != -1)
            method_name=operation.substring(index +1, args_index).trim();
        else
            method_name=operation.substring(index+1).trim();

        String[] args=null;
        if(args_index != -1) {
            int end_index=operation.indexOf(']');
            if(end_index == -1)
                throw new IllegalArgumentException("] not found");
            List str_args=Util.parseCommaDelimitedStrings(operation.substring(args_index + 1, end_index));
            Object[] strings=str_args.toArray();
            args=new String[strings.length];
            for(int i=0; i < strings.length; i++)
                args[i]=(String)strings[i];
        }

        Object target=prot;
        Method method=MethodCall.findMethod(target.getClass(), method_name, args);
        if(method == null) {
            if(prot instanceof AdditionalJmxObjects) {
                for(Object obj: ((AdditionalJmxObjects)prot).getJmxObjects()) {
                    method=MethodCall.findMethod(obj.getClass(), method_name, args);
                    if(method != null) {
                        target=obj;
                        break;
                    }
                }
            }
            if(method == null) {
                log.warn(Util.getMessage("MethodNotFound"), ch.getAddress(), target.getClass().getSimpleName(), method_name);
                return;
            }
        }

        MethodCall call=new MethodCall(method);
        Object[] converted_args=null;
        if(args != null) {
            converted_args=new Object[args.length];
            Class[] types=method.getParameterTypes();
            for(int i=0; i < args.length; i++)
                converted_args[i]=Util.convert(args[i], types[i]);
        }
        Object retval=call.invoke(target, converted_args);
        if(retval != null)
            map.put(prot_name + "." + method_name, retval.toString());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy