All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy