/** * Update the history store with the value of an an read, write or execute operation. Also, the * timestamp of the insertion is recorded. Also, the recorded history values are added to the * given json value. * * @param pJmxReq request for which an entry should be added in this history store * @param pJson the JSONObject to which to add the history. */ public synchronized void updateAndAdd(JmxRequest pJmxReq, JSONObject pJson) { long timestamp = System.currentTimeMillis() / 1000; pJson.put(KEY_TIMESTAMP, timestamp); JmxRequest.Type type = pJmxReq.getType(); if (type == EXEC || type == WRITE) { HistoryEntry entry = historyStore.get(new HistoryKey(pJmxReq)); if (entry != null) { synchronized (entry) { // A history data to json object for the response pJson.put(KEY_HISTORY, entry.jsonifyValues()); // Update history for next time if (type == EXEC) { entry.add(pJson.get(KEY_VALUE), timestamp); } else if (type == WRITE) { // The new value to set as string representation entry.add(pJmxReq.getValue(), timestamp); } } } } else if (type == READ) { updateReadHistory(pJmxReq, pJson, timestamp); } }
// Update potentially multiple history entries for a READ request which could // return multiple values with a single request private void updateReadHistory(JmxRequest pJmxReq, JSONObject pJson, long pTimestamp) { ObjectName name = pJmxReq.getObjectName(); if (name.isPattern()) { // We have a pattern and hence a value structure // of bean -> attribute_key -> attribute_value JSONObject history = new JSONObject(); for (Map.Entry<String, Object> beanEntry : ((Map<String, Object>) pJson.get(KEY_VALUE)).entrySet()) { String beanName = beanEntry.getKey(); JSONObject beanHistory = addAttributesFromComplexValue( pJmxReq, ((Map<String, Object>) beanEntry.getValue()), beanName, pTimestamp); if (beanHistory.size() > 0) { history.put(beanName, beanHistory); } } if (history.size() > 0) { pJson.put(KEY_HISTORY, history); } } else if (!pJmxReq.isSingleAttribute() || pJmxReq.getAttributeName() == null) { // Multiple attributes, but a single bean. // Value has the following structure: // attribute_key -> attribute_value JSONObject history = addAttributesFromComplexValue( pJmxReq, ((Map<String, Object>) pJson.get(KEY_VALUE)), pJmxReq.getObjectNameAsString(), pTimestamp); if (history.size() > 0) { pJson.put(KEY_HISTORY, history); } } else { // Single attribute, single bean. Value is the attribute_value // itself. addAttributeFromSingleValue( pJson, KEY_HISTORY, new HistoryKey(pJmxReq), pJson.get(KEY_VALUE), pTimestamp); } }
private JSONObject addAttributesFromComplexValue( JmxRequest pJmxReq, Map<String, Object> pAttributesMap, String pBeanName, long pTimestamp) { JSONObject ret = new JSONObject(); for (Map.Entry<String, Object> attrEntry : pAttributesMap.entrySet()) { String attrName = attrEntry.getKey(); Object value = attrEntry.getValue(); HistoryKey key; try { key = new HistoryKey( pBeanName, attrName, null /* No path support for complex read handling */, pJmxReq.getTargetConfigUrl()); } catch (MalformedObjectNameException e) { // Shouldnt occur since we get the MBeanName from a JMX operation's result. However, // we will rethrow it throw new IllegalArgumentException("Cannot pars MBean name " + pBeanName, e); } addAttributeFromSingleValue(ret, attrName, key, value, pTimestamp); } return ret; }