Search in sources :

Example 1 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class QpidQueueStats method createQueueSubscription.

/**
     * Create a Subscription to query for all queue objects
     */
private void createQueueSubscription() {
    try {
        // This QmfQuery simply does an ID query for objects with the className "queue"
        QmfQuery query = new QmfQuery(QmfQueryTarget.OBJECT, new SchemaClassId("queue"));
        SubscribeParams params = _console.createSubscription(_broker, query, "queueStatsHandle");
        _subscriptionId = params.getSubscriptionId();
        // Subtract 10 as we want to refresh before it times out
        _subscriptionDuration = params.getLifetime() - 10;
        _startTime = System.currentTimeMillis();
    } catch (QmfException qmfe) {
    }
}
Also used : SubscribeParams(org.apache.qpid.qmf2.console.SubscribeParams) SchemaClassId(org.apache.qpid.qmf2.common.SchemaClassId) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery) QmfException(org.apache.qpid.qmf2.common.QmfException)

Example 2 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class ConnectionAudit method validateQueue.

/**
     * Looks up the exchange and binding information from the supplied queuename then calls the main validateQueue()
     * @param queueName the name of the queue that we want to check against the whitelists.
     * @param address the connection address information for the subscription.
     * @param timestamp the timestamp of the subscription.
     */
private void validateQueue(final String queueName, final String address, final String timestamp) {
    ObjectId queueId = null;
    List<QmfConsoleData> queues = _console.getObjects("org.apache.qpid.broker", "queue");
    for (QmfConsoleData queue : queues) {
        // We first have to find the ObjectId of the queue called queueName.
        if (queue.getStringValue("name").equals(queueName)) {
            queueId = queue.getObjectId();
            break;
        }
    }
    if (queueId == null) {
        System.out.printf("%s ERROR ConnectionAudit.validateQueue() %s reference couldn't be found\n", new Date().toString(), queueName);
    } else {
        // If we've got the queue's ObjectId we then find the binding that references it.
        List<QmfConsoleData> bindings = _console.getObjects("org.apache.qpid.broker", "binding");
        for (QmfConsoleData binding : bindings) {
            ObjectId queueRef = binding.getRefValue("queueRef");
            if (queueRef.equals(queueId)) {
                // We've found a binding that matches queue queueName so look up the associated exchange and validate.
                QmfConsoleData exchange = dereference(binding.getRefValue("exchangeRef"));
                String exchangeName = exchange.getStringValue("name");
                validateQueue(queueName, exchangeName, binding, address, timestamp);
            }
        }
    }
}
Also used : ObjectId(org.apache.qpid.qmf2.common.ObjectId) QmfConsoleData(org.apache.qpid.qmf2.console.QmfConsoleData) Date(java.util.Date)

Example 3 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class ConnectionLogger method onEvent.

/**
     * Listener for QMF2 WorkItems
     * <p>
     * This method looks for clientConnect or clientDisconnect Events and uses these as a trigger to log the new
     * connection state when the next Heartbeat occurs.
     * <p>
     * There are a couple of reasons for using this approach rather than just calling logConnectionInformation()
     * as soon as we see the clientConnect or clientDisconnect Event.
     * <p>
     * 1. We could potentially have lots of connection Events and redisplaying all of the connections for each
     *    Event is likely to be confusing.
     * <p>
     * 2. When a clientConnect Event occurs we don't have all of the informatin that we might need, for example this
     *    application checks the Session and Subscription information and also optionally Queue and Binding information.
     *    Creating Sessions/Subscriptions won't generally occur until some (possibly small, but possibly not) time
     *    after the Connection has been made. The approach taken here reduces spurious assertions that a Session is
     *    probably a "producer only" Session. As one of the use-cases for this tool is to attempt to flag up "producer
     *    only" Sessions we want to try and make it as reliable as possible.
     *
     * @param wi a QMF2 WorkItem object
     */
public void onEvent(final WorkItem wi) {
    if (wi instanceof EventReceivedWorkItem) {
        EventReceivedWorkItem item = (EventReceivedWorkItem) wi;
        Agent agent = item.getAgent();
        QmfEvent event = item.getEvent();
        String className = event.getSchemaClassId().getClassName();
        if (className.equals("clientConnect") || className.equals("clientDisconnect")) {
            _stateChanged = true;
        }
    } else if (wi instanceof AgentRestartedWorkItem) {
        _stateChanged = true;
    } else if (wi instanceof AgentHeartbeatWorkItem) {
        AgentHeartbeatWorkItem item = (AgentHeartbeatWorkItem) wi;
        Agent agent = item.getAgent();
        if (_stateChanged && agent.getName().contains("qpidd")) {
            logConnectionInformation();
            _stateChanged = false;
        }
    }
}
Also used : Agent(org.apache.qpid.qmf2.console.Agent) AgentRestartedWorkItem(org.apache.qpid.qmf2.console.AgentRestartedWorkItem) EventReceivedWorkItem(org.apache.qpid.qmf2.console.EventReceivedWorkItem) AgentHeartbeatWorkItem(org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem) QmfEvent(org.apache.qpid.qmf2.common.QmfEvent)

Example 4 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class Console method onMessage.

/**
     * MessageListener for QMF2 Agent Events, Hearbeats and Asynchronous data indications
     *
     * @param message the JMS Message passed to the listener
     */
public void onMessage(Message message) {
    try {
        String agentName = QmfData.getString(message.getObjectProperty("qmf.agent"));
        String content = QmfData.getString(message.getObjectProperty("qmf.content"));
        String opcode = QmfData.getString(message.getObjectProperty("qmf.opcode"));
        if (opcode.equals("_agent_heartbeat_indication") || opcode.equals("_agent_locate_response")) {
            // This block handles Agent lifecycle information (discover, register, delete)
            if (_agents.containsKey(agentName)) {
                // This block handles Agents that have previously been registered
                Agent agent = _agents.get(agentName);
                long originalEpoch = agent.getEpoch();
                // If we already know about an Agent we simply update the Agent's state using initialise()
                agent.initialise(AMQPMessage.getMap(message));
                // If the Epoch has changed it means the Agent has been restarted so we send a notification
                if (agent.getEpoch() != originalEpoch) {
                    // Clear cache to force a lookup
                    agent.clearSchemaCache();
                    List<SchemaClassId> classes = getClasses(agent);
                    // Discover the schema for this Agent and cache it
                    getSchema(classes, agent);
                    _log.info("Agent {} has been restarted", agentName);
                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                        _eventListener.onEvent(new AgentRestartedWorkItem(agent));
                    }
                } else {
                    // Otherwise just send a heartbeat notification
                    _log.info("Agent {} heartbeat", agent.getName());
                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                        _eventListener.onEvent(new AgentHeartbeatWorkItem(agent));
                    }
                }
            } else {
                // This block handles Agents that haven't already been registered
                Agent agent = new Agent(AMQPMessage.getMap(message), this);
                List<SchemaClassId> classes = getClasses(agent);
                // Discover the schema for this Agent and cache it
                getSchema(classes, agent);
                _agents.put(agentName, agent);
                _log.info("Adding Agent {}", agentName);
                // the Agent more "user friendly" than using the full Agent name.
                if (agent.getVendor().equals("apache.org") && agent.getProduct().equals("qpidd")) {
                    _log.info("Recording {} as _brokerAgentName", agentName);
                    _brokerAgentName = agentName;
                }
                // wait for the broker Agent to become available.
                if (_brokerAgentName != null) {
                    synchronized (this) {
                        _agentAvailable = true;
                        notifyAll();
                    }
                }
                if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                    _eventListener.onEvent(new AgentAddedWorkItem(agent));
                }
            }
            // The broker Agent sends periodic heartbeats and that Agent should *always* be available given
            // a running broker, so we should get here every "--mgmt-pub-interval" seconds or so, so it's
            // a good place to periodically check for the expiry of any other Agents.
            handleAgentExpiry();
            return;
        }
        if (!_agents.containsKey(agentName)) {
            _log.info("Ignoring Event from unregistered Agent {}", agentName);
            return;
        }
        Agent agent = _agents.get(agentName);
        if (!agent.eventsEnabled()) {
            _log.info("{} has disabled Event reception, ignoring Event", agentName);
            return;
        }
        // If we get to here the Agent from whence the Event came should be registered and should
        // have Event reception enabled, so we should be able to send events to the EventListener
        Handle handle = new Handle(message.getJMSCorrelationID());
        if (opcode.equals("_method_response") || opcode.equals("_exception")) {
            if (AMQPMessage.isAMQPMap(message)) {
                _eventListener.onEvent(new MethodResponseWorkItem(handle, new MethodResult(AMQPMessage.getMap(message))));
            } else {
                _log.info("onMessage() Received Method Response message in incorrect format");
            }
        }
        // refresh() call on QmfConsoleData so the number of results in the returned list *should* be one.
        if (opcode.equals("_query_response") && content.equals("_data")) {
            if (AMQPMessage.isAMQPList(message)) {
                List<Map> list = AMQPMessage.getList(message);
                for (Map m : list) {
                    _eventListener.onEvent(new ObjectUpdateWorkItem(handle, new QmfConsoleData(m, agent)));
                }
            } else {
                _log.info("onMessage() Received Query Response message in incorrect format");
            }
        }
        // This block handles responses to createSubscription and refreshSubscription
        if (opcode.equals("_subscribe_response")) {
            if (AMQPMessage.isAMQPMap(message)) {
                String correlationId = message.getJMSCorrelationID();
                SubscribeParams params = new SubscribeParams(correlationId, AMQPMessage.getMap(message));
                String subscriptionId = params.getSubscriptionId();
                if (subscriptionId != null && correlationId != null) {
                    SubscriptionManager subscription = _subscriptionById.get(subscriptionId);
                    if (subscription == null) {
                        // This is a createSubscription response so the correlationId should be the consoleHandle
                        subscription = _subscriptionByHandle.get(correlationId);
                        if (subscription != null) {
                            _subscriptionById.put(subscriptionId, subscription);
                            subscription.setSubscriptionId(subscriptionId);
                            subscription.setDuration(params.getLifetime());
                            String replyHandle = subscription.getReplyHandle();
                            if (replyHandle == null) {
                                subscription.signal();
                            } else {
                                _eventListener.onEvent(new SubscribeResponseWorkItem(new Handle(replyHandle), params));
                            }
                        }
                    } else {
                        // This is a refreshSubscription response
                        params.setConsoleHandle(subscription.getConsoleHandle());
                        subscription.setDuration(params.getLifetime());
                        subscription.refresh();
                        _eventListener.onEvent(new SubscribeResponseWorkItem(handle, params));
                    }
                }
            } else {
                _log.info("onMessage() Received Subscribe Response message in incorrect format");
            }
        }
        // Subscription Indication - in other words the asynchronous results of a Subscription
        if (opcode.equals("_data_indication") && content.equals("_data")) {
            if (AMQPMessage.isAMQPList(message)) {
                String consoleHandle = handle.getCorrelationId();
                if (consoleHandle != null && _subscriptionByHandle.containsKey(consoleHandle)) {
                    // If we have a valid consoleHandle the data has come from a "real" Subscription.
                    List<Map> list = AMQPMessage.getList(message);
                    List<QmfConsoleData> resultList = new ArrayList<QmfConsoleData>(list.size());
                    for (Map m : list) {
                        resultList.add(new QmfConsoleData(m, agent));
                    }
                    _eventListener.onEvent(new SubscriptionIndicationWorkItem(new SubscribeIndication(consoleHandle, resultList)));
                } else if (_subscriptionEmulationEnabled && agentName.equals(_brokerAgentName)) {
                    // If the data has come from is the broker Agent we emulate a Subscription on the Console
                    for (SubscriptionManager subscription : _subscriptionByHandle.values()) {
                        QmfQuery query = subscription.getQuery();
                        if (subscription.getAgent().getName().equals(_brokerAgentName) && query.getTarget() == QmfQueryTarget.OBJECT) {
                            // Only evaluate broker Agent subscriptions with QueryTarget == OBJECT on the Console.
                            long objectEpoch = 0;
                            consoleHandle = subscription.getConsoleHandle();
                            List<Map> list = AMQPMessage.getList(message);
                            List<QmfConsoleData> resultList = new ArrayList<QmfConsoleData>(list.size());
                            for (Map m : list) {
                                // Evaluate the QmfConsoleData object against the query
                                QmfConsoleData object = new QmfConsoleData(m, agent);
                                if (query.evaluate(object)) {
                                    long epoch = object.getObjectId().getAgentEpoch();
                                    objectEpoch = (epoch > objectEpoch && !object.isDeleted()) ? epoch : objectEpoch;
                                    resultList.add(object);
                                }
                            }
                            if (resultList.size() > 0) {
                                // data from the restarted Agent (in case they need to reset any state).
                                if (objectEpoch > agent.getEpoch()) {
                                    agent.setEpoch(objectEpoch);
                                    // Clear cache to force a lookup
                                    agent.clearSchemaCache();
                                    List<SchemaClassId> classes = getClasses(agent);
                                    // Discover the schema for this Agent and cache it
                                    getSchema(classes, agent);
                                    _log.info("Agent {} has been restarted", agentName);
                                    if (_discoverAgents && (_agentQuery == null || _agentQuery.evaluate(agent))) {
                                        _eventListener.onEvent(new AgentRestartedWorkItem(agent));
                                    }
                                }
                                _eventListener.onEvent(new SubscriptionIndicationWorkItem(new SubscribeIndication(consoleHandle, resultList)));
                            }
                        }
                    }
                }
            } else {
                _log.info("onMessage() Received Subscribe Indication message in incorrect format");
            }
        }
        // The results of an Event delivered from an Agent
        if (opcode.equals("_data_indication") && content.equals("_event")) {
            // There are differences in the type of message sent by Qpid 0.8 and 0.10 onwards.
            if (AMQPMessage.isAMQPMap(message)) {
                // 0.8 broker passes Events as amqp/map encoded as MapMessages (we convert into java.util.Map)
                _eventListener.onEvent(new EventReceivedWorkItem(agent, new QmfEvent(AMQPMessage.getMap(message))));
            } else if (AMQPMessage.isAMQPList(message)) {
                // 0.10 and above broker passes Events as amqp/list encoded as BytesMessage (needs decoding)
                // 0.20 encodes amqp/list in a MapMessage!!?? AMQPMessage hopefully abstracts this detail.
                List<Map> list = AMQPMessage.getList(message);
                for (Map m : list) {
                    _eventListener.onEvent(new EventReceivedWorkItem(agent, new QmfEvent(m)));
                }
            } else {
                _log.info("onMessage() Received Event message in incorrect format");
            }
        }
    } catch (JMSException jmse) {
        _log.info("JMSException {} caught in onMessage()", jmse.getMessage());
    }
}
Also used : ArrayList(java.util.ArrayList) QmfEvent(org.apache.qpid.qmf2.common.QmfEvent) JMSException(javax.jms.JMSException) ArrayList(java.util.ArrayList) List(java.util.List) SchemaClassId(org.apache.qpid.qmf2.common.SchemaClassId) Handle(org.apache.qpid.qmf2.common.Handle) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) QmfQuery(org.apache.qpid.qmf2.common.QmfQuery)

Example 5 with Subscription

use of org.apache.qpid.qmf2.agent.Subscription in project qpid by apache.

the class Agent method evaluateQuery.

/**
     * This method evaluates a QmfQuery over the Agent's data on behalf of a Subscription.
     *
     * @param query the QmfQuery that the Subscription wants to be evaluated over the Agent's data.
     * @return a List of QmfAgentData objects that match the specified QmfQuery.
     */
public final List<QmfAgentData> evaluateQuery(final QmfQuery query) {
    List<QmfAgentData> results = new ArrayList<QmfAgentData>(_objectIndex.size());
    if (query.getTarget() == QmfQueryTarget.OBJECT) {
        // destroyed we asynchronously publish its new state to subscribers, see QmfAgentData.destroy() method.
        if (query.getObjectId() != null) {
            // Look up a QmfAgentData object by the ObjectId obtained from the query
            ObjectId objectId = query.getObjectId();
            QmfAgentData object = _objectIndex.get(objectId);
            if (object != null && !object.isDeleted()) {
                results.add(object);
            }
        } else {
            // Look up QmfAgentData objects evaluating the query
            for (QmfAgentData object : _objectIndex.values()) {
                if (!object.isDeleted() && query.evaluate(object)) {
                    results.add(object);
                }
            }
        }
    }
    return results;
}
Also used : ObjectId(org.apache.qpid.qmf2.common.ObjectId) ArrayList(java.util.ArrayList)

Aggregations

QmfException (org.apache.qpid.qmf2.common.QmfException)9 ObjectId (org.apache.qpid.qmf2.common.ObjectId)8 QmfQuery (org.apache.qpid.qmf2.common.QmfQuery)6 JMSException (javax.jms.JMSException)5 Handle (org.apache.qpid.qmf2.common.Handle)5 QmfData (org.apache.qpid.qmf2.common.QmfData)4 QmfConsoleData (org.apache.qpid.qmf2.console.QmfConsoleData)4 ArrayList (java.util.ArrayList)3 Date (java.util.Date)3 MapMessage (javax.jms.MapMessage)3 QmfAgentData (org.apache.qpid.qmf2.agent.QmfAgentData)3 QmfEvent (org.apache.qpid.qmf2.common.QmfEvent)3 SchemaClassId (org.apache.qpid.qmf2.common.SchemaClassId)3 AddressParser (org.apache.qpid.messaging.util.AddressParser)2 Subscription (org.apache.qpid.qmf2.agent.Subscription)2 AgentHeartbeatWorkItem (org.apache.qpid.qmf2.console.AgentHeartbeatWorkItem)2 AgentRestartedWorkItem (org.apache.qpid.qmf2.console.AgentRestartedWorkItem)2 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1