Search in sources :

Example 1 with PinotResourceManagerResponse

use of com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse in project pinot by linkedin.

the class PinotSegmentRestletResource method toggleSegmentState.

/**
   * Handler to toggle state of segment for a given table.
   *
   * @param tableName: External name for the table
   * @param segmentName: Segment to set the state for
   * @param state: Value of state to set
   * @param tableType: Offline or realtime
   * @return
   * @throws JsonProcessingException
   * @throws JSONException
   */
protected Representation toggleSegmentState(String tableName, String segmentName, String state, String tableType) throws JsonProcessingException, JSONException {
    JSONArray ret = new JSONArray();
    List<String> segmentsToToggle = new ArrayList<>();
    String offlineTableName = TableNameBuilder.OFFLINE_TABLE_NAME_BUILDER.forTable(tableName);
    String realtimeTableName = TableNameBuilder.REALTIME_TABLE_NAME_BUILDER.forTable(tableName);
    String tableNameWithType = "";
    List<String> realtimeSegments = _pinotHelixResourceManager.getAllSegmentsForResource(realtimeTableName);
    List<String> offlineSegments = _pinotHelixResourceManager.getAllSegmentsForResource(offlineTableName);
    if (tableType == null) {
        PinotResourceManagerResponse responseRealtime = toggleSegmentsForTable(realtimeSegments, realtimeTableName, segmentName, state);
        PinotResourceManagerResponse responseOffline = toggleSegmentsForTable(offlineSegments, offlineTableName, segmentName, state);
        setStatus(responseRealtime.isSuccessful() && responseOffline.isSuccessful() ? Status.SUCCESS_OK : Status.SERVER_ERROR_INTERNAL);
        List<PinotResourceManagerResponse> responses = new ArrayList<>();
        responses.add(responseRealtime);
        responses.add(responseOffline);
        ret.put(responses);
        return new StringRepresentation(ret.toString());
    } else if (TableType.REALTIME.name().equalsIgnoreCase(tableType)) {
        if (_pinotHelixResourceManager.hasRealtimeTable(tableName)) {
            tableNameWithType = realtimeTableName;
            if (segmentName != null) {
                segmentsToToggle = Collections.singletonList(segmentName);
            } else {
                segmentsToToggle.addAll(realtimeSegments);
            }
        } else {
            throw new UnsupportedOperationException("There is no realtime table for " + tableName);
        }
    } else {
        if (_pinotHelixResourceManager.hasOfflineTable(tableName)) {
            tableNameWithType = offlineTableName;
            if (segmentName != null) {
                segmentsToToggle = Collections.singletonList(segmentName);
            } else {
                segmentsToToggle.addAll(offlineSegments);
            }
        } else {
            throw new UnsupportedOperationException("There is no offline table for " + tableName);
        }
    }
    PinotResourceManagerResponse resourceManagerResponse = toggleSegmentsForTable(segmentsToToggle, tableNameWithType, segmentName, state);
    setStatus(resourceManagerResponse.isSuccessful() ? Status.SUCCESS_OK : Status.SERVER_ERROR_INTERNAL);
    ret.put(resourceManagerResponse);
    return new StringRepresentation(ret.toString());
}
Also used : StringRepresentation(org.restlet.representation.StringRepresentation) PinotResourceManagerResponse(com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse) JSONArray(org.json.JSONArray) ArrayList(java.util.ArrayList)

Example 2 with PinotResourceManagerResponse

use of com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse 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 3 with PinotResourceManagerResponse

use of com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse in project pinot by linkedin.

the class PinotInstanceRestletResource method addInstance.

@HttpVerb("post")
@Summary("Adds an instance")
@Tags({ "instance" })
@Paths({ "/instances", "/instances/" })
@Responses({ @Response(statusCode = "200", description = "The instance was created successfully"), @Response(statusCode = "409", description = "The instance already exists and no action was taken"), @Response(statusCode = "500", description = "Failed to create the instance") })
private StringRepresentation addInstance(@Parameter(name = "instance", in = "body", description = "The instance to add", required = true) Instance instance) throws JSONException {
    StringRepresentation presentation;
    LOGGER.info("Instance creation request received for instance " + instance.toInstanceId());
    final PinotResourceManagerResponse resp = _pinotHelixResourceManager.addInstance(instance);
    if (resp.status == PinotResourceManagerResponse.ResponseStatus.failure) {
        setStatus(Status.CLIENT_ERROR_CONFLICT);
    }
    presentation = new StringRepresentation(resp.toJSON().toString());
    return presentation;
}
Also used : StringRepresentation(org.restlet.representation.StringRepresentation) PinotResourceManagerResponse(com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse) 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 4 with PinotResourceManagerResponse

use of com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse in project pinot by linkedin.

the class PinotTenantRestletResource method updateTenant.

@HttpVerb("put")
@Summary("Updates a tenant")
@Tags({ "tenant" })
@Paths({ "/tenants", "/tenants/" })
private StringRepresentation updateTenant(Tenant tenant) {
    PinotResourceManagerResponse response;
    StringRepresentation presentation;
    switch(tenant.getTenantRole()) {
        case BROKER:
            response = _pinotHelixResourceManager.updateBrokerTenant(tenant);
            presentation = new StringRepresentation(response.toString());
            break;
        case SERVER:
            response = _pinotHelixResourceManager.updateServerTenant(tenant);
            presentation = new StringRepresentation(response.toString());
            break;
        default:
            throw new RuntimeException("Not a valid tenant update call");
    }
    return presentation;
}
Also used : StringRepresentation(org.restlet.representation.StringRepresentation) PinotResourceManagerResponse(com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse) 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 5 with PinotResourceManagerResponse

use of com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse in project pinot by linkedin.

the class PinotTenantRestletResource method deleteTenant.

@HttpVerb("delete")
@Summary("Deletes a tenant")
@Tags({ "tenant" })
@Description("Deletes a tenant from the cluster")
@Paths({ "/tenants/{tenantName}", "/tenants/{tenantName}/" })
private StringRepresentation deleteTenant(@Parameter(name = "tenantName", in = "path", description = "The tenant id") String tenantName, @Parameter(name = "type", in = "query", description = "The type of tenant, either SERVER or BROKER", required = true) String type) {
    StringRepresentation presentation;
    if (type == null) {
        presentation = new StringRepresentation("Not specify the type for the tenant name. Please try to append:" + "/?type=SERVER or /?type=BROKER ");
    } else {
        TenantRole tenantRole = TenantRole.valueOf(type.toUpperCase());
        PinotResourceManagerResponse res = null;
        switch(tenantRole) {
            case BROKER:
                if (_pinotHelixResourceManager.isBrokerTenantDeletable(tenantName)) {
                    res = _pinotHelixResourceManager.deleteBrokerTenantFor(tenantName);
                } else {
                    res = new PinotResourceManagerResponse();
                    res.status = ResponseStatus.failure;
                    res.message = "Broker Tenant is not null, cannot delete it.";
                }
                break;
            case SERVER:
                if (_pinotHelixResourceManager.isServerTenantDeletable(tenantName)) {
                    res = _pinotHelixResourceManager.deleteOfflineServerTenantFor(tenantName);
                    if (res.isSuccessful()) {
                        res = _pinotHelixResourceManager.deleteRealtimeServerTenantFor(tenantName);
                    }
                } else {
                    res = new PinotResourceManagerResponse();
                    res.status = ResponseStatus.failure;
                    res.message = "Server Tenant is not null, cannot delete it.";
                }
                break;
            default:
                break;
        }
        presentation = new StringRepresentation(res.toString());
    }
    return presentation;
}
Also used : StringRepresentation(org.restlet.representation.StringRepresentation) TenantRole(com.linkedin.pinot.common.utils.TenantRole) PinotResourceManagerResponse(com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse) Description(com.linkedin.pinot.common.restlet.swagger.Description) 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)

Aggregations

PinotResourceManagerResponse (com.linkedin.pinot.controller.helix.core.PinotResourceManagerResponse)6 StringRepresentation (org.restlet.representation.StringRepresentation)6 HttpVerb (com.linkedin.pinot.common.restlet.swagger.HttpVerb)5 Paths (com.linkedin.pinot.common.restlet.swagger.Paths)5 Summary (com.linkedin.pinot.common.restlet.swagger.Summary)5 Tags (com.linkedin.pinot.common.restlet.swagger.Tags)5 Responses (com.linkedin.pinot.common.restlet.swagger.Responses)2 OfflineTableConfig (com.linkedin.pinot.common.config.OfflineTableConfig)1 Description (com.linkedin.pinot.common.restlet.swagger.Description)1 SegmentMetadata (com.linkedin.pinot.common.segment.SegmentMetadata)1 TenantRole (com.linkedin.pinot.common.utils.TenantRole)1 StorageQuotaChecker (com.linkedin.pinot.controller.validation.StorageQuotaChecker)1 SegmentMetadataImpl (com.linkedin.pinot.core.segment.index.SegmentMetadataImpl)1 File (java.io.File)1 ArrayList (java.util.ArrayList)1 JSONArray (org.json.JSONArray)1