com.microsoft.azure.documentdb.internal.directconnectivity.ConsistencyReader Maven / Gradle / Ivy
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
*/
package com.microsoft.azure.documentdb.internal.directconnectivity;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.microsoft.azure.documentdb.DocumentClientException;
import com.microsoft.azure.documentdb.internal.AuthorizationTokenProvider;
import com.microsoft.azure.documentdb.ClientSideRequestStatistics;
import com.microsoft.azure.documentdb.internal.DatabaseAccountConfigurationProvider;
import com.microsoft.azure.documentdb.internal.DocumentServiceRequest;
import com.microsoft.azure.documentdb.internal.HttpConstants;
import com.microsoft.azure.documentdb.internal.RequestChargeTracker;
import com.microsoft.azure.documentdb.internal.SessionContainer;
/**
* Used internally to provides store reading functionality for all consistency levels in the Azure Cosmos DB database service.
*/
public class ConsistencyReader {
private static Logger logger = LoggerFactory.getLogger(ConsistencyReader.class);
private StoreReader storeReader;
private DatabaseAccountConfigurationProvider databaseAccountConfigurationProvider;
private QuorumReader quorumReader;
private AuthorizationTokenProvider authorizationTokenProvider;
public ConsistencyReader(GlobalAddressResolver globalAddressResolver,
SessionContainer sessionContainer,
TransportClient transportClient,
DatabaseAccountConfigurationProvider databaseAccountConfigurationProvider,
AuthorizationTokenProvider authorizationTokenProvider,
ExecutorService executorService) {
this.databaseAccountConfigurationProvider = databaseAccountConfigurationProvider;
this.authorizationTokenProvider = authorizationTokenProvider;
this.storeReader = new StoreReader(globalAddressResolver,
transportClient, sessionContainer, executorService);
this.quorumReader = new QuorumReader(
this.storeReader,
this.authorizationTokenProvider,
this.databaseAccountConfigurationProvider);
}
public StoreResponse read(DocumentServiceRequest request) throws DocumentClientException {
if (request.getRequestChargeTracker() == null) {
request.setRequestChargeTracker(new RequestChargeTracker());
}
if (request.getClientSideRequestStatistics() == null) {
request.setClientSideRequestStatistics(new ClientSideRequestStatistics());
}
int maxReplicaCount = this.databaseAccountConfigurationProvider.getMaxReplicaSetSize();
int readQuorumValue = maxReplicaCount - (maxReplicaCount / 2);
if (request.getDefaultReplicaIndex() != null) {
return this.storeReader.readPrimary(request, false, null).toStoreResponse(null);
}
switch (RequestHelper.getConsistencyLevel(this.databaseAccountConfigurationProvider, request)) {
case Session:
return this.readSession(request);
case Eventual:
case ConsistentPrefix:
return this.readAny(request);
case BoundedStaleness:
return this.quorumReader.readBoundedStaleness(request, readQuorumValue);
case Strong:
return this.quorumReader.readStrong(request, readQuorumValue);
default:
throw new IllegalStateException("Unsupported consistency level.");
}
}
private StoreResponse readSession(DocumentServiceRequest request) throws DocumentClientException {
StoreReadResult response = this.storeReader.readSession(request);
if (response == null) {
DocumentClientException e = new DocumentClientException(HttpStatus.SC_NOT_FOUND,
new com.microsoft.azure.documentdb.Error(
String.valueOf(HttpStatus.SC_NOT_FOUND),
"The read session is not available for the input session token."),
new HashMap() {{
put(HttpConstants.HttpHeaders.SUB_STATUS,
String.valueOf(HttpConstants.SubStatusCodes.READ_SESSION_NOT_AVAILABLE));
}});
throw e;
} else if (response.getException() != null &&
response.getException().getStatusCode() == HttpConstants.StatusCodes.NOTFOUND) {
DocumentClientException dce = response.getException();
if (dce.getStatusCode() == HttpConstants.StatusCodes.NOTFOUND &&
request.getSessionToken() != null && response.getSessionToken() != null && !request.getSessionToken().isValid(response.getSessionToken())) {
logger.debug("Convert to session read exception, request {} with session token {}, response session token {}",
request.getResourceAddress(), request.getSessionToken().convertToString(), response.getSessionToken().convertToString());
dce.getResponseHeaders().put(HttpConstants.HttpHeaders.SUB_STATUS,
String.valueOf(HttpConstants.SubStatusCodes.READ_SESSION_NOT_AVAILABLE));
throw dce;
}
}
return response.toStoreResponse(request.getRequestChargeTracker());
}
private StoreResponse readAny(DocumentServiceRequest request) throws DocumentClientException {
StoreReadResult response = this.storeReader.readEventual(request);
if (response == null) {
throw new DocumentClientException(HttpStatus.SC_GONE,
"The requested resource is no longer available at the server.");
}
return response.toStoreResponse(request.getRequestChargeTracker());
}
String getLastReadAddress() {
return storeReader.getLastReadAddress();
}
void setLastReadAddress(String lastReadAddress) {
storeReader.setLastReadAddress(lastReadAddress);
}
}