io.druid.server.http.InfoResource.java Source code

Java tutorial

Introduction

Here is the source code for io.druid.server.http.InfoResource.java

Source

/*
 * Druid - a distributed column store.
 * Copyright (C) 2012, 2013  Metamarkets Group Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package io.druid.server.http;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import io.druid.client.DruidDataSource;
import io.druid.client.DruidServer;
import io.druid.client.InventoryView;
import io.druid.client.indexing.IndexingServiceClient;
import io.druid.db.DatabaseRuleManager;
import io.druid.db.DatabaseSegmentManager;
import io.druid.server.coordinator.DruidCoordinator;
import io.druid.server.coordinator.rules.LoadRule;
import io.druid.server.coordinator.rules.Rule;
import io.druid.timeline.DataSegment;
import org.joda.time.Interval;

import javax.annotation.Nullable;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 */
@Deprecated
@Path("/info")
public class InfoResource {
    private static final Function<DruidServer, Map<String, Object>> simplifyClusterFn = new Function<DruidServer, Map<String, Object>>() {
        @Override
        public Map<String, Object> apply(DruidServer server) {
            return new ImmutableMap.Builder<String, Object>().put("host", server.getHost())
                    .put("type", server.getType()).put("tier", server.getTier())
                    .put("currSize", server.getCurrSize()).put("maxSize", server.getMaxSize())
                    .put("segments", Collections2.transform(server.getSegments().values(),
                            new Function<DataSegment, Map<String, Object>>() {
                                @Override
                                public Map<String, Object> apply(DataSegment segment) {
                                    return new ImmutableMap.Builder<String, Object>()
                                            .put("id", segment.getIdentifier())
                                            .put("dataSource", segment.getDataSource())
                                            .put("interval", segment.getInterval().toString())
                                            .put("version", segment.getVersion()).put("size", segment.getSize())
                                            .build();
                                }
                            }))
                    .build();
        }
    };

    private final DruidCoordinator coordinator;
    private final InventoryView serverInventoryView;
    private final DatabaseSegmentManager databaseSegmentManager;
    private final DatabaseRuleManager databaseRuleManager;
    private final IndexingServiceClient indexingServiceClient;

    private final ObjectMapper jsonMapper;

    @Inject
    public InfoResource(DruidCoordinator coordinator, InventoryView serverInventoryView,
            DatabaseSegmentManager databaseSegmentManager, DatabaseRuleManager databaseRuleManager,
            @Nullable IndexingServiceClient indexingServiceClient, ObjectMapper jsonMapper) {
        this.coordinator = coordinator;
        this.serverInventoryView = serverInventoryView;
        this.databaseSegmentManager = databaseSegmentManager;
        this.databaseRuleManager = databaseRuleManager;
        this.indexingServiceClient = indexingServiceClient;
        this.jsonMapper = jsonMapper;
    }

    @GET
    @Path("/coordinator")
    @Produces("application/json")
    public Response getMaster() {
        return Response.status(Response.Status.OK).entity(coordinator.getCurrentLeader()).build();
    }

    @GET
    @Path("/cluster")
    @Produces("application/json")
    public Response getClusterInfo(@QueryParam("full") String full) {
        if (full != null) {
            return Response.ok(serverInventoryView.getInventory()).build();
        }
        return Response
                .ok(Lists.newArrayList(Iterables.transform(serverInventoryView.getInventory(), simplifyClusterFn)))
                .build();
    }

    @GET
    @Path("/servers")
    @Produces("application/json")
    public Response getClusterServers(@QueryParam("full") String full) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (full != null) {
            return builder.entity(Lists.newArrayList(serverInventoryView.getInventory())).build();
        }

        return builder.entity(Lists.newArrayList(
                Iterables.transform(serverInventoryView.getInventory(), new Function<DruidServer, String>() {
                    @Override
                    public String apply(DruidServer druidServer) {
                        return druidServer.getHost();
                    }
                }))).build();
    }

    @GET
    @Path("/servers/{serverName}")
    @Produces("application/json")
    public Response getServer(@PathParam("serverName") String serverName) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        DruidServer server = serverInventoryView.getInventoryValue(serverName);
        if (server == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return builder.status(Response.Status.OK).entity(server).build();
    }

    @GET
    @Path("/servers/{serverName}/segments")
    @Produces("application/json")
    public Response getServerSegments(@PathParam("serverName") String serverName, @QueryParam("full") String full) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        DruidServer server = serverInventoryView.getInventoryValue(serverName);
        if (server == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        if (full != null) {
            return builder.entity(server.getSegments().values()).build();
        }

        return builder
                .entity(Collections2.transform(server.getSegments().values(), new Function<DataSegment, String>() {
                    @Override
                    public String apply(@Nullable DataSegment segment) {
                        return segment.getIdentifier();
                    }
                })).build();
    }

    @GET
    @Path("/servers/{serverName}/segments/{segmentId}")
    @Produces("application/json")
    public Response getServerSegment(@PathParam("serverName") String serverName,
            @PathParam("segmentId") String segmentId) {
        DruidServer server = serverInventoryView.getInventoryValue(serverName);
        if (server == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        DataSegment segment = server.getSegment(segmentId);
        if (segment == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.status(Response.Status.OK).entity(segment).build();
    }

    @GET
    @Path("/segments")
    @Produces("application/json")
    public Response getClusterSegments(@QueryParam("full") String full) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (full != null) {
            return builder.entity(
                    Lists.newArrayList(Iterables.concat(Iterables.transform(serverInventoryView.getInventory(),
                            new Function<DruidServer, Iterable<DataSegment>>() {
                                @Override
                                public Iterable<DataSegment> apply(@Nullable DruidServer druidServer) {
                                    return druidServer.getSegments().values();
                                }
                            }))))
                    .build();
        }

        return builder.entity(Lists.newArrayList(Iterables.concat(Iterables
                .transform(serverInventoryView.getInventory(), new Function<DruidServer, Iterable<String>>() {
                    @Override
                    public Iterable<String> apply(@Nullable DruidServer druidServer) {
                        return Collections2.transform(druidServer.getSegments().values(),
                                new Function<DataSegment, String>() {
                                    @Override
                                    public String apply(@Nullable DataSegment segment) {
                                        return segment.getIdentifier();
                                    }
                                });
                    }
                })))).build();
    }

    @GET
    @Path("/segments/{segmentId}")
    @Produces("application/json")
    public Response getClusterSegment(@PathParam("segmentId") String segmentId) {
        for (DruidServer server : serverInventoryView.getInventory()) {
            if (server.getSegments().containsKey(segmentId)) {
                return Response.status(Response.Status.OK).entity(server.getSegments().get(segmentId)).build();
            }
        }

        return Response.status(Response.Status.NOT_FOUND).build();
    }

    @GET
    @Path("/tiers")
    @Produces("application/json")
    public Response getTiers() {
        Set<String> tiers = Sets.newHashSet();
        for (DruidServer server : serverInventoryView.getInventory()) {
            tiers.add(server.getTier());
        }
        return Response.status(Response.Status.OK).entity(tiers).build();
    }

    @GET
    @Path("/rules")
    @Produces("application/json")
    public Response getRules() {
        // FUGLY, backwards compatibility
        // This will def. be removed as part of the next release
        return Response.ok()
                .entity(Maps.transformValues(databaseRuleManager.getAllRules(), new Function<List<Rule>, Object>() {
                    @Override
                    public Object apply(List<Rule> rules) {
                        return Lists.transform(rules, new Function<Rule, Object>() {
                            @Override
                            public Object apply(Rule rule) {
                                if (rule instanceof LoadRule) {
                                    Map<String, Object> newRule = jsonMapper.convertValue(rule,
                                            new TypeReference<Map<String, Object>>() {
                                            });
                                    Set<String> tiers = Sets
                                            .newHashSet(((LoadRule) rule).getTieredReplicants().keySet());
                                    tiers.remove(DruidServer.DEFAULT_TIER);
                                    String tier = DruidServer.DEFAULT_TIER;
                                    if (!tiers.isEmpty()) {
                                        tier = tiers.iterator().next();
                                    }

                                    newRule.put("tier", tier);
                                    newRule.put("replicants", ((LoadRule) rule).getNumReplicants(tier));

                                    return newRule;
                                }
                                return rule;
                            }
                        });
                    }
                })).build();
    }

    @GET
    @Path("/rules/{dataSourceName}")
    @Produces("application/json")
    public Response getDatasourceRules(@PathParam("dataSourceName") final String dataSourceName,
            @QueryParam("full") final String full

    ) {
        if (full != null) {
            return Response.ok(databaseRuleManager.getRulesWithDefault(dataSourceName)).build();
        }
        return Response.ok(databaseRuleManager.getRules(dataSourceName)).build();
    }

    @POST
    @Path("/rules/{dataSourceName}")
    @Consumes("application/json")
    public Response setDatasourceRules(@PathParam("dataSourceName") final String dataSourceName,
            final List<Rule> rules) {
        if (databaseRuleManager.overrideRule(dataSourceName, rules)) {
            return Response.status(Response.Status.OK).build();
        }
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
    }

    @GET
    @Path("/datasources")
    @Produces("application/json")
    public Response getQueryableDataSources(@QueryParam("full") String full) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (full != null) {
            return builder.entity(getDataSources()).build();
        }

        return builder.entity(
                Lists.newArrayList(Iterables.transform(getDataSources(), new Function<DruidDataSource, String>() {
                    @Override
                    public String apply(@Nullable DruidDataSource dataSource) {
                        return dataSource.getName();
                    }
                }))).build();
    }

    @GET
    @Path("/datasources/{dataSourceName}")
    @Produces("application/json")
    public Response getTheDataSource(@PathParam("dataSourceName") final String dataSourceName) {
        DruidDataSource dataSource = getDataSource(dataSourceName.toLowerCase());
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.ok(dataSource).build();
    }

    @DELETE
    @Path("/datasources/{dataSourceName}")
    public Response deleteDataSource(@PathParam("dataSourceName") final String dataSourceName,
            @QueryParam("kill") final String kill, @QueryParam("interval") final String interval) {
        // This is weird enough to have warranted some sort of T0D0 comment at one point, but it will likely be all
        // rewritten once Guice introduced, and that's the brunt of the information that was in the original T0D0 too.
        if (indexingServiceClient == null) {
            return Response.status(Response.Status.OK).entity(ImmutableMap.of("error", "no indexing service found"))
                    .build();
        }
        if (kill != null && Boolean.valueOf(kill)) {
            indexingServiceClient.killSegments(dataSourceName, new Interval(interval));
        } else {
            if (!databaseSegmentManager.removeDatasource(dataSourceName)) {
                return Response.status(Response.Status.NOT_FOUND).build();
            }
        }

        return Response.status(Response.Status.OK).build();
    }

    @POST
    @Path("/datasources/{dataSourceName}")
    @Consumes("application/json")
    public Response enableDataSource(@PathParam("dataSourceName") final String dataSourceName) {
        if (!databaseSegmentManager.enableDatasource(dataSourceName)) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.status(Response.Status.OK).build();
    }

    @GET
    @Path("/datasources/{dataSourceName}/segments")
    @Produces("application/json")
    public Response getSegmentDataSourceSegments(@PathParam("dataSourceName") String dataSourceName,
            @QueryParam("full") String full) {
        DruidDataSource dataSource = getDataSource(dataSourceName.toLowerCase());
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (full != null) {
            return builder.entity(dataSource.getSegments()).build();
        }

        return builder.entity(Iterables.transform(dataSource.getSegments(), new Function<DataSegment, Object>() {
            @Override
            public Object apply(@Nullable DataSegment segment) {
                return segment.getIdentifier();
            }
        })).build();
    }

    @GET
    @Path("/datasources/{dataSourceName}/segments/{segmentId}")
    @Produces("application/json")
    public Response getSegmentDataSourceSegment(@PathParam("dataSourceName") String dataSourceName,
            @PathParam("segmentId") String segmentId) {
        DruidDataSource dataSource = getDataSource(dataSourceName.toLowerCase());
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        for (DataSegment segment : dataSource.getSegments()) {
            if (segment.getIdentifier().equalsIgnoreCase(segmentId)) {
                return Response.status(Response.Status.OK).entity(segment).build();
            }
        }
        return Response.status(Response.Status.NOT_FOUND).build();
    }

    @DELETE
    @Path("/datasources/{dataSourceName}/segments/{segmentId}")
    public Response deleteDatasourceSegment(@PathParam("dataSourceName") String dataSourceName,
            @PathParam("segmentId") String segmentId) {
        if (!databaseSegmentManager.removeSegment(dataSourceName, segmentId)) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.status(Response.Status.OK).build();
    }

    @POST
    @Path("/datasources/{dataSourceName}/segments/{segmentId}")
    @Consumes("application/json")
    public Response enableDatasourceSegment(@PathParam("dataSourceName") String dataSourceName,
            @PathParam("segmentId") String segmentId) {
        if (!databaseSegmentManager.enableSegment(segmentId)) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.status(Response.Status.OK).build();
    }

    private DruidDataSource getDataSource(final String dataSourceName) {
        Iterable<DruidDataSource> dataSources = Iterables.concat(Iterables
                .transform(serverInventoryView.getInventory(), new Function<DruidServer, DruidDataSource>() {
                    @Override
                    public DruidDataSource apply(@Nullable DruidServer input) {
                        return input.getDataSource(dataSourceName);
                    }
                }));

        List<DruidDataSource> validDataSources = Lists.newArrayList();
        for (DruidDataSource dataSource : dataSources) {
            if (dataSource != null) {
                validDataSources.add(dataSource);
            }
        }
        if (validDataSources.isEmpty()) {
            return null;
        }

        Map<String, DataSegment> segmentMap = Maps.newHashMap();
        for (DruidDataSource dataSource : validDataSources) {
            if (dataSource != null) {
                Iterable<DataSegment> segments = dataSource.getSegments();
                for (DataSegment segment : segments) {
                    segmentMap.put(segment.getIdentifier(), segment);
                }
            }
        }

        return new DruidDataSource(dataSourceName, ImmutableMap.<String, String>of()).addSegments(segmentMap);
    }

    private Set<DruidDataSource> getDataSources() {
        TreeSet<DruidDataSource> dataSources = Sets.newTreeSet(new Comparator<DruidDataSource>() {
            @Override
            public int compare(DruidDataSource druidDataSource, DruidDataSource druidDataSource1) {
                return druidDataSource.getName().compareTo(druidDataSource1.getName());
            }
        });
        dataSources
                .addAll(Lists.newArrayList(Iterables.concat(Iterables.transform(serverInventoryView.getInventory(),
                        new Function<DruidServer, Iterable<DruidDataSource>>() {
                            @Override
                            public Iterable<DruidDataSource> apply(@Nullable DruidServer input) {
                                return input.getDataSources();
                            }
                        }))));
        return dataSources;
    }

    @GET
    @Path("/db/datasources")
    @Produces("application/json")
    public Response getDatabaseDataSources(@QueryParam("full") String full,
            @QueryParam("includeDisabled") String includeDisabled) {
        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (includeDisabled != null) {
            return builder.entity(databaseSegmentManager.getAllDatasourceNames()).build();
        }
        if (full != null) {
            return builder.entity(databaseSegmentManager.getInventory()).build();
        }

        List<String> dataSourceNames = Lists.newArrayList(
                Iterables.transform(databaseSegmentManager.getInventory(), new Function<DruidDataSource, String>() {
                    @Override
                    public String apply(@Nullable DruidDataSource dataSource) {
                        return dataSource.getName();
                    }
                }));

        Collections.sort(dataSourceNames);

        return builder.entity(dataSourceNames).build();
    }

    @GET
    @Path("/db/datasources/{dataSourceName}")
    @Produces("application/json")
    public Response getDatabaseSegmentDataSource(@PathParam("dataSourceName") final String dataSourceName) {
        DruidDataSource dataSource = databaseSegmentManager.getInventoryValue(dataSourceName);
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        return Response.status(Response.Status.OK).entity(dataSource).build();
    }

    @GET
    @Path("/db/datasources/{dataSourceName}/segments")
    @Produces("application/json")
    public Response getDatabaseSegmentDataSourceSegments(@PathParam("dataSourceName") String dataSourceName,
            @QueryParam("full") String full) {
        DruidDataSource dataSource = databaseSegmentManager.getInventoryValue(dataSourceName);
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        Response.ResponseBuilder builder = Response.status(Response.Status.OK);
        if (full != null) {
            return builder.entity(dataSource.getSegments()).build();
        }

        return builder.entity(Iterables.transform(dataSource.getSegments(), new Function<DataSegment, Object>() {
            @Override
            public Object apply(@Nullable DataSegment segment) {
                return segment.getIdentifier();
            }
        })).build();
    }

    @GET
    @Path("/db/datasources/{dataSourceName}/segments/{segmentId}")
    @Produces("application/json")
    public Response getDatabaseSegmentDataSourceSegment(@PathParam("dataSourceName") String dataSourceName,
            @PathParam("segmentId") String segmentId) {
        DruidDataSource dataSource = databaseSegmentManager.getInventoryValue(dataSourceName);
        if (dataSource == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }

        for (DataSegment segment : dataSource.getSegments()) {
            if (segment.getIdentifier().equalsIgnoreCase(segmentId)) {
                return Response.status(Response.Status.OK).entity(segment).build();
            }
        }
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}