/* * Copyright 2013 Jive Software, Inc * * 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.jivesoftware.os.amza.service.replication.http; import com.fasterxml.jackson.databind.ObjectMapper; import com.jivesoftware.os.amza.api.AmzaInterner; import com.jivesoftware.os.amza.api.ring.RingHost; import com.jivesoftware.os.amza.api.ring.RingMember; import com.jivesoftware.os.amza.api.ring.TimestampedRingHost; import com.jivesoftware.os.amza.service.take.AvailableRowsTaker; import com.jivesoftware.os.amza.service.take.StreamingTakesConsumer; import com.jivesoftware.os.mlogger.core.MetricLogger; import com.jivesoftware.os.mlogger.core.MetricLoggerFactory; import com.jivesoftware.os.routing.bird.http.client.ConnectionDescriptorSelectiveStrategy; import com.jivesoftware.os.routing.bird.http.client.HttpStreamResponse; import com.jivesoftware.os.routing.bird.http.client.NonSuccessStatusCodeException; import com.jivesoftware.os.routing.bird.http.client.TenantAwareHttpClient; import com.jivesoftware.os.routing.bird.shared.ClientCall.ClientResponse; import com.jivesoftware.os.routing.bird.shared.HostPort; import java.io.BufferedInputStream; import java.io.DataInputStream; import org.xerial.snappy.SnappyInputStream; public class HttpAvailableRowsTaker implements AvailableRowsTaker { private static final MetricLogger LOG = MetricLoggerFactory.getLogger(); private final TenantAwareHttpClient<String> ringClient; private final StreamingTakesConsumer streamingTakesConsumer; private final ObjectMapper mapper; public HttpAvailableRowsTaker(TenantAwareHttpClient<String> ringClient, AmzaInterner amzaInterner, ObjectMapper mapper) { this.ringClient = ringClient; this.streamingTakesConsumer = new StreamingTakesConsumer(amzaInterner); this.mapper = mapper; } @Override public void availableRowsStream(RingMember localRingMember, TimestampedRingHost localTimestampedRingHost, RingMember remoteRingMember, RingHost remoteRingHost, boolean system, long takeSessionId, long takeSharedKey, long timeoutMillis, AvailableStream availableStream, PingStream pingStream) throws Exception { String endpoint = "/amza/rows/available" + "/" + localRingMember.getMember() + "/" + localTimestampedRingHost.ringHost.toCanonicalString() + "/" + system + "/" + localTimestampedRingHost.timestampId + "/" + takeSessionId + "/" + timeoutMillis; String sharedKeyJson = mapper.writeValueAsString(takeSharedKey); // lame HttpStreamResponse httpStreamResponse = ringClient.call("", new ConnectionDescriptorSelectiveStrategy(new HostPort[] { new HostPort(remoteRingHost.getHost(), remoteRingHost.getPort()) }), "availableRowsStream", httpClient -> { HttpStreamResponse response = httpClient.streamingPost(endpoint, sharedKeyJson, null); if (response.getStatusCode() < 200 || response.getStatusCode() >= 300) { throw new NonSuccessStatusCodeException(response.getStatusCode(), response.getStatusReasonPhrase()); } return new ClientResponse<>(response, true); }); try { BufferedInputStream bis = new BufferedInputStream(httpStreamResponse.getInputStream(), 8192); // TODO config?? DataInputStream dis = new DataInputStream(new SnappyInputStream(bis)); streamingTakesConsumer.consume(dis, availableStream, pingStream); } finally { httpStreamResponse.close(); } } }