/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

package org.apache.cassandra.gms;

import java.lang.management.ManagementFactory;
import java.net.UnknownHostException;
import java.util.*;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import com.cloudius.urchin.api.APIClient;

public class FailureDetector implements FailureDetectorMBean {
    public static final String MBEAN_NAME = "org.apache.cassandra.net:type=FailureDetector";
    private static final java.util.logging.Logger logger = java.util.logging.Logger
            .getLogger(FailureDetector.class.getName());

    private APIClient c = new APIClient();

    public void log(String str) {
        logger.info(str);
    }

    private static final FailureDetector instance = new FailureDetector();

    public static FailureDetector getInstance() {
        return instance;
    }

    private FailureDetector() {
        // Register this instance with JMX
        try {
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            mbs.registerMBean(this, new ObjectName(MBEAN_NAME));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void dumpInterArrivalTimes() {
        log(" dumpInterArrivalTimes()");
    }

    public void setPhiConvictThreshold(double phi) {
        log(" setPhiConvictThreshold(double phi)");        
    }

    public double getPhiConvictThreshold() {
        log(" getPhiConvictThreshold()");
        return c.getDoubleValue("/failure_detector/phi");
    }

    public String getAllEndpointStates() {
        log(" getAllEndpointStates()");
        return c.getStringValue("/failure_detector/endpoints");
    }

    public String getEndpointState(String address) throws UnknownHostException {
        log(" getEndpointState(String address) throws UnknownHostException");
        return c.getStringValue("/failure_detector/endpoints/states/" +  address);
    }

    public Map<String, String> getSimpleStates() {
        log(" getSimpleStates()");
        return c.getMapStrValue("/failure_detector/simple_states");
    }

    public int getDownEndpointCount() {
        log(" getDownEndpointCount()");
        return c.getIntValue("/failure_detector/count/endpoint/down");
    }

    public int getUpEndpointCount() {
        log(" getUpEndpointCount()");
        return c.getIntValue("/failure_detector/count/endpoint/up");
    }

}

@@ -1017,16 +1017,76 @@
 .util.*;
+%0A%0Aimport javax.json.JsonArray;%0Aimport javax.json.JsonObject;
 %0Aimport 
@@ -2276,24 +2276,16 @@
  phi)%22);
-        
 %0A    %7D%0A%0A
@@ -2515,32 +2515,33 @@
 States()%22);%0A
+%0A
         
 return c.get
@@ -2532,62 +2532,1863 @@
     
-return c.getStringValue(%22/failure_detector/endpoints%22)
+StringBuilder sb = new StringBuilder();%0A        for (Map.Entry%3CString, EndpointState%3E entry : getEndpointStateMap().entrySet())%0A        %7B%0A            sb.append(entry.getKey()).append(%22%5Cn%22);%0A            appendEndpointState(sb, entry.getValue());%0A        %7D%0A        return sb.toString();%0A    %7D%0A%0A    private void appendEndpointState(StringBuilder sb, EndpointState endpointState)%0A    %7B%0A        sb.append(%22  generation:%22).append(endpointState.getHeartBeatState().getGeneration()).append(%22%5Cn%22);%0A        sb.append(%22  heartbeat:%22).append(endpointState.getHeartBeatState().getHeartBeatVersion()).append(%22%5Cn%22);%0A        for (Map.Entry%3CApplicationState, String%3E state : endpointState.applicationState.entrySet())%0A        %7B%0A            if (state.getKey() == ApplicationState.TOKENS)%0A                continue;%0A            sb.append(%22  %22).append(state.getKey()).append(%22:%22).append(state.getValue()).append(%22%5Cn%22);%0A        %7D%0A    %7D%0A%0A    public Map%3CString, EndpointState%3E getEndpointStateMap() %7B%0A        Map%3CString, EndpointState%3E res = new HashMap%3CString, EndpointState%3E();%0A        JsonArray arr = c.getJsonArray(%22/failure_detector/endpoints%22);%0A        for (int i = 0; i %3C arr.size(); i++) %7B%0A            JsonObject obj = arr.getJsonObject(i);%0A            EndpointState ep = new EndpointState(new HeartBeatState(obj.getInt(%22generation%22), obj.getInt(%22version%22)));%0A            ep.setAliave(obj.getBoolean(%22is_alive%22));%0A            ep.setUpdateTimestamp(obj.getJsonNumber(%22update_time%22).longValue());%0A            JsonArray states = obj.getJsonArray(%22application_state%22);%0A            for (int j = 0; j %3C states.size(); j++) %7B%0A                JsonObject state = states.getJsonObject(j);%0A                ep.addApplicationState(state.getInt(%22application_state%22), state.getString(%22value%22));%0A            %7D%0A            res.put(obj.getString(%22addrs%22), ep);%0A        %7D%0A        return res
 ;%0A  

Change getAllEndpointStates implementation