Package voldemort.store.socket

Source Code of voldemort.store.socket.SocketStore

/*
* Copyright 2008-2012 LinkedIn, 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 voldemort.store.socket;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import voldemort.VoldemortException;
import voldemort.client.protocol.RequestFormat;
import voldemort.client.protocol.RequestFormatFactory;
import voldemort.server.RequestRoutingType;
import voldemort.store.AbstractStore;
import voldemort.store.NoSuchCapabilityException;
import voldemort.store.StoreCapabilityType;
import voldemort.store.StoreUtils;
import voldemort.store.UnreachableStoreException;
import voldemort.store.nonblockingstore.NonblockingStore;
import voldemort.store.nonblockingstore.NonblockingStoreCallback;
import voldemort.store.socket.clientrequest.BlockingClientRequest;
import voldemort.store.socket.clientrequest.ClientRequest;
import voldemort.store.socket.clientrequest.ClientRequestExecutor;
import voldemort.store.socket.clientrequest.ClientRequestExecutorPool;
import voldemort.store.socket.clientrequest.DeleteClientRequest;
import voldemort.store.socket.clientrequest.GetAllClientRequest;
import voldemort.store.socket.clientrequest.GetClientRequest;
import voldemort.store.socket.clientrequest.GetVersionsClientRequest;
import voldemort.store.socket.clientrequest.PutClientRequest;
import voldemort.store.stats.ClientSocketStats;
import voldemort.utils.ByteArray;
import voldemort.utils.Utils;
import voldemort.versioning.Version;
import voldemort.versioning.Versioned;

/**
* The client implementation of a socket store--translates each request into a
* network operation to be handled by the socket server on the other side.
*
* <p/>
*
* SocketStore handles both <i>blocking</i> and <i>non-blocking</i> styles of
* requesting. For non-blocking requests, SocketStore checks out a
* {@link ClientRequestExecutor} instance from the
* {@link ClientRequestExecutorPool pool} and adds an appropriate
* {@link ClientRequest request} to be processed by the NIO thread.
*/
public class SocketStore extends AbstractStore<ByteArray, byte[], byte[]> implements
        NonblockingStore {

    private final RequestFormatFactory requestFormatFactory = new RequestFormatFactory();

    private final long timeoutMs;
    private final ClientRequestExecutorPool pool;
    private final SocketDestination destination;
    private final RequestFormat requestFormat;
    private final RequestRoutingType requestRoutingType;
    private final Logger logger = Logger.getLogger(SocketStore.class);
    private final ClientSocketStats stats;

    public SocketStore(String storeName,
                       long timeoutMs,
                       SocketDestination dest,
                       ClientRequestExecutorPool pool,
                       RequestRoutingType requestRoutingType,
                       ClientSocketStats stats) {
        super(storeName);
        this.timeoutMs = timeoutMs;
        this.pool = Utils.notNull(pool);
        this.destination = dest;
        this.requestFormat = requestFormatFactory.getRequestFormat(dest.getRequestFormatType());
        this.requestRoutingType = requestRoutingType;
        this.stats = stats;
    }

    @Override
    public void submitDeleteRequest(ByteArray key,
                                    Version version,
                                    NonblockingStoreCallback callback,
                                    long timeoutMs) {
        StoreUtils.assertValidKey(key);
        DeleteClientRequest clientRequest = new DeleteClientRequest(getName(),
                                                                    requestFormat,
                                                                    requestRoutingType,
                                                                    key,
                                                                    version);
        if(logger.isDebugEnabled())
            logger.debug("DELETE keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        requestAsync(clientRequest, callback, timeoutMs, "delete");
    }

    @Override
    public void submitGetRequest(ByteArray key,
                                 byte[] transforms,
                                 NonblockingStoreCallback callback,
                                 long timeoutMs) {
        StoreUtils.assertValidKey(key);
        GetClientRequest clientRequest = new GetClientRequest(getName(),
                                                              requestFormat,
                                                              requestRoutingType,
                                                              key,
                                                              transforms);
        if(logger.isDebugEnabled())
            logger.debug("GET keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        requestAsync(clientRequest, callback, timeoutMs, "get");
    }

    @Override
    public void submitGetAllRequest(Iterable<ByteArray> keys,
                                    Map<ByteArray, byte[]> transforms,
                                    NonblockingStoreCallback callback,
                                    long timeoutMs) {
        StoreUtils.assertValidKeys(keys);
        GetAllClientRequest clientRequest = new GetAllClientRequest(getName(),
                                                                    requestFormat,
                                                                    requestRoutingType,
                                                                    keys,
                                                                    transforms);
        if(logger.isDebugEnabled())
            logger.debug("GETALL keyRef: " + System.identityHashCode(keys) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        requestAsync(clientRequest, callback, timeoutMs, "get all");
    }

    @Override
    public void submitGetVersionsRequest(ByteArray key,
                                         NonblockingStoreCallback callback,
                                         long timeoutMs) {
        StoreUtils.assertValidKey(key);
        GetVersionsClientRequest clientRequest = new GetVersionsClientRequest(getName(),
                                                                              requestFormat,
                                                                              requestRoutingType,
                                                                              key);
        if(logger.isDebugEnabled())
            logger.debug("GETVERSIONS keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        requestAsync(clientRequest, callback, timeoutMs, "get versions");
    }

    @Override
    public void submitPutRequest(ByteArray key,
                                 Versioned<byte[]> value,
                                 byte[] transforms,
                                 NonblockingStoreCallback callback,
                                 long timeoutMs) {
        StoreUtils.assertValidKey(key);
        PutClientRequest clientRequest = new PutClientRequest(getName(),
                                                              requestFormat,
                                                              requestRoutingType,
                                                              key,
                                                              value,
                                                              transforms);
        if(logger.isDebugEnabled())
            logger.debug("PUT keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        requestAsync(clientRequest, callback, timeoutMs, "put");
    }

    @Override
    public boolean delete(ByteArray key, Version version) throws VoldemortException {
        StoreUtils.assertValidKey(key);
        DeleteClientRequest clientRequest = new DeleteClientRequest(getName(),
                                                                    requestFormat,
                                                                    requestRoutingType,
                                                                    key,
                                                                    version);
        if(logger.isDebugEnabled())
            logger.debug("DELETE keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        return request(clientRequest, "delete");
    }

    @Override
    public List<Versioned<byte[]>> get(ByteArray key, byte[] transforms) throws VoldemortException {
        StoreUtils.assertValidKey(key);
        GetClientRequest clientRequest = new GetClientRequest(getName(),
                                                              requestFormat,
                                                              requestRoutingType,
                                                              key,
                                                              transforms);
        if(logger.isDebugEnabled())
            logger.debug("GET keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        return request(clientRequest, "get");
    }

    @Override
    public Map<ByteArray, List<Versioned<byte[]>>> getAll(Iterable<ByteArray> keys,
                                                          Map<ByteArray, byte[]> transforms)
            throws VoldemortException {
        StoreUtils.assertValidKeys(keys);
        GetAllClientRequest clientRequest = new GetAllClientRequest(getName(),
                                                                    requestFormat,
                                                                    requestRoutingType,
                                                                    keys,
                                                                    transforms);
        if(logger.isDebugEnabled())
            logger.debug("GETALL keyRef: " + System.identityHashCode(keys) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        return request(clientRequest, "getAll");
    }

    @Override
    public List<Version> getVersions(ByteArray key) {
        StoreUtils.assertValidKey(key);
        GetVersionsClientRequest clientRequest = new GetVersionsClientRequest(getName(),
                                                                              requestFormat,
                                                                              requestRoutingType,
                                                                              key);
        if(logger.isDebugEnabled())
            logger.debug("GETVERSIONS keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        return request(clientRequest, "getVersions");
    }

    @Override
    public void put(ByteArray key, Versioned<byte[]> versioned, byte[] transforms)
            throws VoldemortException {
        StoreUtils.assertValidKey(key);
        PutClientRequest clientRequest = new PutClientRequest(getName(),
                                                              requestFormat,
                                                              requestRoutingType,
                                                              key,
                                                              versioned,
                                                              transforms);
        if(logger.isDebugEnabled())
            logger.debug("PUT keyRef: " + System.identityHashCode(key) + " requestRef: "
                         + System.identityHashCode(clientRequest));
        request(clientRequest, "put");
    }

    @Override
    public Object getCapability(StoreCapabilityType capability) {
        if(StoreCapabilityType.SOCKET_POOL.equals(capability))
            return this.pool;
        else
            throw new NoSuchCapabilityException(capability, getName());
    }

    /**
     * This method handles submitting and then waiting for the request from the
     * server. It uses the ClientRequest API to actually write the request and
     * then read back the response. This implementation will block for a
     * response from the server.
     *
     * @param <T> Return type
     *
     * @param clientRequest ClientRequest implementation used to write the
     *        request and read the response
     * @param operationName Simple string representing the type of request
     *
     * @return Data returned by the individual requests
     */

    private <T> T request(ClientRequest<T> delegate, String operationName) {
        long startTimeMs = -1;
        long startTimeNs = -1;

        if(logger.isDebugEnabled()) {
            startTimeMs = System.currentTimeMillis();
        }
        ClientRequestExecutor clientRequestExecutor = pool.checkout(destination);
        String debugMsgStr = "";

        startTimeNs = System.nanoTime();

        BlockingClientRequest<T> blockingClientRequest = null;
        try {
            blockingClientRequest = new BlockingClientRequest<T>(delegate, timeoutMs);
            clientRequestExecutor.addClientRequest(blockingClientRequest,
                                                   timeoutMs,
                                                   System.nanoTime() - startTimeNs);

            boolean awaitResult = blockingClientRequest.await();

            if(awaitResult == false) {
                blockingClientRequest.timeOut();
            }

            if(logger.isDebugEnabled())
                debugMsgStr += "success";

            return blockingClientRequest.getResult();
        } catch(InterruptedException e) {

            if(logger.isDebugEnabled())
                debugMsgStr += "unreachable: " + e.getMessage();

            throw new UnreachableStoreException("Failure in " + operationName + " on "
                                                + destination + ": " + e.getMessage(), e);
        } catch(IOException e) {
            clientRequestExecutor.close();

            if(logger.isDebugEnabled())
                debugMsgStr += "failure: " + e.getMessage();

            throw new UnreachableStoreException("Failure in " + operationName + " on "
                                                + destination + ": " + e.getMessage(), e);
        } finally {
            if(blockingClientRequest != null && !blockingClientRequest.isComplete()) {
                // close the executor if we timed out
                clientRequestExecutor.close();
            }
            // Record operation time
            long opTimeNs = Utils.elapsedTimeNs(startTimeNs, System.nanoTime());
            if (stats != null) {
                stats.recordSyncOpTimeNs(destination, opTimeNs);
            }
            if(logger.isDebugEnabled()) {
                logger.debug("Sync request end, type: "
                             + operationName
                             + " requestRef: "
                             + System.identityHashCode(delegate)
                             + " totalTimeNs: "
                             + opTimeNs
                             + " start time: "
                             + startTimeMs
                             + " end time: "
                             + System.currentTimeMillis()
                             + " client:"
                             + clientRequestExecutor.getSocketChannel().socket().getLocalAddress()
                             + ":"
                             + clientRequestExecutor.getSocketChannel().socket().getLocalPort()
                             + " server: "
                             + clientRequestExecutor.getSocketChannel()
                                                    .socket()
                                                    .getRemoteSocketAddress() + " outcome: "
                             + debugMsgStr);
            }

            pool.checkin(destination, clientRequestExecutor);
        }
    }

    /**
     * This method handles submitting and then waiting for the request from the
     * server. It uses the ClientRequest API to actually write the request and
     * then read back the response. This implementation will not block for a
     * response from the server.
     *
     * @param <T> Return type
     *
     * @param clientRequest ClientRequest implementation used to write the
     *        request and read the response
     * @param operationName Simple string representing the type of request
     *
     * @return Data returned by the individual requests
     */

    private <T> void requestAsync(ClientRequest<T> delegate,
                                  NonblockingStoreCallback callback,
                                  long timeoutMs,
                                  String operationName) {
        pool.submitAsync(this.destination, delegate, callback, timeoutMs, operationName);
    }
}
TOP

Related Classes of voldemort.store.socket.SocketStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.