/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed 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. */ package com.linkedin.pinot.server.realtime; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import org.apache.commons.httpclient.methods.multipart.PartSource; import org.apache.commons.httpclient.params.HttpMethodParams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.linkedin.pinot.common.protocols.SegmentCompletionProtocol; /** * A class that handles sending segment completion protocol requests to the controller and getting * back responses */ public class ServerSegmentCompletionProtocolHandler { private static Logger LOGGER = LoggerFactory.getLogger(ServerSegmentCompletionProtocolHandler.class); private final String _instanceId; public ServerSegmentCompletionProtocolHandler(String instanceId) { _instanceId = instanceId; } public SegmentCompletionProtocol.Response segmentCommit(long offset, final String segmentName, final File segmentTarFile) throws FileNotFoundException { SegmentCompletionProtocol.Request.Params params = new SegmentCompletionProtocol.Request.Params(); params.withInstanceId(_instanceId).withOffset(offset).withSegmentName(segmentName); SegmentCompletionProtocol.SegmentCommitRequest request = new SegmentCompletionProtocol.SegmentCommitRequest(params); final InputStream inputStream = new FileInputStream(segmentTarFile); Part[] parts = { new FilePart(segmentName, new PartSource() { @Override public long getLength() { return segmentTarFile.length(); } @Override public String getFileName() { return "fileName"; } @Override public InputStream createInputStream() throws IOException { return new BufferedInputStream(inputStream); } }) }; return doHttp(request, parts); } public SegmentCompletionProtocol.Response extendBuildTime(SegmentCompletionProtocol.Request.Params params) { params.withInstanceId(_instanceId); SegmentCompletionProtocol.ExtendBuildTimeRequest request = new SegmentCompletionProtocol.ExtendBuildTimeRequest(params); return doHttp(request, null); } public SegmentCompletionProtocol.Response segmentConsumed(SegmentCompletionProtocol.Request.Params params) { params.withInstanceId(_instanceId); SegmentCompletionProtocol.SegmentConsumedRequest request = new SegmentCompletionProtocol.SegmentConsumedRequest(params); return doHttp(request, null); } public SegmentCompletionProtocol.Response segmentStoppedConsuming(SegmentCompletionProtocol.Request.Params params) { params.withInstanceId(_instanceId); SegmentCompletionProtocol.SegmentStoppedConsuming request = new SegmentCompletionProtocol.SegmentStoppedConsuming(params); return doHttp(request, null); } private SegmentCompletionProtocol.Response doHttp(SegmentCompletionProtocol.Request request, Part[] parts) { SegmentCompletionProtocol.Response response = SegmentCompletionProtocol.RESP_NOT_SENT; HttpClient httpClient = new HttpClient(); ControllerLeaderLocator leaderLocator = ControllerLeaderLocator.getInstance(); final String leaderAddress = leaderLocator.getControllerLeader(); if (leaderAddress == null) { LOGGER.error("No leader found {}", this.toString()); return SegmentCompletionProtocol.RESP_NOT_LEADER; } final String url = request.getUrl(leaderAddress); HttpMethodBase method; if (parts != null) { PostMethod postMethod = new PostMethod(url); postMethod.setRequestEntity(new MultipartRequestEntity(parts, new HttpMethodParams())); method = postMethod; } else { method = new GetMethod(url); } LOGGER.info("Sending request {} for {}", url, this.toString()); try { int responseCode = httpClient.executeMethod(method); if (responseCode >= 300) { LOGGER.error("Bad controller response code {} for {}", responseCode, this.toString()); return response; } else { response = new SegmentCompletionProtocol.Response(method.getResponseBodyAsString()); LOGGER.info("Controller response {} for {}", response.toJsonString(), this.toString()); if (response.getStatus().equals(SegmentCompletionProtocol.ControllerResponseStatus.NOT_LEADER)) { leaderLocator.refreshControllerLeader(); } return response; } } catch (IOException e) { LOGGER.error("IOException {}", this.toString(), e); leaderLocator.refreshControllerLeader(); return response; } } }