Search in sources :

Example 11 with Paths

use of com.linkedin.pinot.common.restlet.swagger.Paths in project pinot by linkedin.

the class PinotTableRestletResource method getTable.

@HttpVerb("get")
@Summary("Views a table's configuration")
@Tags({ "table" })
@Paths({ "/tables/{tableName}", "/tables/{tableName}/" })
private Representation getTable(@Parameter(name = "tableName", in = "path", description = "The name of the table for which to toggle its state", required = true) String tableName, @Parameter(name = "type", in = "query", description = "Type of table, Offline or Realtime", required = true) String tableType) throws JSONException, JsonParseException, JsonMappingException, JsonProcessingException, IOException {
    JSONObject ret = new JSONObject();
    if ((tableType == null || TableType.OFFLINE.name().equalsIgnoreCase(tableType)) && _pinotHelixResourceManager.hasOfflineTable(tableName)) {
        AbstractTableConfig config = _pinotHelixResourceManager.getTableConfig(tableName, TableType.OFFLINE);
        ret.put(TableType.OFFLINE.name(), config.toJSON());
    }
    if ((tableType == null || TableType.REALTIME.name().equalsIgnoreCase(tableType)) && _pinotHelixResourceManager.hasRealtimeTable(tableName)) {
        AbstractTableConfig config = _pinotHelixResourceManager.getTableConfig(tableName, TableType.REALTIME);
        ret.put(TableType.REALTIME.name(), config.toJSON());
    }
    return new StringRepresentation(ret.toString(2));
}
Also used : JSONObject(org.json.JSONObject) StringRepresentation(org.restlet.representation.StringRepresentation) AbstractTableConfig(com.linkedin.pinot.common.config.AbstractTableConfig) Summary(com.linkedin.pinot.common.restlet.swagger.Summary) HttpVerb(com.linkedin.pinot.common.restlet.swagger.HttpVerb) Paths(com.linkedin.pinot.common.restlet.swagger.Paths) Tags(com.linkedin.pinot.common.restlet.swagger.Tags)

Example 12 with Paths

use of com.linkedin.pinot.common.restlet.swagger.Paths in project pinot by linkedin.

the class PinotTableRestletResource method addTable.

@HttpVerb("post")
@Summary("Adds a table")
@Tags({ "table" })
@Paths({ "/tables", "/tables/" })
private void addTable(AbstractTableConfig config) throws IOException {
    // For self-serviced cluster, ensure that the tables are created with atleast
    // min replication factor irrespective of table configuratio value.
    SegmentsValidationAndRetentionConfig segmentsConfig = config.getValidationConfig();
    int requestReplication = segmentsConfig.getReplicationNumber();
    int configMinReplication = _controllerConf.getDefaultTableMinReplicas();
    if (requestReplication < configMinReplication) {
        LOGGER.info("Creating table with minimum replication factor of: {} instead of requested replication: {}", configMinReplication, requestReplication);
        segmentsConfig.setReplication(String.valueOf(configMinReplication));
    }
    if (segmentsConfig.getReplicasPerPartition() != null) {
        int replicasPerPartition = Integer.valueOf(segmentsConfig.getReplicasPerPartition());
        if (replicasPerPartition < configMinReplication) {
            LOGGER.info("Creating table with minimum replicasPerPartition of: {} instead of requested replicasPerPartition: {}", configMinReplication, requestReplication);
            segmentsConfig.setReplicasPerPartition(String.valueOf(configMinReplication));
        }
    }
    _pinotHelixResourceManager.addTable(config);
}
Also used : SegmentsValidationAndRetentionConfig(com.linkedin.pinot.common.config.SegmentsValidationAndRetentionConfig) Summary(com.linkedin.pinot.common.restlet.swagger.Summary) HttpVerb(com.linkedin.pinot.common.restlet.swagger.HttpVerb) Paths(com.linkedin.pinot.common.restlet.swagger.Paths) Tags(com.linkedin.pinot.common.restlet.swagger.Tags)

Example 13 with Paths

use of com.linkedin.pinot.common.restlet.swagger.Paths in project pinot by linkedin.

the class PinotTenantRestletResource method toggleTenantState.

@HttpVerb("get")
@Summary("Enable, disable or drop a tenant")
@Tags({ "tenant" })
@Paths({ "/tenants/{tenantName}", "/tenants/{tenantName}/" })
private StringRepresentation toggleTenantState(@Parameter(name = "tenantName", in = "path", description = "The tenant name") String tenantName, @Parameter(name = "state", in = "query", description = "state to set for the tenant {enable|disable|drop}") String state, @Parameter(name = "type", in = "query", description = "The type of tenant, either SERVER or BROKER or NULL") String type) throws JSONException {
    Set<String> serverInstances = new HashSet<String>();
    Set<String> brokerInstances = new HashSet<String>();
    JSONObject instanceResult = new JSONObject();
    if ((type == null) || type.equalsIgnoreCase("server")) {
        serverInstances = _pinotHelixResourceManager.getAllInstancesForServerTenant(tenantName);
    }
    if ((type == null) || type.equalsIgnoreCase("broker")) {
        brokerInstances = _pinotHelixResourceManager.getAllInstancesForBrokerTenant(tenantName);
    }
    Set<String> allInstances = new HashSet<String>(serverInstances);
    allInstances.addAll(brokerInstances);
    if (StateType.DROP.name().equalsIgnoreCase(state)) {
        if (!allInstances.isEmpty()) {
            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            return new StringRepresentation("Error: Tenant " + tenantName + " has live instances, cannot be dropped.");
        }
        _pinotHelixResourceManager.deleteBrokerTenantFor(tenantName);
        _pinotHelixResourceManager.deleteOfflineServerTenantFor(tenantName);
        _pinotHelixResourceManager.deleteRealtimeServerTenantFor(tenantName);
        return new StringRepresentation("Dropped tenant " + tenantName + " successfully.");
    }
    boolean enable = StateType.ENABLE.name().equalsIgnoreCase(state) ? true : false;
    for (String instance : allInstances) {
        if (enable) {
            instanceResult.put(instance, _pinotHelixResourceManager.enableInstance(instance));
        } else {
            instanceResult.put(instance, _pinotHelixResourceManager.disableInstance(instance));
        }
    }
    return new StringRepresentation(instanceResult.toString(), MediaType.APPLICATION_JSON);
}
Also used : JSONObject(org.json.JSONObject) StringRepresentation(org.restlet.representation.StringRepresentation) HashSet(java.util.HashSet) Summary(com.linkedin.pinot.common.restlet.swagger.Summary) HttpVerb(com.linkedin.pinot.common.restlet.swagger.HttpVerb) Paths(com.linkedin.pinot.common.restlet.swagger.Paths) Tags(com.linkedin.pinot.common.restlet.swagger.Tags)

Example 14 with Paths

use of com.linkedin.pinot.common.restlet.swagger.Paths in project pinot by linkedin.

the class PinotSegmentUploadRestletResource method uploadSegment.

@HttpVerb("post")
@Summary("Uploads a segment")
@Tags({ "segment" })
@Paths({ "/segments", "/segments/" })
@Responses({ @Response(statusCode = "200", description = "The segment was successfully uploaded"), @Response(statusCode = "403", description = "Forbidden operation typically because it exceeds configured quota"), @Response(statusCode = "500", description = "There was an error when uploading the segment") })
private Representation uploadSegment(File indexDir, File dataFile, String downloadUrl) throws ConfigurationException, IOException, JSONException {
    final SegmentMetadata metadata = new SegmentMetadataImpl(indexDir);
    final File tableDir = new File(baseDataDir, metadata.getTableName());
    String tableName = metadata.getTableName();
    File segmentFile = new File(tableDir, dataFile.getName());
    OfflineTableConfig offlineTableConfig = (OfflineTableConfig) ZKMetadataProvider.getOfflineTableConfig(_pinotHelixResourceManager.getPropertyStore(), tableName);
    if (offlineTableConfig == null) {
        LOGGER.info("Missing configuration for table: {} in helix", metadata.getTableName());
        setStatus(Status.CLIENT_ERROR_NOT_FOUND);
        StringRepresentation repr = new StringRepresentation("{\"error\" : \"Missing table: " + tableName + "\"}");
        repr.setMediaType(MediaType.APPLICATION_JSON);
        return repr;
    }
    StorageQuotaChecker.QuotaCheckerResponse quotaResponse = checkStorageQuota(indexDir, metadata, offlineTableConfig);
    if (!quotaResponse.isSegmentWithinQuota) {
        // this is not an "error" hence we don't increment segment upload errors
        LOGGER.info("Rejecting segment upload for table: {}, segment: {}, reason: {}", metadata.getTableName(), metadata.getName(), quotaResponse.reason);
        setStatus(Status.CLIENT_ERROR_FORBIDDEN);
        StringRepresentation repr = new StringRepresentation("{\"error\" : \"" + quotaResponse.reason + "\"}");
        repr.setMediaType(MediaType.APPLICATION_JSON);
        return repr;
    }
    PinotResourceManagerResponse response;
    if (!isSegmentTimeValid(metadata)) {
        response = new PinotResourceManagerResponse("Invalid segment start/end time", false);
    } else {
        if (downloadUrl == null) {
            // serve the data downloading from Pinot Servers.
            if (segmentFile.exists()) {
                FileUtils.deleteQuietly(segmentFile);
            }
            FileUtils.moveFile(dataFile, segmentFile);
            downloadUrl = ControllerConf.constructDownloadUrl(tableName, dataFile.getName(), vip);
        }
        // TODO: this will read table configuration again from ZK. We should optimize that
        response = _pinotHelixResourceManager.addSegment(metadata, downloadUrl);
    }
    if (response.isSuccessful()) {
        setStatus(Status.SUCCESS_OK);
    } else {
        ControllerRestApplication.getControllerMetrics().addMeteredGlobalValue(ControllerMeter.CONTROLLER_SEGMENT_UPLOAD_ERROR, 1L);
        setStatus(Status.SERVER_ERROR_INTERNAL);
    }
    return new StringRepresentation(response.toJSON().toString());
}
Also used : SegmentMetadata(com.linkedin.pinot.common.segment.SegmentMetadata) StringRepresentation(org.restlet.representation.StringRepresentation) PinotResourceManagerResponse(com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse) SegmentMetadataImpl(com.linkedin.pinot.core.segment.index.SegmentMetadataImpl) OfflineTableConfig(com.linkedin.pinot.common.config.OfflineTableConfig) StorageQuotaChecker(com.linkedin.pinot.controller.validation.StorageQuotaChecker) File(java.io.File) Summary(com.linkedin.pinot.common.restlet.swagger.Summary) HttpVerb(com.linkedin.pinot.common.restlet.swagger.HttpVerb) Paths(com.linkedin.pinot.common.restlet.swagger.Paths) Tags(com.linkedin.pinot.common.restlet.swagger.Tags) Responses(com.linkedin.pinot.common.restlet.swagger.Responses)

Example 15 with Paths

use of com.linkedin.pinot.common.restlet.swagger.Paths in project pinot by linkedin.

the class PinotSegmentUploadRestletResource method getAllSegments.

@HttpVerb("get")
@Summary("Lists all segments")
@Tags({ "segment" })
@Paths({ "/segments", "/segments/" })
@Responses({ @Response(statusCode = "200", description = "A list of all segments for the all tables") })
private Representation getAllSegments() {
    Representation presentation;
    final JSONArray ret = new JSONArray();
    for (final File file : baseDataDir.listFiles()) {
        final String fileName = file.getName();
        if (fileName.equalsIgnoreCase("fileUploadTemp") || fileName.equalsIgnoreCase("schemasTemp")) {
            continue;
        }
        final String url = _controllerConf.generateVipUrl() + "/segments/" + fileName;
        ret.put(url);
    }
    presentation = new StringRepresentation(ret.toString());
    return presentation;
}
Also used : StringRepresentation(org.restlet.representation.StringRepresentation) JSONArray(org.json.JSONArray) StringRepresentation(org.restlet.representation.StringRepresentation) FileRepresentation(org.restlet.representation.FileRepresentation) Representation(org.restlet.representation.Representation) File(java.io.File) Summary(com.linkedin.pinot.common.restlet.swagger.Summary) HttpVerb(com.linkedin.pinot.common.restlet.swagger.HttpVerb) Paths(com.linkedin.pinot.common.restlet.swagger.Paths) Tags(com.linkedin.pinot.common.restlet.swagger.Tags) Responses(com.linkedin.pinot.common.restlet.swagger.Responses)

Aggregations

Paths (com.linkedin.pinot.common.restlet.swagger.Paths)33 HttpVerb (com.linkedin.pinot.common.restlet.swagger.HttpVerb)32 Summary (com.linkedin.pinot.common.restlet.swagger.Summary)32 Tags (com.linkedin.pinot.common.restlet.swagger.Tags)31 StringRepresentation (org.restlet.representation.StringRepresentation)30 Responses (com.linkedin.pinot.common.restlet.swagger.Responses)14 JSONObject (org.json.JSONObject)10 JSONArray (org.json.JSONArray)9 AbstractTableConfig (com.linkedin.pinot.common.config.AbstractTableConfig)7 Schema (com.linkedin.pinot.common.data.Schema)5 PinotResourceManagerResponse (com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse)5 File (java.io.File)5 IOException (java.io.IOException)4 JSONException (org.json.JSONException)4 FileRepresentation (org.restlet.representation.FileRepresentation)3 Representation (org.restlet.representation.Representation)3 Description (com.linkedin.pinot.common.restlet.swagger.Description)2 TreeSet (java.util.TreeSet)2 JSONArray (com.alibaba.fastjson.JSONArray)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1